Integration guides ยท 2026-08-29

Connecting Claude Code to LLMTR through the Anthropic Messages endpoint

The environment variables Claude Code needs to reach LLMTR, the identifier filter in its model picker, the 200K context window assumption and the request fields that have no effect on the Anthropic Messages endpoint.

LLMTR guide diagram showing the request path from the Claude Code client through the environment variable layer into the Anthropic Messages endpoint of the LLMTR gateway.

Which wire format Claude Code speaks

Claude Code is a terminal coding agent and it emits model requests in the Anthropic Messages format. LLMTR serves that format on its own endpoint: the /v1/messages path is appended to the base URL, and every chat model in the catalog can be called through it. Nothing on the tool side has to be replaced, patched or proxied.

Two details of the endpoint shape the setup. The first is authentication: both the x-api-key header and the Authorization Bearer header accept the same key, so the tool keeps its own header layout. The second is that max_tokens is required. The Anthropic format defines no default for it, and a request without it returns 400. Claude Code always sends the field, so day-to-day use never surfaces this, but you will meet it the moment you hit the same endpoint from your own script.

Connecting with three environment variables

The whole setup is environment variables. The base URL carries no endpoint path: the client appends /v1/messages itself, so ANTHROPIC_BASE_URL is set to the llmtr.com root. If you append the /v1 suffix you are used to from OpenAI-compatible clients, the path is written twice and the request lands on an address the gateway does not serve.

The credential travels in ANTHROPIC_AUTH_TOKEN. LLMTR keys start with the llmtr- prefix, which makes a wrong value easy to spot by eye. The session default model comes from ANTHROPIC_MODEL and its value is the canonical catalog identifier, written as provider slash model. Writing the full identifier instead of a short alias keeps you on the intended route even when model discovery is switched off.

Environment variables used in a Claude Code setup
VariableExample valueEffect
ANTHROPIC_BASE_URLhttps://llmtr.comRequests go to this root with /v1/messages appended
ANTHROPIC_AUTH_TOKENllmtr-your_keyKey is carried in the Authorization header
ANTHROPIC_MODELanthropic/claude-sonnet-5Default model identifier for the session
CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY1Adds the gateway catalog to the model picker
CLAUDE_CODE_MAX_CONTEXT_TOKENS1000000Replaces the assumed context window with the real one

Baseline setup for a bash or zsh session

export ANTHROPIC_BASE_URL=https://llmtr.com
export ANTHROPIC_AUTH_TOKEN=llmtr-your_key
export ANTHROPIC_MODEL=anthropic/claude-sonnet-5

Which identifiers reach the model picker

The catalog is readable from /v1/models without a key, so you can inspect the list before you sign in anywhere. To make LLMTR entries appear in the Claude Code model picker itself, the discovery flag has to be switched on.

The picker applies a filter: it lists only identifiers that contain claude or anthropic. Turning the flag on therefore does not move the whole catalog into the picker. For a model that the filter excludes, you pass the identifier directly through ANTHROPIC_MODEL. Absence from the picker is a listing rule, not a rejection: the request still runs.

  • anthropic/claude-sonnet-5 shows up in the picker as the balanced default
  • anthropic/claude-opus-4.8 is listed for heavier editing sessions
  • anthropic/claude-haiku-4.5 suits short and frequent calls
  • Identifiers such as qwen/qwen3.8-max never pass the filter and are set through ANTHROPIC_MODEL only

Enabling discovery and searching the catalog for identifiers

export CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1

curl -s https://llmtr.com/v1/models \
  | grep -o '"id":"anthropic/[^"]*"'

The 200K assumption and the context window warning

When Claude Code meets a model identifier that is not in its own list, it assumes a 200K context window and prints a warning line. The request is still sent and the response still comes back; the warning is not an error. Its real cost is a wrong context budget: on a wide-window model the tool may compact far too early, and on a narrow one it may notice the ceiling too late.

The correct move is to declare the real window with CLAUDE_CODE_MAX_CONTEXT_TOKENS. Read the value from the context_length field in the catalog, which reports input and output combined. Update the variable whenever you switch models, otherwise the previous window is applied to the new route.

PowerShell session setup including the window value

$env:ANTHROPIC_BASE_URL = "https://llmtr.com"
$env:ANTHROPIC_AUTH_TOKEN = "llmtr-your_key"
$env:ANTHROPIC_MODEL = "anthropic/claude-sonnet-5"
$env:CLAUDE_CODE_MAX_CONTEXT_TOKENS = "1000000"

Fields with no counterpart on this endpoint

This is the part of the integration that has to be stated plainly. Three request fields currently have no effect on the Anthropic Messages endpoint. The request is not rejected and the field is silently ignored, so you notice the difference in the response body rather than in an error message.

The practical consequence: if you planned to make long system instructions cheaper through prompt caching, do not budget for that saving on this endpoint. Any tool surface that renders thinking blocks stays empty. Tool calling itself behaves normally, returning a tool_use block that you answer with tool_result on the following turn.

  • thinking can be sent, but no thinking block comes back in the response
  • cache_control markers are not applied and do not affect pricing
  • context_management is disregarded
  • Response bodies contain only text and tool_use blocks

Verification and reading the error envelope

Test the setup with a single request before you start the agent. A 200 response proves the base URL, the key and the model identifier are all correct at once. Keep max_tokens small in that probe; you are confirming a route, not collecting output.

Errors arrive in the Anthropic envelope: the body type is error and error.type is derived from the HTTP status. That mapping turns the one-line failure in your terminal into a specific part of the setup to inspect, which is exactly what the table below gives you.

HTTP status mapped to the Anthropic error type
HTTPerror.typeWhat to inspect in the setup
400invalid_request_errorMissing max_tokens or an invalid body field
401authentication_errorThe ANTHROPIC_AUTH_TOKEN value and key validity
403permission_errorWhether the key may reach this model
404not_found_errorAn extra path on the base URL or a mistyped identifier
413request_too_largeThe size of the context being sent
429rate_limit_errorRequest frequency
5xxapi_errorA transient condition on the upstream provider

Probing the connection with one request

curl https://llmtr.com/v1/messages \
  -H "Authorization: Bearer $ANTHROPIC_AUTH_TOKEN" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{"model":"anthropic/claude-sonnet-5","max_tokens":16,"messages":[{"role":"user","content":"test"}]}'

Frequently asked questions

Do I need a separate build of Claude Code for LLMTR?

No. The integration is entirely environment variables. Once ANTHROPIC_BASE_URL, ANTHROPIC_AUTH_TOKEN and ANTHROPIC_MODEL are set, the tool sends its requests to the Anthropic Messages endpoint on LLMTR. There is no repository to switch, no patch to apply and no plugin to install.

Why does the model picker show only part of the catalog?

The picker lists only identifiers containing claude or anthropic. Enabling the discovery flag does not remove that filter. Any model missing from the list can still be used by writing its full canonical identifier into ANTHROPIC_MODEL.

Can I ignore the context window warning?

The request keeps working, but the tool assumes a 200K window and therefore budgets context incorrectly. Declaring the model's real window with CLAUDE_CODE_MAX_CONTEXT_TOKENS removes both the warning and the wrong arithmetic.

Do prompt cache markers reduce cost on this endpoint?

No. cache_control is ignored here and has no pricing effect. Because the request does not fail, the only symptom is that the saving you expected never appears. Billing is token based and follows the tariff of the model you selected.

Related posts