X-Valar-Client-Id header, so the Portkey setup below applies unchanged. Just connect Pi with valar pi on --endpoint https://api.portkey.ai --api-key <portkey-api-key> and restart Pi. Instructions for connecting Cursor through Portkey are coming soon (Cursor carries its client id as a token suffix rather than a header).
How it fits together
valar claude on writes three Valar headers into ~/.claude/settings.json: X-Valar-Client-Id (attributes usage to an engineer, defaulting to their username), X-Valar-Harness (names the tool, from a fixed set of supported values) and X-Valar-Cli-Version. Getting them across the Portkey hop is the one thing that matters.
It matters more through a proxy than it does directly. Portkey makes its own request upstream, so the user agent Valar sees is Portkey’s, not your harness’s. The headers are the only reliable signal left. Without X-Valar-Harness, everything on this path is recorded as Claude Code.
An unrecognised value does the same thing. X-Valar-Harness accepts a fixed set of tool names — claude, codex, cursor, gemini, opencode, pi, copilot, librechat — and anything outside that set is ignored rather than rejected, so putting your own application or deployment name here also records the traffic as Claude Code. That affects routing as well as reporting: traffic recorded as Claude Code is served on Claude Code’s cohort configuration. Send the name of the tool actually making the request, and talk to us if yours isn’t on the list.
Portkey does not forward client headers by default. You must name the headers that may pass through. The recommended setup stores that allowlist in a Portkey Config. Some workspaces reject the equivalent per-request x-portkey-forward-headers setting as inline configuration. If the allowlist is missing or misspelled, requests can still succeed while the usage arrives at Valar unattributed.
Add Valar to the Portkey Model Catalog
Valar speaks the Anthropic Messages API athttps://api.valarhq.ai, so Portkey treats it as an anthropic provider pointed at a custom host.
In the Portkey dashboard, go to Model Catalog → Add Provider and create a provider with:
Set the API key to the
vlrcode_… key you generated in the Valar Dashboard. Portkey stores it and authenticates to Valar upstream, so the key never lands on an engineer’s machine. This is the same split LiteLLM gives you with a virtual key.
The Custom Host must include the
/v1 path segment. Portkey appends the endpoint path (/messages) to whatever you give it, so https://api.valarhq.ai without the suffix produces a 404 on every request. This is the opposite of the convention everywhere else in these docs, where you pass the Valar root and the client adds /v1 itself.Provision every Valar model
A new Anthropic integration starts with Anthropic’s own model catalog. Add the Valar models to the integration before you create the Portkey API key. In Portkey, open the integration you created, then go to Model Provisioning → Add Model. Leave Model Type on Custom Model and add:valar-auto, the Valar auto-router.- Every model id returned by Valar’s Models API for your coding key, except the OpenAI-only ids below.
data[].id as the Portkey Model Slug, preserving its spelling and case. You can also browse the current catalog on the Models page.
Skip the ids served only on Valar’s OpenAI-compatible APIs. This integration speaks the Anthropic Messages API, and they have no route on it, so selecting one through Portkey returns an error instead of an answer. The Models API does not mark them; currently they are:
google/gemma-4-26B-A4B-it · google/gemma-4-31B-it · MiniMaxAI/MiniMax-M3 · nvidia/NVIDIA-Nemotron-3-Ultra-550B-A55B-NVFP4 · openai/gpt-oss-120b · Qwen/Qwen3.5-27B · Qwen/Qwen3.5-397B-A17B · Qwen/Qwen3.6-35B-A3B
Portkey combines the provider slug and model id in the request’s model field:
/; Portkey treats only the first segment, @valar, as the provider selector.
Provisioning a model makes it available through Portkey. It does not route every request to that model. The caller still chooses with
@valar/<model-id>, unless a Portkey Config fixes the provider or overrides the model.Generate a Portkey API key
Portkey sits between Claude Code and Valar, so Claude Code no longer talks to Valar directly. Instead it authenticates to Portkey with a Portkey API key you create there. In the Portkey dashboard, go to API Keys → Generate, and scope it to thevalar provider you just created. Copy the key; Claude Code will use it as its bearer token.
What flows through after this:
- Claude Code authenticates to Portkey with the Portkey API key.
- Portkey authenticates to Valar with the Valar coding key stored in the Model Catalog.
- Claude Code’s
X-Valar-*headers are forwarded to Valar, so routing and attribution behave exactly as in the direct path.
Create a Portkey Config
Store the forwarding allowlist in a Portkey Config. This works in workspaces that block inline gateway configuration. In the Portkey dashboard, go to Configs → Create and enter:pc-, for example pc-valar-a1bbcf.
The Config selects the @valar Model Catalog provider and tells Portkey which request headers it may pass to Valar. anthropic-beta is included because Claude Code uses Anthropic beta features that fail closed when the header is dropped. Use this pinned Config for clients such as Claude Code that send bare model names. Clients that send @valar/<model-id> can select Valar without it.
Connect Claude Code
Point Claude Code at Portkey withvalar claude on, using your Portkey API key:
ANTHROPIC_AUTH_TOKEN authenticates Claude Code to Portkey. Add the saved Config ID to the ANTHROPIC_CUSTOM_HEADERS line in ~/.claude/settings.json:
Name: value. This is the newline-separated format valar claude on already writes.
Order does not matter, and neither does which you do first.
valar claude on rewrites only its own three X-Valar-* lines and preserves every other header you set, so the Portkey lines survive re-enables, client-id changes and CLI upgrades. You can add them before or after the first valar claude on.x-portkey-configselects the saved Config. Do not also setx-portkey-provider; the Config already selects@valar. The one exception is the unpinned Config below, which deliberately selects nothing.ANTHROPIC_AUTH_TOKENis the Portkey credential. You do not need to repeat it in anx-portkey-api-keycustom header on the Model Catalog path.- Do not set
ANTHROPIC_DEFAULT_*_MODEL. Portkey’s generic Claude Code guide tells you to pin model IDs per provider; that advice does not apply here. Valar maps whatever model string Claude Code sends to the target model your cohort resolves to, andvalar claude ondeliberately strips those pins so the gateway’s server-side routing stays authoritative. Keep choosing tiers with/model.
Claude Code appends
/v1/messages to the base URL, so pass https://api.portkey.ai without a /v1 suffix. valar claude on strips a trailing /v1 if you include one.If your workspace allows inline configuration
If your Portkey workspace permits inline configuration, you can skip the saved Config and use these two lines instead ofx-portkey-config:
@ prefix on @valar is required. A bare valar value is interpreted as a built-in provider name and fails. The forwarding list is comma-separated, and its header names are lowercase.
If Portkey returns this error, your workspace blocks the inline form:
x-portkey-provider and x-portkey-forward-headers with x-portkey-config: <portkey-config-id>.
If one Portkey key serves other backends
One Portkey key in front of several providers — a LibreChat deployment offering a few backends, say — must not carry the pinned Config as its default. Every request on that key is force-routed to Valar, whatever model it asked for, and the@slug/ prefix the caller sent is discarded.
Nothing errors when that happens. A Valar coding key maps a model string it does not recognise onto the tier your cohort resolves to rather than rejecting it, so a request for @anthropic/eu.anthropic.claude-sonnet-5 or @z-ai/zai.glm-5 comes back 200, with a sensible answer, from a Valar-routed model — and on Valar’s bill. The symptom is a provider that went quiet, not a failure.
Two ways round it.
Give ValarCode its own Portkey API key, with the pinned Config as its default. The shared key keeps its own Config and the two never meet. Take this one unless you have a reason not to.
Or drop the pin and let each request choose. A Config can carry the forwarding allowlist and no provider at all:
passthrough tells Portkey to resolve the provider from the request rather than from the Config. @valar/valar-auto uses Valar’s auto-router, @valar/zai-org/GLM-5.3 selects that model directly, and @anthropic/… still reaches Anthropic. The Valar headers are forwarded on whichever hop carries them. A caller that names its provider in the model string, such as LibreChat, needs nothing further.
Claude Code is the exception. It sends claude-sonnet-…, with no prefix for Portkey to read, so it has to name the provider itself: add x-portkey-provider: @valar to ANTHROPIC_CUSTOM_HEADERS alongside x-portkey-config. That is inline configuration, which some workspaces block; where it is blocked, give Claude Code its own key.
The unpinned form comes from Portkey’s Config schema, and we have not run it end to end ourselves. The pinned Config above is the path we document and test. Tell us if the unpinned one misbehaves.
Without the Model Catalog
If you would rather not store the Valar key in Portkey, you can pass the upstream host and credential inline instead. This option requires a workspace that allows inline configuration. Drop thex-portkey-provider: @valar line and use:
valar claude on --endpoint https://api.portkey.ai --api-key <your-coding-key> so ANTHROPIC_AUTH_TOKEN holds the vlrcode_… key. Authorization is in the forward list, so Portkey passes that credential through to Valar untouched rather than processing it; x-portkey-api-key is what authenticates to Portkey.
The Valar coding key now sits in every engineer’s settings.json instead of in Portkey. Prefer the Model Catalog path unless you have a reason not to. If block_inline_config is enabled, use the Model Catalog and saved Config path above.
Verify it works
After the first few requests, check:- Portkey logs: the request shows the saved Config ID and provider
valar, and the response is successful. - Valar analytics dashboard: the engineer appears under their client id (their username by default), and their harness list includes the tool you configured —
claudefor Claude Code.
X-Valar-Client-Id. Check Valar analytics for the attribution result.
If usage appears but is not attributed to an engineer, X-Valar-Client-Id is not making it through. Check the saved Config’s forward_headers list first. A missing or misspelled entry is the common cause.
This failure is silent. Portkey’s Anthropic transform re-issues the upstream credential as x-api-key and adds anthropic-version independently of the forwarding allowlist. Authentication can still succeed when the allowlist is wrong. The request returns 200, the answer is correct, and the only symptom is unattributed Valar usage.
To stop routing through Portkey and restore Claude Code’s previous settings:
off restores the whole settings.json from its backup, so the Portkey header lines go with it.
Next steps
Claude Code
The direct connect path and what the CLI writes to
settings.json.LiteLLM
The same setup for a LiteLLM proxy.
Model routing
How the client id drives cohort assignment and the split.
Analytics
Where per-engineer attribution shows up.