Skip to content

Configure an LLM gateway for Claude Code

Claude Code sends model traffic to api.anthropic.com unless environment variables route it elsewhere: to Amazon Bedrock, Google Cloud’s Agent Platform, Microsoft Foundry, Claude Platform on AWS, or an LLM gateway through ANTHROPIC_BASE_URL. A gateway needs a gateway credential as well; with only the base URL set, a saved claude.ai login still pays for every request.

This page is for the developer who has to connect to the route their company chose, and for the tech lead or platform engineer who rolls that route out to a team. Security approved Claude Code on one condition: no developer laptop calls Anthropic directly, and every token is billed to the company’s AWS account with a name attached. You have the gateway URL, a Bedrock account, and forty developers who are already signed in with personal subscriptions.

What you’ll walk away with from gateway routing

Section titled “What you’ll walk away with from gateway routing”
  • A decision table for choosing between a cloud provider, Anthropic’s Claude apps gateway, and a gateway you already run
  • Working configuration for each cloud provider and for any Anthropic-format gateway, including LiteLLM
  • A managed-settings block that routes the whole team without anyone editing a shell profile
  • A verification routine that proves each session uses the route, without inspecting every laptop
  • A failure table for the errors gateway routing produces, with the fix for each

Every variable, command and error string on this page was checked against the Claude Code documentation and the installed CLI, version 2.1.283, on 2026-09-26. Which route your organization should use for data residency and zero data retention is a separate decision: see where the model runs.

A cloud provider changes who serves the model. A gateway changes who holds the credential. You can combine both: a gateway in front of Amazon Bedrock is a common pattern.

RouteHow Claude Code reaches itPick it whenWhat it costs you
Cloud provider, directCLAUDE_CODE_USE_BEDROCK, CLAUDE_CODE_USE_VERTEX, CLAUDE_CODE_USE_FOUNDRY or CLAUDE_CODE_USE_ANTHROPIC_AWS, plus the provider’s own credentialsBilling and data must stay in your cloud account, and each developer already has cloud credentialsPer-developer cloud IAM, provider-specific model IDs, and model defaults that differ per provider
Claude apps gatewayclaude gateway --config gateway.yaml on a Linux server; developers sign in with /login through your OIDC identity providerYou want SSO sign-in, model allowlists and managed settings per IdP group, and OTLP usage metrics without running a third-party productA PostgreSQL database, a private-network hostname, and no service-token sign-in, so CI connects to the provider directly
Your own gateway (LiteLLM, Kong, an internal proxy)ANTHROPIC_BASE_URL plus ANTHROPIC_AUTH_TOKEN, ANTHROPIC_API_KEY or apiKeyHelperThe organization already runs one for other LLM traffic and wants one budget and audit logThe gateway must forward every header and request field each new Claude Code release sends, or features break

Every route turns off some features, so check them before you commit:

  • The claude.ai subscription stops paying. While a gateway credential or apiKeyHelper is active, requests bill per token to whoever owns the credential the gateway forwards.
  • Remote Control and voice dictation stop working. Both need a claude.ai identity. Remote Control is also off whenever ANTHROPIC_BASE_URL points at a non-Anthropic host.
  • Slack and cloud sessions bypass the route. They always use Anthropic’s API and ignore gateway variables, so do not enable them for users whose traffic must stay on the gateway.
  • WebSearch disappears on Amazon Bedrock and on Claude apps gateway sessions.

Each provider has its own switch variable and credential chain. Amazon Bedrock and Google Cloud also have a setup wizard: run /setup-bedrock or /setup-vertex in a session, and it writes the result to the env block of ~/.claude/settings.json.

Submit the Anthropic use-case form once per account in the Bedrock model catalog, then give each developer’s role this policy:

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowModelAndInferenceProfileAccess",
"Effect": "Allow",
"Action": [
"bedrock:InvokeModel",
"bedrock:InvokeModelWithResponseStream",
"bedrock:ListInferenceProfiles",
"bedrock:GetInferenceProfile"
],
"Resource": [
"arn:aws:bedrock:*:*:inference-profile/*",
"arn:aws:bedrock:*:*:application-inference-profile/*",
"arn:aws:bedrock:*:*:foundation-model/*"
]
}
]
}

The official policy adds an aws-marketplace statement for first-time model subscription; keep it on the account that subscribes. Then, in the terminal:

