Skip to content

v2.0 - Anthropic API Release

Choose a tag to compare

@jwadow jwadow released this 11 Jan 04:26
· 109 commits to main since this release

A major architectural overhaul transforming Kiro Gateway from an OpenAI-only proxy into a universal API gateway supporting both OpenAI and Anthropic protocols. This release introduces a new unified core layer, dynamic model resolution, and significant reliability improvements for authentication and tool handling.

💥 Breaking Changes

Project Renamed: kiro-openai-gatewaykiro-gateway

The project has been restructured to reflect its new multi-API nature:

Before After
from kiro_gateway import ... from kiro import ...
kiro_gateway/routes.py kiro/routes_openai.py
kiro_gateway/streaming.py kiro/streaming_openai.py
kiro_gateway/converters.py kiro/converters_openai.py

Migration: Update all imports from kiro_gateway to kiro. OpenAI-specific modules now have _openai suffix.

Static Model Mapping Removed

The hardcoded MODEL_MAPPING and AVAILABLE_MODELS in config.py have been replaced with dynamic model resolution. Models are now fetched from Kiro API at startup and cached.

Impact: If you were relying on specific model aliases, they should still work due to the new normalization system.

✨ New Features

Anthropic Messages API Support (#15)

Full native support for the Anthropic Messages API at /v1/messages endpoint:

  • Complete protocol compatibility — Use the official Anthropic Python SDK or any Anthropic-compatible tool
  • Streaming support — Full SSE streaming with proper event types (message_start, content_block_delta, message_stop)
  • Tool calling — Native tool_use and tool_result content blocks
  • Extended thinking — Thinking content blocks for reasoning visibility
import anthropic

client = anthropic.Anthropic(
    api_key="your-proxy-key",
    base_url="http://localhost:8000"
)

response = client.messages.create(
    model="claude-sonnet-4-5",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Hello!"}]
)

Image Content Blocks (#30, #32)

Vision support is here! Send images to Claude via both OpenAI and Anthropic formats:

# Anthropic format
{"type": "image", "source": {"type": "base64", "media_type": "image/jpeg", "data": "..."}}

# OpenAI format
{"type": "image_url", "image_url": {"url": "data:image/jpeg;base64,..."}}

The gateway automatically handles format conversion and data URL prefix stripping for seamless integration with any client.

Dynamic Model Resolution

Smart model name handling that accepts any format and normalizes automatically:

You Send Gateway Sends to Kiro
claude-sonnet-4-5 claude-sonnet-4.5
claude-sonnet-4.5 claude-sonnet-4.5
claude-sonnet-4-5-20250929 claude-sonnet-4.5
claude-3-7-sonnet claude-3.7-sonnet
claude-3-7-sonnet-20250219 claude-3.7-sonnet

Key principle: The gateway is a gateway, not a gatekeeper. Unknown models are passed through to Kiro API — let Kiro decide if they're valid.

Configurable Server Host and Port (#19)

New environment variables and CLI arguments for flexible deployment:

# Environment variables
SERVER_HOST=127.0.0.1 SERVER_PORT=9000 python main.py

# CLI arguments (highest priority)
python main.py --host 127.0.0.1 --port 9000
python main.py -H 0.0.0.0 -p 8080

Multi-API Core Architecture

New unified core layer (streaming_core.py, converters_core.py) that:

  • Parses Kiro API responses into API-agnostic KiroEvent objects
  • Enables consistent behavior across OpenAI and Anthropic endpoints
  • Simplifies adding support for future API formats

Shared HTTP Client with Connection Pooling (#24)

Application-level shared httpx.AsyncClient for better resource management:

  • Reduced memory usage under concurrent load
  • Connection reuse across requests
  • Proper cleanup on shutdown

🐛 Bug Fixes

AWS SSO OIDC Authentication (#14, #16, #22)

Multiple fixes for users authenticating via kiro-cli with AWS Builder ID:

  • Fixed scope parameter — No longer sent during token refresh per OAuth 2.0 RFC 6749 Section 6. AWS SSO OIDC was returning invalid_request when scope was included.
  • Detailed error logging — Now logs full error response from AWS SSO OIDC for easier debugging
  • SQLite credentials reload — Reloads credentials from SQLite before refresh attempt, catching updates from kiro-cli
  • Retry on 400 errors — If refresh fails with 400, reloads SQLite and retries once (handles kiro-cli memory-only token updates)
  • Separate SSO region — SSO region can now differ from API region for multi-region setups
  • Graceful degradation — If refresh fails but access token is still valid, continues using it with a warning

Tool Content Handling (#20, #23)

Fixes for clients like Cline/Roo that send tool-related content in various scenarios:

  • Strip tool content when no tools defined — Kiro API rejects toolResults without tools. Now automatically strips tool content from messages when request has no tools.
  • Placeholders for empty content — After stripping tool content, adds semantic placeholders ((tool use), (tool result)) to prevent empty message errors
  • Handle orphaned tool_results — When tool_result appears without preceding tool_use, strips it gracefully instead of failing

Other Fixes

  • Suppress shutdown tracebacks — Clean exit on Ctrl+C without noisy CancelledError stack traces
  • Tool results format — Properly converts tool_use_id to toolUseId for Kiro API
  • System as content blocks — Support for system prompt as content blocks (enables prompt caching)

⚡ Improvements

  • CLI improvements — Server port and host configurable via --port and --host arguments with priority: CLI > ENV > Default
  • Debug logging middleware — New DebugLoggerMiddleware captures validation errors (422) in debug logs (#31)
  • Reduced log spam — Consolidated merge_adjacent_messages logging into summary messages instead of per-message logs
  • Extended thinking content blocks — Anthropic endpoint now properly handles thinking blocks in responses

📝 Documentation

  • Added architecture documentation for Anthropic API support (#15)
  • Clarified that git is optional, added ZIP download as alternative (#27)
  • Added donation section and GitHub funding configuration
  • Improved README with supported models section at the top
  • Cleaned up test documentation — removed verbose test descriptions from tests/README.md

⚙️ Configuration

Variable Default Description
SERVER_HOST 0.0.0.0 Server bind address. Use 127.0.0.1 for local-only access
SERVER_PORT 8000 Server port number

🙏 Contributors

  • @kilhyeonjun — SQLite credentials reload for containers (#22), thinking tags fix for toolResults (#23)
  • @cniu6 — Image content block support inspiration (#26)

Full Changelog: v1.0.8...v2.0