Skip to content

Roll out an LLM gateway

An admin checklist for putting your own LLM gateway in front of Claude Code, from routing checks and developer keys to managed settings and upgrades.

This is the admin's runbook for putting an existing gateway product in front of Claude Code across a team. It assumes the gateway is already installed per its vendor's documentation and meets the requirements below. Developers configuring their own machine want Connect Claude Code to an LLM gateway; the full list of what Claude Code sends lives in the compatibility guide.

Before you start

You need three things:

  1. A gateway on HTTPS at its final address. Serve the exact URL you will hand out, not one that redirects. Redirects can drop the request body or strip the credential header, and model discovery treats any redirect as a failure so the credential cannot leak to the target.
  2. A provider credential for the gateway. For the Anthropic API that is a Console API key; for a cloud provider, cloud credentials with model access (see Amazon Bedrock, Google Vertex AI or Microsoft Foundry).
  3. A way to push files to laptops, such as MDM or configuration management. Set up Claude Code for your organisation compares options if you have none.

What the gateway must do

RequirementWhy it matters
Accept a supported API formatThis runbook assumes Anthropic Messages at POST /v1/messages, which most products offer
Stream server-sent events as they arrive, keep-alive pings includedBuffering makes sessions look hung and can trip timeouts
Map Claude model names (for example claude-sonnet-4-6) to upstream modelsUnmapped names return 404 to whoever selects them
Pass anthropic-beta, anthropic-version and the body through unchanged, both waysStripped values silently break the features that need them
Return upstream errors as-isClaude Code's recovery logic matches on error wording. Wrapping errors in your own envelope breaks it, unless the message carries one of the capability_rejected: tokens described in Claude apps gateway configuration
Exempt the path from WAF body inspectionPrompts contain source code and XML-like tags that trip cross-site-scripting rules, so short tests pass and real sessions get 403

Serving GET /v1/models is optional but lets Claude Code fill the model picker from the gateway.

Three credentials, three placeholders

Most failed rollouts I have debugged came down to confusing these. The checkpoints below name them explicitly.

CredentialHeld byShown below as
Provider credentialThe gateway only, sent upstreamNever appears in client commands
Gateway admin or test credentialYou, if your product has one<admin-key>
Developer keyEach developer, issued by the gateway<dev-key>

Step 1: prove the gateway routes your models

Send a minimal request with whatever key currently works (an admin key, a test key, or your own developer key if the product has no admin credential):

curl "https://claude-gw.northwind.internal/v1/messages" \
  -H "Authorization: Bearer <admin-key>" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{"model":"claude-sonnet-4-6","max_tokens":1,"messages":[{"role":"user","content":"hi"}]}'

Checkpoint. 200 with a content field: the gateway reached the provider. 404: that model name is not routed. 401 from the provider: the gateway's provider credential is wrong. Repeat for every model name in your routing table, because anyone selecting an untested name gets a 404.

Step 2: issue a key per developer

Create one credential per person using your product's key management. Shared keys defeat both per-person attribution and clean offboarding. Re-run the step 1 request with a freshly issued <dev-key>.

Checkpoint. 200 means the developer key works end to end. A 401 here, when step 1 passed, means the key is wrong or not yet active.

Note which header the gateway reads, because it decides the client variable: Authorization: Bearer means ANTHROPIC_AUTH_TOKEN, x-api-key means ANTHROPIC_API_KEY.

Step 3: run Claude Code through it yourself

Type these straight into a terminal (not a .env or settings file) so closing the terminal undoes them:

export ANTHROPIC_BASE_URL=https://claude-gw.northwind.internal
export ANTHROPIC_AUTH_TOKEN="<dev-key>"
claude -p "Answer with the single word: routed"

Checkpoint. You get an answer, and the gateway log shows a POST to /v1/messages with 200. Claude Code appends a query string such as ?beta=true, so match on the path.

