Proxy gateway for Kiro API (Amazon Q Developer / AWS CodeWhisperer)
🇬🇧 English • 🇷🇺 Русский • 🇨🇳 中文 • 🇪🇸 Español • 🇮🇩 Indonesia • 🇧🇷 Português • 🇯🇵 日本語 • 🇰🇷 한국어
Made with ❤️ by @Jwadow
Use Claude models from Kiro with Claude Code, OpenCode, OpenClaw, Claw Code, Codex app, Cursor, Cline, Roo Code, Kilo Code, Obsidian, OpenAI SDK, LangChain, Continue and other OpenAI or Anthropic compatible tools
Models • Features • Enterprise / IdC Setup • Configuration • 💖 Sponsor
This is a Polarity fork of Jwadow/kiro-gateway, maintained at polarity-dev/kiro-gateway.
It adds support for Kiro IDE Enterprise accounts (AWS IAM Identity Center), which the upstream project does not fully cover. See Enterprise / IdC Setup for the automated installer and Fork Changes for what differs from upstream.
This repo is both the gateway and the setup kit for running Claude Code against it locally. Cloning it gets you everything you need to point Claude Code (and other AI coding tools) at your Kiro subscription.
If you have Kiro IDE or another AI coding assistant open in this repo, ask:
"Set up kiro-gateway and Claude Code for me."
In Claude Code you can also run /setup-gateway. The setup uses the current
repository directory automatically and keeps setup, gateway startup, and
verification there. It uses another path only when you explicitly name one.
When safe event streaming is available, the agent runs one long-lived process:
./setup.sh -y --aws-profile company --agent-eventsIts stdout contains only allowlisted KIRO_EVENT JSONL records, so the agent can
relay the code and URL in chat while that same process continues polling. Raw
setup/debug logs are never streamed. If safe monitoring is unavailable, enter
! ./setup.sh -y --aws-profile company directly at the Claude Code prompt. In a
normal terminal, use the same command without !.
-y accepts local installer confirmations only; it does not bypass AWS
approval. Keep the command running. It prints a Code: and URL: before opening
the browser and before polling. Compare the browser code with the terminal code
character-for-character, including case and hyphens, and choose Confirm and
continue only when they match exactly and you initiated the request. If the
code differs, is missing, or the request is unexpected, cancel it, press Ctrl+C,
and rerun setup for a fresh code. Never reuse a code from an interrupted,
denied, or expired attempt.
Add --no-browser to open the printed URL manually, --q-profile NAME_OR_ARN
when multiple Q profiles are assigned, or --port PORT for a custom first-setup
port. Wait for setup to exit successfully before starting the gateway:
python3 main.pyAt startup, an expired access token is refreshed silently. If the direct IdC
refresh token or client registration is no longer usable, a local foreground
python3 main.py starts one device-authorization flow and then continues only
after successful approval. It never loops or silently changes Q profiles.
Docker, CI, direct uvicorn main:app, non-TTY services, SQLite/Kiro CLI, and
multi-account mode never open a browser; renew credentials separately in those
contexts. Use python3 main.py --no-interactive-reauth to disable startup device
login explicitly. Agents may use --agent-events to stream only safe startup
authentication events.
The full agent contract and troubleshooting flow live in
.kiro/steering/setup.md, referenced from
CLAUDE.md and AGENTS.md.
AWS IAM Identity Center users can bootstrap the gateway without Kiro IDE or
Kiro CLI. Configure an AWS shared-config profile with sso_start_url and
sso_region (directly or through sso_session), then use the normal-terminal
command above. Keep it in the foreground and apply the same exact-code check.
With --aws-profile, setup registers a public AWS SSO OIDC client, completes
device authorization, discovers the assigned Amazon Q Developer profile through
bearer-authenticated ListAvailableProfiles, and writes refreshable owner-only
(0600) credentials to ~/.aws/sso/cache/kiro-gateway-auth.json. It stores the
SSO and Q API regions separately, generates .env, and atomically synchronizes
Claude Code and the selected gateway port.
Running without --aws-profile preserves the legacy Kiro IDE credential/log
path. Existing credential and .env files are never replaced without
confirmation; .env is backed up first.
- Python 3.10+
- an AWS shared-config IAM Identity Center profile
- an assigned Amazon Q Developer subscription/profile
- Claude Code
Code is not visible while the browser waits — cancel the request and stop
the command; never reuse that code. Agents should rerun with --agent-events
through safe event monitoring. Without it, use a visible foreground shell
(! ./setup.sh ... inside Claude Code; no ! in a normal terminal).
Repeated 401 Invalid API key from the local gateway — setup and the running
gateway may be using different checkouts, each with its own .env proxy key.
This is a local Claude-to-gateway mismatch, not an expired IAM Identity Center
token. Stop the gateway, return to the repository directory where setup was
run, rerun setup/alignment there, restart from that same path, and open a new
Claude Code session. Do not delete kiro-gateway-auth.json to fix a local 401.
Browser does not open — rerun with --no-browser, open the printed URL, and
approve only if its code exactly matches the terminal Code:.
Code differs, was denied, or expired — cancel/stop the attempt and rerun setup for a fresh code.
No Q Developer profiles — ask the AWS administrator to assign the subscription/profile and retry after propagation.
Multiple Q Developer profiles — rerun with --q-profile NAME_OR_ARN.
runtime.<region>.kiro.dev does not resolve — configure VPN_PROXY_URL in
.env.
Claude Code asks for a Claude account login — this is different from the
expected AWS IAM Identity Center approval page. Rerun setup; it configures
ANTHROPIC_AUTH_TOKEN, not ANTHROPIC_API_KEY.
setup.sh writes the Claude Code configuration to ~/.claude/settings.json, so claude works
from any terminal without exporting anything. The only recurring task is starting the gateway.
Add this to ~/.zshrc to avoid typing the path each time:
# Kiro Gateway
kiro-gateway() {
local gw_dir="$HOME/repo/kiro-gateway" # adjust to your clone location
(cd "$gw_dir" && python3 main.py)
}Then kiro-gateway starts it in the foreground; stop it with Ctrl+C. Do not add
--port or a SERVER_PORT=... assignment to the helper: main.py reads the
persisted port from this checkout's .env, so the helper automatically follows
future port changes.
.env is the persisted source of truth for the gateway port. The installer uses
the same value for the server runtime and Claude Code's ANTHROPIC_BASE_URL.
For a first setup on a custom port:
./setup.sh -y --aws-profile NAME --port 9000To change the port after setup is already complete:
./setup.sh --port 9100The existing-installation path changes only SERVER_PORT and the managed Claude
Code connection values. It reuses the current proxy token, preserves unrelated
Claude settings, and backs up .env to .env.bak.
Complete this checklist one step at a time:
- Run
./setup.sh --port <new-port>and resolve any reported zsh helper drift. - Stop the running gateway with Ctrl+C.
- Start it again with
python3 main.pyor the port-neutralkiro-gatewayhelper. - Open a new Claude Code session so it reloads
~/.claude/settings.json. - Run
./setup.sh --check-port; it must report the runtime, Claude Code, and optional zsh helper as aligned.
Do not use python3 main.py --port N for a persistent change: that is a transient
runtime override and cannot update Claude Code. Also remove any exported
SERVER_PORT from the launching shell (unset SERVER_PORT), because shell
environment variables override .env.
Why no
exportlines? Environment variables do not cross terminal sessions, so exporting them in the window running the gateway would not reach the window runningclaude. Putting them in~/.claude/settings.jsonavoids the problem and also reaches Claude Code's background agents, which shell exports do not.
If you prefer environment variables over the settings file, export these instead — but note they apply only to the shell you set them in:
export ANTHROPIC_BASE_URL="http://localhost:$(python3 scripts/manage_gateway_port.py resolve)"
export ANTHROPIC_AUTH_TOKEN="<your PROXY_API_KEY from .env>"Model discovery is enabled by setup.sh, so /model inside Claude Code lists the models your
subscription grants, labelled From gateway. To inspect them directly:
PORT=$(python3 scripts/manage_gateway_port.py resolve)
curl -s "localhost:$PORT/v1/models" -H "Authorization: Bearer $PROXY_API_KEY" \
| python3 -c "import sys,json; print('\n'.join(m['id'] for m in json.load(sys.stdin)['data']))"The synchronizer selects Kiro's auto router and maps Claude Code's virtual
Default row to Kiro Auto. Haiku remains separately selectable through its
explicit gateway row. Choose any other persistent model with /model or the
top-level model setting. Do not set ANTHROPIC_MODEL: it has higher precedence
and overrides the saved picker choice. When Kiro adds or removes models, refresh
the static local allowlist with:
python3 scripts/sync_claude_models.py syncUse --check to detect drift without writing. The user-level allowlist is local
configuration, not an administrative policy boundary.
Changes in this fork that are not yet in upstream:
setup.sh — Automated installer for Enterprise / IdC accounts, described above.
Transparent aliases for long tool names — Kiro limits tool names to 64 characters, while
MCP clients can generate longer names such as mcp__<server>__<tool>. The gateway now assigns
deterministic, request-scoped aliases only on the Kiro-facing side and restores the exact original
names in OpenAI and Anthropic responses, in both streaming and non-streaming modes. Tool IDs,
arguments, results, and short names are unchanged; MCP server names no longer need manual shortening.
Support for role: "system" in the Anthropic endpoint — Claude Code sends the system prompt
as a message inside the messages array, while the Anthropic API specifies it as a separate
top-level system field. Upstream rejects these requests with an HTTP 422 validation error.
This fork accepts them:
kiro/models_anthropic.py—AnthropicMessage.roleaccepts"system"alongside"user"and"assistant"kiro/converters_anthropic.py—build_kiro_payload_anthropic()filters system messages out of the array and merges their text into the system prompt before building the Kiro payload
Note: this change currently covers the Anthropic endpoint only. Upstream's contribution guidelines require feature parity across both the OpenAI and Anthropic surfaces plus test coverage for streaming and non-streaming paths, so it is not yet suitable for a pull request.
git fetch upstream
git merge upstream/mainExpect conflicts in kiro/models_anthropic.py and kiro/converters_anthropic.py, since both
carry fork-specific changes.
Model availability is discovered from Kiro for the authenticated subscription and
region; this repository intentionally contains no authoritative static model list.
Inspect the current gateway catalog with authenticated GET /v1/models, or run
python3 scripts/sync_claude_models.py sync to refresh Claude Code's picker.
Non-Claude Kiro IDs are exposed through reversible claude-kiro-<length>-...
rows, then decoded back to their raw Kiro modelId before inference.
| Feature | Description |
|---|---|
| 🔌 OpenAI-compatible API | Works with any OpenAI-compatible tool |
| 🔌 Anthropic-compatible API | Native /v1/messages endpoint |
| 🔀 Multi-Account Support | Intelligent failover between multiple accounts |
| 🌐 VPN/Proxy Support | HTTP/SOCKS5 proxy for restricted networks |
| 🧠 Extended Thinking | Reasoning is exclusive to our project |
| 👁️ Vision Support | Send images to model |
| 🔍 Web Search | Search the web for current information |
| 🛠️ Tool Calling | Supports function calling |
| 💬 Full message history | Passes complete conversation context |
| 📡 Streaming | Full SSE streaming support |
| 🔄 Retry Logic | Automatic retries on errors (403, 429, 5xx) |
| 📋 Extended model list | Including versioned models |
| 🔐 Smart token management | Automatic refresh before expiration |
IAM Identity Center users: prefer the automated Enterprise / IdC Setup above. The methods below reuse credentials managed by Kiro IDE/Kiro CLI or configure credential sources manually; they are retained for compatibility.
Choose your deployment method:
- 🐍 Native Python - Full control, easy debugging
- 🐳 Docker - Isolated environment, easy deployment → jump to Docker
- Python 3.10+
- One of the following:
# Clone the repository (requires Git)
git clone https://github.com/Jwadow/kiro-gateway.git
cd kiro-gateway
# Or download ZIP: Code → Download ZIP → extract → open kiro-gateway folder
# Install dependencies
pip install -r requirements.txt
# Configure (see Configuration section)
cp .env.example .env
# Copy and edit .env with your credentials
# Start the server
python main.py
# Or with custom port (if 4567 is busy)
python main.py --port 9000The server will be available at http://localhost:4567
💡 Advanced users: Looking for multi-account support? See Account System below.
Specify the path to the credentials file:
Works with:
- Kiro IDE (standard) - for personal accounts
- Enterprise - for corporate accounts with SSO
KIRO_CREDS_FILE="~/.aws/sso/cache/kiro-auth-token.json"
# Password to protect YOUR proxy server (make up any secure string)
# You'll use this as api_key when connecting to your gateway
PROXY_API_KEY="my-super-secret-password-123"📄 JSON file format
{
"accessToken": "eyJ...",
"refreshToken": "eyJ...",
"expiresAt": "2025-01-12T23:00:00.000Z",
"profileArn": "arn:aws:codewhisperer:us-east-1:...",
"region": "us-east-1",
"clientIdHash": "abc123..." // Optional: for corporate SSO setups
}Note: If you have two JSON files in
~/.aws/sso/cache/(e.g.,kiro-auth-token.jsonand a file with a hash name), usekiro-auth-token.jsoninKIRO_CREDS_FILE. The gateway will automatically load the other file.
Create a .env file in the project root:
# Required
REFRESH_TOKEN="your_kiro_refresh_token"
# Password to protect YOUR proxy server (make up any secure string)
PROXY_API_KEY="my-super-secret-password-123"
# Optional
PROFILE_ARN="arn:aws:codewhisperer:us-east-1:..."
KIRO_REGION="us-east-1"If you use kiro-cli or Kiro IDE with AWS SSO (AWS IAM Identity Center), the gateway will automatically detect and use the appropriate authentication.
Works with both free Builder ID accounts and corporate accounts.
KIRO_CREDS_FILE="~/.aws/sso/cache/your-sso-cache-file.json"
# Password to protect YOUR proxy server
PROXY_API_KEY="my-super-secret-password-123"
# Enterprise Amazon Q requests require a profile ARN.
# Direct bootstrap discovers it automatically. For legacy credential sources
# that omit it, set PROFILE_ARN manually. Builder ID may work without one.📄 AWS SSO JSON file format
AWS SSO credentials files (from ~/.aws/sso/cache/) contain:
{
"accessToken": "eyJ...",
"refreshToken": "eyJ...",
"expiresAt": "2025-01-12T23:00:00.000Z",
"region": "us-east-1",
"clientId": "...",
"clientSecret": "..."
}Note: Direct IAM Identity Center bootstrap discovers and stores profileArn automatically. Enterprise Amazon Q requests require it; legacy AWS SSO credential sources that omit it must provide PROFILE_ARN separately. Builder ID accounts may work without an Enterprise profile ARN.
🔍 How it works
The gateway automatically detects the authentication type based on the credentials file:
-
Kiro Desktop Auth (default): Used when
clientIdandclientSecretare NOT present- Endpoint:
https://prod.{region}.auth.desktop.kiro.dev/refreshToken
- Endpoint:
-
AWS SSO (OIDC): Used when
clientIdandclientSecretARE present- Endpoint:
https://oidc.{region}.amazonaws.com/token
- Endpoint:
No additional configuration is needed — just point to your credentials file!
If you use kiro-cli and prefer to use its SQLite database directly:
KIRO_CLI_DB_FILE="~/.local/share/kiro-cli/data.sqlite3"
# Password to protect YOUR proxy server
PROXY_API_KEY="my-super-secret-password-123"
# Enterprise Amazon Q requests require a profile ARN.
# Direct bootstrap discovers it automatically. For legacy credential sources
# that omit it, set PROFILE_ARN manually. Builder ID may work without one.📄 Database locations
| CLI Tool | Database Path |
|---|---|
| kiro-cli | ~/.local/share/kiro-cli/data.sqlite3 |
| amazon-q-developer-cli | ~/.local/share/amazon-q/data.sqlite3 |
The gateway reads credentials from the auth_kv table which stores:
kirocli:odic:tokenorcodewhisperer:odic:token— access token, refresh token, expirationkirocli:odic:device-registrationorcodewhisperer:odic:device-registration— client ID and secret
Both key formats are supported for compatibility with different kiro-cli versions.
For Kiro IDE users:
- Log in to Kiro IDE and use Option 1 above (JSON credentials file)
- The credentials file is created automatically after login
For Kiro CLI users:
- Log in with
kiro-cli loginand use Option 3 or Option 4 above - No manual token extraction needed!
🔧 Advanced: Manual token extraction
If you need to manually extract the refresh token (e.g., for debugging), you can intercept Kiro IDE traffic:
- Look for requests to:
prod.us-east-1.auth.desktop.kiro.dev/refreshToken
Account System is a way to manage multiple Kiro accounts with automatic failover. In the future, this system will replace .env file for credential configuration, but currently it's optional and intended for those who want to use multiple accounts.
If you have multiple Kiro accounts, the gateway can automatically switch between them when account is temporarily unavailable.
The system works with a single account too — just without switching.
Add to your .env:
ACCOUNT_SYSTEM=trueWhat happens:
- On first startup, your credentials from
.envare automatically migrated tocredentials.json(one-time) - After that, all account and region settings from
.envare ignored - Account management only through
credentials.json
📄 Configuration Examples
Single account:
[
{
"type": "json",
"path": "~/.aws/sso/cache/kiro-auth-token.json"
}
]Multiple accounts:
[
{
"type": "json",
"path": "~/.aws/sso/cache/kiro-auth-token.json"
},
{
"type": "sqlite",
"path": "~/.local/share/kiro-cli/data.sqlite3"
},
{
"type": "refresh_token",
"refresh_token": "eyJhbGc...",
"profile_arn": "arn:aws:codewhisperer:us-east-1:..."
}
]Folder with files:
[
{
"type": "json",
"path": "C:\\MyAccs\\kiro67"
}
]The gateway will scan all files in the folder and add them as separate accounts.
When one account returns an error (429 rate limit, 402 quota exceeded), the gateway automatically tries the next account from the list. If an account fails several times in a row, the gateway temporarily stops using it and periodically checks if it has recovered.
For a single account, failover doesn't work — you get the original error from Kiro API.
For complete configuration examples (including per-account region settings), see credentials.json.example.
Docker-based deployment. Prefer native Python? See Enterprise / IdC Setup above.
# 1. Clone and configure
git clone https://github.com/Jwadow/kiro-gateway.git
cd kiro-gateway
cp .env.example .env
# Edit .env with your credentials
# 2. Run with docker-compose
docker-compose up -d
# 3. Check status
docker-compose logs -f
curl http://localhost:4567/health🔹 Using Environment Variables
docker run -d \
-p 4567:4567 \
-e PROXY_API_KEY="my-super-secret-password-123" \
-e REFRESH_TOKEN="your_refresh_token" \
--name kiro-gateway \
ghcr.io/jwadow/kiro-gateway:latest🔹 Using Credentials File
Linux/macOS:
docker run -d \
-p 4567:4567 \
-v ~/.aws/sso/cache:/home/kiro/.aws/sso/cache:ro \
-e KIRO_CREDS_FILE=/home/kiro/.aws/sso/cache/kiro-auth-token.json \
-e PROXY_API_KEY="my-super-secret-password-123" \
--name kiro-gateway \
ghcr.io/jwadow/kiro-gateway:latestWindows (PowerShell):
docker run -d `
-p 4567:4567 `
-v ${HOME}/.aws/sso/cache:/home/kiro/.aws/sso/cache:ro `
-e KIRO_CREDS_FILE=/home/kiro/.aws/sso/cache/kiro-auth-token.json `
-e PROXY_API_KEY="my-super-secret-password-123" `
--name kiro-gateway `
ghcr.io/jwadow/kiro-gateway:latest🔹 Using .env File
docker run -d -p 4567:4567 --env-file .env --name kiro-gateway ghcr.io/jwadow/kiro-gateway:latestEdit docker-compose.yml and uncomment volume mounts for your OS:
volumes:
# Kiro IDE credentials (choose your OS)
- ~/.aws/sso/cache:/home/kiro/.aws/sso/cache:ro # Linux/macOS
# - ${USERPROFILE}/.aws/sso/cache:/home/kiro/.aws/sso/cache:ro # Windows
# kiro-cli database (choose your OS)
- ~/.local/share/kiro-cli:/home/kiro/.local/share/kiro-cli # Linux/macOS
# - ${USERPROFILE}/.local/share/kiro-cli:/home/kiro/.local/share/kiro-cli # Windows
# Debug logs (optional)
- ./debug_logs:/app/debug_logsdocker-compose logs -f # View logs
docker-compose restart # Restart
docker-compose down # Stop
docker-compose pull && docker-compose up -d # Update🔧 Building from Source
docker build -t kiro-gateway .
docker run -d -p 4567:4567 --env-file .env kiro-gatewayFor users in China, corporate networks, or regions with connectivity issues to AWS services.
The gateway supports routing all Kiro API requests through a VPN or proxy server. This is essential if you experience connection problems to AWS endpoints or need to use a corporate proxy.
Add to your .env file:
# HTTP proxy
VPN_PROXY_URL=http://127.0.0.1:7890
# SOCKS5 proxy
VPN_PROXY_URL=socks5://127.0.0.1:1080
# With authentication (corporate proxies)
VPN_PROXY_URL=http://username:password@proxy.company.com:8080
# Without protocol (defaults to http://)
VPN_PROXY_URL=192.168.1.100:8080- ✅ HTTP — Standard proxy protocol
- ✅ HTTPS — Secure proxy connections
- ✅ SOCKS5 — Advanced proxy protocol (common in VPN software)
- ✅ Authentication — Username/password embedded in URL
| Situation | Solution |
|---|---|
| Connection timeouts to AWS | Use VPN/proxy to route traffic |
| Corporate network restrictions | Configure your company's proxy |
| Regional connectivity issues | Use a VPN service with proxy support |
| Privacy requirements | Route through your own proxy server |
Most VPN clients provide a local proxy server you can use:
- Sing-box — Modern VPN client with HTTP/SOCKS5 proxy
- Clash — Usually runs on
http://127.0.0.1:7890 - V2Ray — Configurable SOCKS5/HTTP proxy
- Shadowsocks — SOCKS5 proxy support
- Corporate VPN — Check your IT department for proxy settings
Leave VPN_PROXY_URL empty (default) if you don't need proxy support.
| Endpoint | Method | Description |
|---|---|---|
/ |
GET | Health check |
/health |
GET | Detailed health check |
/v1/models |
GET | List available models |
/v1/chat/completions |
POST | OpenAI Chat Completions API |
/v1/messages |
POST | Anthropic Messages API |
🔹 Simple cURL Request
curl http://localhost:4567/v1/chat/completions \
-H "Authorization: Bearer my-super-secret-password-123" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-sonnet-4-5",
"messages": [{"role": "user", "content": "Hello!"}],
"stream": true
}'Note: Replace
my-super-secret-password-123with thePROXY_API_KEYyou set in your.envfile.
🔹 Streaming Request
curl http://localhost:4567/v1/chat/completions \
-H "Authorization: Bearer my-super-secret-password-123" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-sonnet-4-5",
"messages": [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "What is 2+2?"}
],
"stream": true
}'🛠️ With Tool Calling
curl http://localhost:4567/v1/chat/completions \
-H "Authorization: Bearer my-super-secret-password-123" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-sonnet-4-5",
"messages": [{"role": "user", "content": "What is the weather in London?"}],
"tools": [{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get weather for a location",
"parameters": {
"type": "object",
"properties": {
"location": {"type": "string", "description": "City name"}
},
"required": ["location"]
}
}
}]
}'🐍 Python OpenAI SDK
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:4567/v1",
api_key="my-super-secret-password-123" # Your PROXY_API_KEY from .env
)
response = client.chat.completions.create(
model="claude-sonnet-4-5",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Hello!"}
],
stream=True
)
for chunk in response:
if chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="")🦜 LangChain
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
base_url="http://localhost:4567/v1",
api_key="my-super-secret-password-123", # Your PROXY_API_KEY from .env
model="claude-sonnet-4-5"
)
response = llm.invoke("Hello, how are you?")
print(response.content)🔹 Simple cURL Request
curl http://localhost:4567/v1/messages \
-H "x-api-key: my-super-secret-password-123" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-sonnet-4-5",
"max_tokens": 1024,
"messages": [{"role": "user", "content": "Hello!"}]
}'Note: Anthropic API uses
x-api-keyheader instead ofAuthorization: Bearer. Both are supported.
🔹 With System Prompt
curl http://localhost:4567/v1/messages \
-H "x-api-key: my-super-secret-password-123" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-sonnet-4-5",
"max_tokens": 1024,
"system": "You are a helpful assistant.",
"messages": [{"role": "user", "content": "Hello!"}]
}'Note: In Anthropic API,
systemis a separate field, not a message.
📡 Streaming
curl http://localhost:4567/v1/messages \
-H "x-api-key: my-super-secret-password-123" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-sonnet-4-5",
"max_tokens": 1024,
"stream": true,
"messages": [{"role": "user", "content": "Hello!"}]
}'🐍 Python Anthropic SDK
import anthropic
client = anthropic.Anthropic(
api_key="my-super-secret-password-123", # Your PROXY_API_KEY from .env
base_url="http://localhost:4567"
)
# Non-streaming
response = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello!"}]
)
print(response.content[0].text)
# Streaming
with client.messages.stream(
model="claude-sonnet-4-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello!"}]
) as stream:
for text in stream.text_stream:
print(text, end="", flush=True)Debug logging is disabled by default. To enable, add to your .env:
# Debug logging mode:
# - off: disabled (default)
# - errors: save logs only for failed requests (4xx, 5xx) - recommended for troubleshooting
# - all: save logs for every request (overwrites on each request)
DEBUG_MODE=errors| Mode | Description | Use Case |
|---|---|---|
off |
Disabled (default) | Production |
errors |
Save logs only for failed requests (4xx, 5xx) | Recommended for troubleshooting |
all |
Save logs for every request | Development/debugging |
When enabled, requests are logged to the debug_logs/ folder:
| File | Description |
|---|---|
request_body.json |
Incoming request from client (OpenAI format) |
kiro_request_body.json |
Request sent to Kiro API |
response_stream_raw.txt |
Raw stream from Kiro |
response_stream_modified.txt |
Transformed stream (OpenAI format) |
app_logs.txt |
Application logs for the request |
error_info.json |
Error details (only on errors) |
Error: "Name or service not known" or DNS resolution failed
The Q API endpoint may not be publicly resolvable in your region. Use a VPN or proxy:
VPN_PROXY_URL=http://127.0.0.1:7890See VPN/Proxy Support for details.
Error: "503 Service Unavailable" through proxy
The Q API endpoint exists in specific regions only. Try a different region:
KIRO_API_REGION="eu-central-1" # or us-east-1Commonly reachable regions: us-east-1, eu-central-1
OIDC works but Q API fails
Your SSO region may differ from the Q API region. The gateway auto-detects this from credentials, but you can override:
KIRO_API_REGION="eu-central-1"This project is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0).
This means:
- ✅ You can use, modify, and distribute this software
- ✅ You can use it for commercial purposes
⚠️ You must disclose source code when you distribute the software⚠️ Network use is distribution — if you run a modified version on a server and let others interact with it, you must make the source code available to them⚠️ Modifications must be released under the same license
See the LICENSE file for the full license text.
AGPL-3.0 ensures that improvements to this software benefit the entire community. If you modify this gateway and deploy it as a service, you must share your improvements with your users.
By submitting a contribution to this project, you agree to the terms of our Contributor License Agreement (CLA). This ensures that:
- You have the right to submit the contribution
- You grant the maintainer rights to use and relicense your contribution
- The project remains legally protected
If this project saved you time or money, consider supporting it!
Every contribution helps keep this project alive and growing
| Currency | Network | Address |
|---|---|---|
| USDT | TRC20 | TSVtgRc9pkC1UgcbVeijBHjFmpkYHDRu26 |
| BTC | Bitcoin | 12GZqxqpcBsqJ4Vf1YreLqwoMGvzBPgJq6 |
| ETH | Ethereum | 0xc86eab3bba3bbaf4eb5b5fff8586f1460f1fd395 |
| SOL | Solana | 9amykF7KibZmdaw66a1oqYJyi75fRqgdsqnG66AK3jvh |
| TON | TON | UQBVh8T1H3GI7gd7b-_PPNnxHYYxptrcCVf3qQk5v41h3QTM |
This project is not affiliated with, endorsed by, or sponsored by Amazon Web Services (AWS), Anthropic, or Kiro IDE. Use at your own risk and in compliance with the terms of service of the underlying APIs.