Terminal window
export CLAUDE_CODE_USE_BEDROCK=1
export AWS_PROFILE=bedrock-dev # SSO profile; the standard AWS credential chain applies
export AWS_REGION=us-east-1 # optional when the profile sets a region
export ANTHROPIC_DEFAULT_OPUS_MODEL='us.anthropic.claude-opus-5-5'
export ANTHROPIC_DEFAULT_HAIKU_MODEL='us.anthropic.claude-haiku-4-5-20251001-v1:0'
claude

Claude Code resolves models to cross-region inference profiles (us., eu., apac., or global., chosen from your region). Set ANTHROPIC_BEDROCK_REGION_PREFIX=global to prefer global profiles. The Mantle endpoint, which serves the Anthropic Messages format on Bedrock, is a separate switch (CLAUDE_CODE_USE_MANTLE=1) with its own bedrock-mantle: IAM actions and model IDs such as anthropic.claude-sonnet-5.

Pin models on every provider before a team rollout. Aliases such as opus and sonnet resolve to defaults built into each Claude Code version, and those defaults differ per provider: on Bedrock and Google Cloud the sonnet alias is Sonnet 4.5 unless you set ANTHROPIC_DEFAULT_SONNET_MODEL. Opus 5.5 needs Claude Code v2.1.280 or later; the stable release channel was still on 2.1.274 on 2026-09-26, where the Bedrock and Google Cloud default is Opus 5. Current model IDs and prices live on the models hub.