If it fails:

  • Not logged in. Check the gateway log. Empty log: no credential reached the session, so re-export in this shell. A 401 whose body mentions x-api-key: the gateway wants that header, so use ANTHROPIC_API_KEY instead.
  • Failed to authenticate. API Error: 401. A credential was sent and refused. If the log shows the 401 coming from api.anthropic.com or your provider, the developer key was fine and the gateway's provider credential is the problem.
  • Apparent hang. A wrong or unreachable base URL causes retries with backoff that can run for minutes. If no request appears in the gateway log, ANTHROPIC_BASE_URL is not pointing at the gateway.

Step 4: distribute the configuration

What to send

Variable or settingPurposeWhen to include
ANTHROPIC_BASE_URLSends requests to the gateway instead of api.anthropic.comAlways
apiKeyHelper, ANTHROPIC_AUTH_TOKEN or ANTHROPIC_API_KEYAuthenticates to the gatewayAlways, exactly one
ANTHROPIC_CUSTOM_HEADERSExtra header on every requestGateway needs a tenant or routing header
CLAUDE_CODE_GATEWAY_HINT_HEADERSSends the gateway hint headers for routing and scheduling (v2.1.273+)Gateway reads them
CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERYPopulates /model from the gateway's /v1/modelsGateway serves that endpoint
CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETASStops pre-release headers and fieldsUpstream is Bedrock or Agent Platform and rejects beta fields
CLAUDE_CODE_SKIP_FAST_MODE_NETWORK_ERRORS or CLAUDE_CODE_SKIP_FAST_MODE_ORG_CHECKRestores fast mode when its direct check to api.anthropic.com fails or is skippedYou use fast mode and auth is gateway-only, or direct egress is blocked
ANTHROPIC_MODEL, ANTHROPIC_DEFAULT_HAIKU_MODELNames requested for the main session and background workGateway names differ from Claude Code's defaults. Route the built-in IDs too, since some background sub-calls request them regardless
ANTHROPIC_BEDROCK_BASE_URL, ANTHROPIC_VERTEX_BASE_URL, ANTHROPIC_FOUNDRY_BASE_URL or ANTHROPIC_AWS_BASE_URL plus that provider's variablesProvider-specific routeGateway fronts that provider in its native format; see the connect page

Costs explains which background functions use the Haiku-class model.

Put the values in the env block of a managed settings file and push it:

{
  "env": {
    "ANTHROPIC_BASE_URL": "https://claude-gw.northwind.internal",
    "CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY": "1"
  },
  "apiKeyHelper": "/opt/northwind/bin/claude-gw-key"
}

A managed ANTHROPIC_BASE_URL beats a developer's shell export and every lower-precedence settings file. The apiKeyHelper approach is the tidy one: a single command that authenticates to your secrets store as the logged-in user, so each laptop fetches its own key and nothing per-person goes in the file. The alternative is delivering keys through your existing secrets process and having developers set ANTHROPIC_AUTH_TOKEN.

Things to avoid and edge cases:

  • Never combine a gateway credential with forceLoginMethod, forceLoginOrgUUID or forceLoginGatewayUrl. The first two, with any value, block ANTHROPIC_API_KEY, ANTHROPIC_AUTH_TOKEN and apiKeyHelper at startup. Developers see This machine's managed settings require a first-party login, or Administrator policy requires a Cloud gateway sign-in when forceLoginMethod is "gateway" or forceLoginGatewayUrl is set.
  • Server-managed settings will not reach these sessions. That delivery route needs a direct connection to api.anthropic.com. Use file-based managed settings, which enforce the same keys. See Server-managed settings.
  • The desktop app reads its own third-party inference configuration, not managed settings; push that file via MDM as well.
  • CI runners need the base URL and credential in the runner environment.
  • WSL on managed Windows reads Windows managed settings only when wslInheritsWindowsSettings is true.

To go further and forbid any other destination, see the allowedProviders example in Other LLM gateways.

