ENGINEERING
Run Claude Code on your own OpenAI-compatible gateway
Why route Claude Code through a gateway
This isn't an announcement. It's a config change most teams running Claude Code at any scale end up making anyway.
By default, Claude Code talks directly to the vendor's API. That's fine for a single developer on a laptop. It gets uncomfortable once you have a team: every prompt and every line of code in context leaves your network with no place for you to inspect, log, or gate it. Put a gateway of your own in front of that traffic and you get four things for free:
- Data containment. Requests terminate at infrastructure you control before going upstream — the thing most compliance reviews actually ask about.
- Predictable cost. Per-team, per-key budgets instead of one shared vendor invoice nobody can attribute.
- Model swaps without touching the client. Change what's behind the gateway; every developer's Claude Code config stays untouched.
- Audit trail. Every request logged by user, by key, by team — not just "someone on the API key called the API."
These aren't hypothetical. A security team doing SOC 2 or ISO 27001 evidence collection will ask where prompts and model output land and who can read them in transit — "directly at the vendor, over TLS" is true but rarely accepted without a compensating control. A gateway you operate gives you that control: request/response logging with retention you set, egress restricted to your gateway's IP range instead of an open allowlist to a third-party API, and a place to block requests that carry secrets Claude Code's context picked up by accident (an open .env file, for instance).
The billing case shows up the moment a second developer joins. Without a gateway, cost visibility is whatever the vendor's dashboard gives you — one number per API key, not per person or team. Mint one key per developer (or CI job) through a gateway and that dashboard becomes a real cost report: who's burning tokens, on what, and whether an agent stuck in a retry loop is quietly eating a week's budget. Cap each key and the failure mode changes from "surprise invoice" to "that job hit its limit and stopped."
The model-swap case matters more over time than on day one. Point-release a new model, A/B two models across teams, or fail over to a backup provider during an outage — all of that is a change to the gateway's routing config, not a rollout to every developer's shell profile. Nobody re-exports an env var; nobody's session breaks because a rollout missed their laptop.
The two variables that matter
Claude Code already supports this. No plugin, no wrapper script, no forked binary:
export ANTHROPIC_BASE_URL="https://gateway.your-company.com"
export ANTHROPIC_AUTH_TOKEN="sk-your-gateway-key"
claude
ANTHROPIC_BASE_URL redirects every call Claude Code makes — completions, streaming, tool calls, everything — to your gateway instead of the vendor's endpoint. ANTHROPIC_AUTH_TOKEN becomes the bearer credential in the Authorization header the gateway receives. Your gateway validates that key, then signs the real upstream request with the actual vendor credential, which the developer's machine never sees. Revoke a leaked key at the gateway; the vendor credential is never exposed to rotate.
These two variables are exactly what we run in production on our own gateway — the same setup behind the api-claude-code integration.
What your gateway must speak
Claude Code expects the Anthropic Messages API surface: a /v1/messages endpoint that accepts the standard request shape (model, messages, system, max_tokens, tools, plus whatever sampling params the request sets) and returns either a single JSON message or, when the request sets "stream": true, a Server-Sent Events stream of typed chunks — message_start, repeated content_block_delta events carrying partial text or tool-input JSON, and a terminal message_stop. Tool use rides in the same stream: Claude Code sends the tool definitions on the request and reads tool-call arguments back out of content_block_delta events, so your gateway can't collapse the stream into a single response without breaking tool calls entirely.
You don't have to hand-roll any of this. LiteLLM speaks the Messages API surface out of the box, with model_group routing to whatever upstream model you point it at, per-key budgets, and per-user request logs already built in — that covers the protocol translation and the accounting. What it doesn't do for you: network placement (the gateway still needs to sit somewhere your developers and CI runners can reach and your egress rules allow), TLS termination and certificate management, and tuning the reverse proxy in front of it for the long-lived streaming connections and long tool-use turns Claude Code produces — that part is still your infrastructure to run.
Gotchas we hit in production
- Streaming must not buffer. If anything in your proxy chain buffers the SSE response before forwarding it, Claude Code's UI just hangs waiting for tokens that already arrived server-side.
- Tool-use timeouts run long. A single tool call can legitimately take over 60 seconds. Default reverse-proxy timeouts will kill the connection mid-turn — raise
proxy_read_timeoutaccordingly. - Per-key budgets aren't optional. An agent stuck in a retry loop burns tokens fast. A hard budget on the key is the difference between a bug report and a surprise invoice.
Try it on ours
Our gateway (iSol API) runs exactly this setup on sovereign infrastructure — US$ 99/month, 14-day trial.