LM Warden

Anthropic SDK on your own GPUs.

Your Anthropic API key stays in api_key; the warden key rides in its own header.

Where a request from Anthropic SDK goes Anthropic SDK sends its requests to LM Warden with base_url set to the warden and X-LMWarden-Key holding a warden key. LM Warden checks the key, speaks Anthropic Messages, queues the request by key priority and hands it to the replica router, which keeps each session on the replica that already holds its cache, one model copy per GPU. A separate path goes to api.anthropic.com: rules send other Claude models here, on your own API key. Anthropic SDK base_url points at the warden X-LMWarden-Key vw_…, in default headers POST /v1/messages LM Warden checks the key: one per app speaks Anthropic Messages scheduler, key priority usage, latency and live stats per key Replica router a session goes back to the replica that holds its cache one model copy per GPU your GPUs: vLLM or llama.cpp replica 0, GPU 0 replica 1, GPU 1 replica 2, GPU 2 a conversation stays on its replica api.anthropic.com rules send other Claude models here, on your own API key
Where a request from Anthropic SDK goes Anthropic SDK sends its requests to LM Warden with base_url set to the warden and X-LMWarden-Key holding a warden key. LM Warden checks the key, speaks Anthropic Messages, queues the request by key priority and hands it to the replica router, which keeps each session on the replica that already holds its cache, one model copy per GPU. A separate path goes to api.anthropic.com: rules send other Claude models here, on your own API key. Anthropic SDK base_url points at the warden X-LMWarden-Key vw_…, in default headers POST /v1/messages LM Warden checks the key: one per app speaks Anthropic Messages scheduler, key priority usage, latency, live stats per key Replica router a session goes back to the replica that holds its cache replica 0 GPU 0 replica 1 GPU 1 replica 2 GPU 2 your GPUs: vLLM or llama.cpp a conversation stays on its replica api.anthropic.com rules send other Claude models here, on your own API key
Where a request from Anthropic SDK goes: the two settings Connect writes, the warden in the middle, then one copy of the model per GPU.

In words: Anthropic SDK sends its requests to LM Warden with base_url set to the warden and X-LMWarden-Key holding a warden key. LM Warden checks the key, speaks Anthropic Messages, queues the request by key priority and hands it to the replica router, which keeps each session on the replica that already holds its cache, one model copy per GPU. A separate path goes to api.anthropic.com: rules send other Claude models here, on your own API key.

Protocol
Anthropic Messages
Support
Full support

The Claude models your rules name run here; every other model and /v1 path goes to Anthropic on your own login. Local only needs no Anthropic account: the warden key is the api_key and the model is a served name.

Requirements

  • Routing must be on, with at least one enabled rule.
  • The key must be allowed to relay to Anthropic (May relay).

Setup

In the console, Connect writes these files with your warden’s address, your key and the model you picked. Here they are with placeholders.

Router: keep your Anthropic key

base_url is this warden; your Anthropic API key stays in api_key and the warden key goes in default headers.

Python
import anthropic

# api_key is your own Anthropic key (ANTHROPIC_API_KEY), used for pass-through.
client = anthropic.Anthropic(
    base_url="https://your-warden",
    default_headers={"X-LMWarden-Key": "vw_YOUR_KEY"},
)
message = client.messages.create(
    model="claude-haiku-4-5",  # a model your rules serve here; others go to Anthropic
    max_tokens=256,
    messages=[{"role": "user", "content": "Reply with the single word OK."}],
)
print(message.content[0].text)
TypeScript
import Anthropic from "@anthropic-ai/sdk";

// apiKey is your own Anthropic key (ANTHROPIC_API_KEY), used for pass-through.
const client = new Anthropic({
  baseURL: "https://your-warden",
  defaultHeaders: { "X-LMWarden-Key": "vw_YOUR_KEY" },
});
const message = await client.messages.create({
  model: "claude-haiku-4-5", // a model your rules serve here; others go to Anthropic
  max_tokens: 256,
  messages: [{ role: "user", content: "Reply with the single word OK." }],
});
console.log(message.content);
curl
curl https://your-warden/v1/messages \
  -H "X-LMWarden-Key: vw_YOUR_KEY" \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{"model": "claude-haiku-4-5", "max_tokens": 256, "messages": [{"role": "user", "content": "Reply with the single word OK."}]}'

Local only

The warden key is the api_key and the model is a served name.

Python
import anthropic

client = anthropic.Anthropic(base_url="https://your-warden", api_key="vw_YOUR_KEY")
message = client.messages.create(
    model="your-served-model-name",
    max_tokens=256,
    messages=[{"role": "user", "content": "Reply with the single word OK."}],
)
print(message.content[0].text)
TypeScript
import Anthropic from "@anthropic-ai/sdk";

const client = new Anthropic({ baseURL: "https://your-warden", apiKey: "vw_YOUR_KEY" });
const message = await client.messages.create({
  model: "your-served-model-name",
  max_tokens: 256,
  messages: [{ role: "user", content: "Reply with the single word OK." }],
});
console.log(message.content);
curl
curl https://your-warden/v1/messages \
  -H "x-api-key: vw_YOUR_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{"model": "your-served-model-name", "max_tokens": 256, "messages": [{"role": "user", "content": "Reply with the single word OK."}]}'

Official documentation: https://platform.claude.com/docs/en/api/sdks/python (read 2026-10-04).