Any gateway that accepts the Anthropic Messages API at POST /v1/messages works. Ask the gateway team for two things: the base URL and a credential. The base URL is the host, without /v1; Claude Code appends the path itself.

  1. Test the gateway before Claude Code touches it. A one-token request isolates gateway problems from configuration problems:

    Terminal window
    export ANTHROPIC_BASE_URL=https://llm-gateway.internal.example.com
    export ANTHROPIC_AUTH_TOKEN="$(vault kv get -field=api_key secret/llm-gateway/claude-code)"
    curl -sS -w '\n%{http_code}\n' -X POST "$ANTHROPIC_BASE_URL/v1/messages" \
    -H "Authorization: Bearer $ANTHROPIC_AUTH_TOKEN" \
    -H "anthropic-version: 2023-06-01" \
    -H "content-type: application/json" \
    -d '{"model": "claude-opus-5-5", "max_tokens": 1, "messages": [{"role": "user", "content": "."}]}'

    A body starting with {"id":"msg_ means the route works. An unknown-model error still proves the URL and credential; a 401 means the gateway reads a different header.

  2. Pick the credential variable by the header the gateway reads. ANTHROPIC_AUTH_TOKEN is sent as Authorization: Bearer, ANTHROPIC_API_KEY as x-api-key, and an apiKeyHelper command’s output as both. When nobody told you which, start with ANTHROPIC_AUTH_TOKEN and switch on a 401. An ANTHROPIC_API_KEY needs a one-time approval in an interactive session.

  3. Start claude from the same shell and run /status. The Status tab must show an Anthropic base URL line with the gateway address and an Auth token or API key line naming your variable. A Login method line naming a claude.ai account means the subscription is still paying.

  4. Persist the values in the env block of ~/.claude/settings.json, not only in your shell. Background agents hosted by the supervisor do not reliably inherit shell exports, and a settings-file value wins over a shell export. Never put the credential in a project’s .claude/settings.json, which is committed.

To fetch a rotating credential instead of storing one, point apiKeyHelper at a script that prints only the key. Claude Code caches the output for five minutes; set CLAUDE_CODE_API_KEY_HELPER_TTL_MS to change that. From v2.1.227, any extra line the script prints, such as a banner, makes the helper fail.

{
"apiKeyHelper": "~/bin/get-gateway-key.sh",
"env": {
"ANTHROPIC_BASE_URL": "https://llm-gateway.internal.example.com",
"ANTHROPIC_CUSTOM_HEADERS": "X-Team: payments",
"CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY": "1"
}
}

ANTHROPIC_CUSTOM_HEADERS adds routing or tenant headers (separate pairs with \n). Model discovery adds the gateway’s /v1/models list to the /model picker.

LiteLLM is an open-source gateway with virtual keys, budgets, and request logging (★59.6k on GitHub and version 1.102.1 on PyPI, both read 2026-09-26). Anthropic does not endorse or audit it. On 2026-03-24, PyPI versions 1.82.7 and 1.82.8 shipped a credential stealer; both have been removed, so always install a pinned version:

Terminal window
uv tool install 'litellm[proxy]==1.102.1'

Keep provider keys out of the file: the os.environ/ prefix tells LiteLLM to read a value from the environment. Name each route after the model ID Claude Code requests.

litellm_config.yaml
model_list:
- model_name: claude-opus-5-5
litellm_params:
model: anthropic/claude-opus-5-5
api_key: os.environ/ANTHROPIC_API_KEY
- model_name: claude-haiku-4-5
litellm_params:
model: anthropic/claude-haiku-4-5
api_key: os.environ/ANTHROPIC_API_KEY
general_settings:
master_key: os.environ/LITELLM_MASTER_KEY
database_url: os.environ/LITELLM_DATABASE_URL # needed for per-developer virtual keys
Terminal window
litellm --config litellm_config.yaml --port 4000

Developers then set ANTHROPIC_BASE_URL to the proxy and ANTHROPIC_AUTH_TOKEN to their own LiteLLM virtual key, never the master key. Set ANTHROPIC_DEFAULT_HAIKU_MODEL=claude-haiku-4-5 on the client so background calls ask for a name the proxy routes. The individual-developer side of LiteLLM, Claude Code Router and local models is covered in gateways and local models.

When the gateway exposes a provider’s native format instead of the Anthropic one, use that provider’s base URL variable and tell Claude Code not to sign requests, because the gateway holds the cloud credential:

Terminal window
export CLAUDE_CODE_USE_BEDROCK=1
export ANTHROPIC_BEDROCK_BASE_URL=https://llm-gateway.internal.example.com/bedrock
export CLAUDE_CODE_SKIP_BEDROCK_AUTH=1
export ANTHROPIC_AUTH_TOKEN="$GATEWAY_TOKEN" # only if the gateway wants its own token

The equivalents are ANTHROPIC_VERTEX_BASE_URL with CLAUDE_CODE_SKIP_VERTEX_AUTH, ANTHROPIC_BEDROCK_MANTLE_BASE_URL with CLAUDE_CODE_SKIP_MANTLE_AUTH, ANTHROPIC_AWS_BASE_URL for Claude Platform on AWS, and ANTHROPIC_FOUNDRY_BASE_URL with ANTHROPIC_FOUNDRY_API_KEY. Leave AWS_BEARER_TOKEN_BEDROCK unset: if it is set, it replaces your gateway token even with auth skipped.

Developers should configure nothing. Deliver the route in the env block of the managed settings file (/etc/claude-code/managed-settings.json on Linux, /Library/Application Support/ClaudeCode/managed-settings.json on macOS, C:\Program Files\ClaudeCode\managed-settings.json on Windows) and let an apiKeyHelper fetch each developer’s own key:

{
"env": {
"ANTHROPIC_BASE_URL": "https://llm-gateway.internal.example.com",
"ANTHROPIC_DEFAULT_OPUS_MODEL": "claude-opus-5-5",
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "claude-haiku-4-5",
"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1"
},
"apiKeyHelper": "/usr/local/bin/get-gateway-key"
}

A managed ANTHROPIC_BASE_URL cannot be overridden by a developer’s shell export. Four rules keep the rollout from locking people out:

  • Never add forceLoginMethod or forceLoginOrgUUID next to a gateway credential. Either key blocks ANTHROPIC_API_KEY, ANTHROPIC_AUTH_TOKEN and apiKeyHelper at startup.
  • Use the file, not server-managed settings. Server-managed settings need a direct connection to api.anthropic.com, so they never reach gateway-routed sessions.
  • Plan for CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC. It turns off auto-updates and the fast-mode check, so ship updates through your package manager. The WebFetch safety check still calls api.anthropic.com unless you also set skipWebFetchPreflight: true.
  • Test each Claude Code release against the gateway first. New releases send new anthropic-beta values and body fields, and a gateway that allowlists them returns 400. Hold the fleet on a tested version with requiredMaximumVersion until the canary passes.

Two surfaces need their own delivery. The VS Code extension checks the credential in claudeCode.environmentVariables before it launches, and the desktop app reads its third-party inference configuration instead of ANTHROPIC_BASE_URL, so push both through MDM alongside the managed file. For the policy that surrounds the route, deny rules, telemetry and a managed CLAUDE.md, follow enterprise integration.

For the Claude apps gateway, the managed file carries the sign-in instead of a credential: "forceLoginMethod": "gateway" and "forceLoginGatewayUrl": "https://claude-gateway.internal.example.com". The gateway runs from the same binary (claude gateway --config gateway.yaml, v2.1.195 or later), only on a hostname that resolves to private addresses.

How do you prove every session takes the route?

Section titled “How do you prove every session takes the route?”

A route you cannot observe is a policy on paper. Four checks give the platform owner, who signs off on the rollout, evidence without reading anyone’s configuration by hand:

  1. Canary check. On one machine per OS image, run claude, then /status: the Setting sources line must include managed settings, Anthropic base URL must show the gateway, and the credential line must name the helper or variable. For a cloud provider, the provider line shows it, for example Amazon Bedrock (Mantle).
  2. Egress test. On the canary, block api.anthropic.com at the firewall and ask Claude Code a question. An answer proves model traffic does not go direct. An error means some request still does, and /status shows which base URL the session used. Ignore fast-mode and WebFetch preflight errors (both call api.anthropic.com by design unless disabled); only a failed model answer counts.
  3. Routing check per model name. Run the one-token curl request above for every model name the gateway routes. A name the gateway does not route returns an error to the first developer who selects it.
  4. Gateway-side attribution. The gateway’s usage log must show one key per developer and no traffic under a shared key; the x-claude-code-session-id request header groups each developer’s requests by session, so you can trace one session end to end. The Claude apps gateway exports OTLP metrics with user identity; for other gateways, compare spend per key with cost control and the agent cost-tracking tools.

Run checks 1 and 3 in CI against every new Claude Code version before it reaches developers.

SymptomCauseRecovery
Usage still counts against personal subscriptionsOnly ANTHROPIC_BASE_URL is set, so the claude.ai login stays the active credentialAdd ANTHROPIC_AUTH_TOKEN, ANTHROPIC_API_KEY or apiKeyHelper; run /logout to drop the saved login
401 naming an invalid tokenThe credential is in a header the gateway does not read, or it was revokedSwitch between ANTHROPIC_AUTH_TOKEN and ANTHROPIC_API_KEY; regenerate the key at the gateway
Login screen appears although the curl test succeedsThe credential sits in a project settings file, which applies only after the first-run wizard and the folder trust promptSet it in a shell export, ~/.claude/settings.json or managed settings
This machine's managed settings require a first-party loginManaged settings contain forceLoginMethod or forceLoginOrgUUIDRemove those keys, or drop the gateway credential; the two cannot coexist
400 naming context_management or Extra inputs are not permittedThe upstream rejects fields Claude Code sends to Anthropic-format endpointsSet CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS=1, then fix the gateway to forward fields verbatim
400 with the gateway’s own context-limit messageThe gateway enforces a smaller window and rewrites the error, so Claude Code does not compactRun /compact; set CLAUDE_CODE_AUTO_COMPACT_WINDOW to the gateway’s limit (minimum 100,000)
403 with an HTML body and nothing in the gateway logA web application firewall blocks prompts that contain XML-style tags and source codeExempt /v1/messages from body inspection (on AWS WAF, the CrossSiteScripting_Body rule)
Bedrock streaming response has content-typeThe gateway rewrote Bedrock’s event-stream Content-TypeForward the response body and Content-Type unmodified
Bedrock: on-demand throughput isn't supportedA bare model ID was used where an inference profile is requiredUse an inference-profile ID such as us.anthropic.claude-opus-5-5
Google Cloud: 404 model not foundThe model is not enabled, or not served in CLOUD_ML_REGIONEnable it in Model Garden; set a VERTEX_REGION_CLAUDE_* override
TLS errors while curl succeedsA TLS-inspecting proxy’s CA is unknown to Claude CodeSet NODE_EXTRA_CA_CERTS; see proxy configuration
The provider bill jumps after an upgradeAn unpinned deployment moved to a new Opus defaultPin ANTHROPIC_MODEL or the ANTHROPIC_DEFAULT_*_MODEL variables, then review cost governance

If Remote Control is unavailable, that is expected on every gateway and cloud route: claude doctor names what blocks it, and channels and Remote Control covers the alternatives.