HIPAA and gateways

Gateway-routed sessions are not eligible for the HIPAA configuration; HIPAA setup lists which sign-in and connection methods are. You can still restrict features with the managed keys covered in Monitoring usage, but they neither make a session eligible nor cover everything the configuration changes. No managed key turns cloud sessions off, and no setting alone strips Anthropic credentials from child processes. Do not reach for CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC as a substitute: it also kills the auto-updater and leaves WebFetch on.

Without settings distribution

Send each developer the gateway URL, their personal key, which variable to put it in (ANTHROPIC_AUTH_TOKEN or ANTHROPIC_API_KEY) and any conditional variables with values. Point them at the connect page. Naming the variable saves them guessing.

Checkpoint. On a developer machine, claude opens straight into a session with no login screen. In /status, the Anthropic base URL line shows the gateway and, for managed delivery, Setting sources includes managed settings.

Step 5: verify from a developer machine

Test from a laptop, not the gateway host, so the real network path is exercised. A streaming request checks the endpoint, streaming pass-through and routing in one go:

curl -N "https://claude-gw.northwind.internal/v1/messages" \
  -H "Authorization: Bearer <dev-key>" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{"model":"claude-sonnet-4-6","max_tokens":16,"stream":true,"messages":[{"role":"user","content":"list three colours"}]}'

data: lines should trickle in. Everything arriving at once after a pause means the gateway is buffering, which will stall Claude Code. On Windows, pipe the body into curl.exe with --data-binary '@-' to avoid PowerShell quoting problems.

Then open claude and send a message:

  • Login prompt. In /status, if Setting sources lacks managed settings, the file never arrived. If it is there, the credential is what is missing.
  • Failed to authenticate. The gateway log says which credential failed: its own rejection names the developer key; a 401 from the provider means the provider credential.
  • One-time key approval prompt. Expected on first use with ANTHROPIC_API_KEY. ANTHROPIC_AUTH_TOKEN takes over silently.

If you use fast mode, run /fast too. Its availability check bypasses the gateway, so it can report unavailable or disabled while inference is fine; the skip variables in the table fix that.

Finally, find your message in the gateway logs. The credential identifies the developer and the x-claude-code-session-id header groups requests into sessions.

Keeping it healthy

What changesWhat you will seeWhat to do
New Claude Code releases add beta values and body fields400 errors naming a new field after people updateForward anthropic-* headers and bodies verbatim rather than allowlisting; test releases before they reach the fleet
New Claude models ship404 on the new name; it is missing from /modelAdd the name to routing, re-run step 1, and update any distributed model variables
Credentials expireEvery request starts failing with 401 from upstreamRotate the provider credential on its own schedule; apiKeyHelper handles developer key rotation without redistributing files

When sizing per-key rate limits, remember the client retries transient failures, 429 included, up to 10 times with backoff and honours Retry-After.

Controlling upgrades

Some behaviour is baked into each Claude Code version, so an upgrade can change things with no gateway change at all. Pin a tested version with requiredMaximumVersion in settings, or DISABLE_UPDATES if you ship Claude Code yourself (see Setup). Before raising the pin, read the release notes and repeat step 3.

AreaWhat can shift on upgradeHow to hold it steady
Feature-flag defaultsSessions that do not fetch flags from Anthropic (cloud providers, telemetry off) use the defaults compiled into the versionThe version pin
Capability assumptions for unknown IDsAn alias such as team-opus runs on default assumptions for adaptive reasoning, effort and context window until recognisedRoute Anthropic model IDs at the gateway, or map the ID to your alias with modelOverrides; on cloud provider connections, declare capabilities instead
Default model and aliasesWhat new sessions start on and what opus or sonnet resolve toANTHROPIC_DEFAULT_MODEL (v2.1.236+) and the ANTHROPIC_DEFAULT_*_MODEL variables

Model configuration covers each of these variables.