Warp

Warp Router

Warp router

Not every request needs a frontier model. Warp scores a prompt’s difficulty in a few milliseconds and sends it to the cheapest tier that still holds the quality line.

warp/auto — automatic routing

Request with model: "warp/auto" and every request is assessed and sent to a model that fits it: easy ones to something light, hard ones to a stronger model. The assessment happens inside the gateway in a few milliseconds with no extra LLM call, so the routing itself adds neither latency nor cost.

Which model served is reported as model in the response metadata and the x-warp-model header; what it saved is saved_usd, on every request.

Intent dials

Every workload wants a different trade-off. Pick one of four with warp.dial (per request) or the key’s routing policy (routing.dial). The applied dial is reported in the dial response metadata and the x-warp-dial header.

DialWhat it doesRecommended workloads
balancedThe default. The balance point between cost and quality.General-purpose backends · internal assistants · default integrations
strict-qualityQuality first. Promotes to stronger models more readily and is conservative about routing down.Customer-facing chatbots · legal, medical, and other work where a wrong answer is costly
max-savingsSavings first. Routes to the cheapest tier regardless of score (the exception being the hardest requests, which the anchor still takes).High-volume batch · offline pipelines · tagging and classification
low-latencySpeed first. Promotes on the same thresholds as balanced, then prefers the quicker of the chosen candidates and the model the session already used.Anchored real-time UIs · autocomplete · voice and streaming frontends

The automatic routers — three of them

There are three, and warp/auto above is one of them. All three route automatically; they differ in what they route across. Name one as the model string — they are virtual model ids, so any OpenAI SDK applies them by changing one model string.

Router idWhat it doesRecommended workloads
warp/autoDefault — scores each prompt’s difficulty and sends it to the tier that fits.General purpose
warp/codeCode Coding-focused — hard code goes to the frontier, lighter code to a chain of strong coding models.Writing, refactoring and debugging code; coding agents
warp/nitroTop speed Picks the fastest model by measured throughput (tokens/sec) and latency. No difficulty tiers.Real-time UIs · autocomplete · voice and streaming

Anchored routing — keep the model you have

If handing model choice wholesale to warp/auto feels like too much, run it the other way round. Name the model you use today as warp.anchor and it becomes the quality ceiling: hard requests are always answered by that model, and only the easy ones route down a tier. There are two things to decide.

DecisionFieldValue
Quality ceilinganchorThe catalog id of the model you use today. Hard requests are promoted up to it and never above it.
Behaviordialstrict-quality · balanced (default) · max-savings · low-latency — see intent dials.

Omit dial and you get balanced. So the minimal form is one line: the anchor.

request.json
{
  "model": "warp/auto",
  "messages": [{ "role": "user", "content": "Summarize this quarter's metrics" }],
  "warp": {
    "anchor": "anthropic/claude-fable-5"
  }
}

The router decides the rest

Which light model to pair with it, and when to route down, are not yours to pick. The candidates are a curated chain per tier, reviewed against benchmark results and updated by hand when a better model shows up. To keep a model or vendor out, exclude it via model policy rather than picking a replacement.

Tools that cannot send a request body

Tools that speak one fixed wire format — Claude Code, Cursor — have nowhere to put a warp object. They read routing defaults stored on the key instead. Precedence is request > key > org, so an anchor stored on the key applies to every warp/auto request that arrives with it. For per-tool setup, see Tools.

terminal
curl -X PATCH https://api.warp.inc/v1/org/keys/key_abc123 \
  -H "Authorization: Bearer $WARP_ADMIN_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "routing": {
      "anchorModel": "anthropic/claude-fable-5",
      "dial": "balanced"
    }
  }'

Dynamic price tracking

Catalog prices are a snapshot. Actual billing rates sync periodically from the LiteLLM and OpenRouter price feeds (every 6 hours by default), and every change is recorded in the model_pricing history table. Read the current rates with GET /admin/pricing, force an immediate re-sync with POST /admin/pricing/refresh, or pin a specific model’s rate by hand with PUT /admin/pricing/override.

Naming a model explicitly

Catalog ids use the vendor/model form — for example anthropic/claude-fable-5, openai/gpt-5.2, deepseek/deepseek-v3.2. List them all with GET /v1/models. Name a model and the request bypasses routing and passes straight through (classifier_score: null); an id that isn’t in the catalog is rejected with 404 model_not_found. warp.tier does still apply to a named model, as a spend cap: name a model above the cap and the request re-routes through the forced tier, so a budget downgrade cannot be sidestepped by hardcoding a model id.

Per-request warp options

The warp object in the request body lets you control routing and caching behavior per request. Every field is optional.

request.json
{
  "model": "warp/auto",
  "messages": [{ "role": "user", "content": "Design the core API" }],
  "warp": {
    "dial": "strict-quality",
    "anchor": "anthropic/claude-fable-5",
    "session_id": "conv_8f2a91",
    "context_compression": true,
    "no_cache": true
  }
}
FieldTypeDescription
dialbalanced | strict-quality | max-savings | low-latencyThe intent dial for this request. When omitted, the key’s configured dial, then balanced. Applies only when an anchor is in force.
anchorstringThe anchor (ceiling) model id — even an extreme-difficulty query never falls back above this model. Takes precedence over the key’s routing.anchorModel.
cascadebooleanQuality re-check — true by default. A plainly unusable tier-2/3 answer is re-served once from the next tier up. See the router decides the rest. Takes precedence over the key’s routing.cascade.
session_idstringSticky-routing session id — conversations sharing an id are pinned to the model whose prompt cache is warm (check the x-warp-sticky header).
context_compressionbooleanTrims the middle of an over-long prompt (a lost-in-the-middle trim) to fit the context window of a cheaper model.
tier1 | 2 | 3Forces this tier instead of letting the router pick. Applied as a spend cap on every path, including explicitly named models and warp/nitro.
no_cachebooleanDisables both cache lookup and storage for this request.
no_pii_maskbooleanPasses this one request through without masking even when PII masking is enabled on the key.
fallbacksstring[]Explicit-model requests only — a chain of catalog ids appended after the named model. With warp/auto the tier chain already acts as the fallback.
shadowbooleanShadow (validation) mode — the response is served by the anchor (else the frontier baseline) while the router's pick and its estimated cost are only recorded in the warp.shadow response meta (would_model · would_tier · would_cost_usd) and the x-warp-shadow header. Use it to validate the router on real traffic risk-free. Overrides the key's routing.shadow; auto routing only.

How the fallback chain behaves

  • Retry conditions — if an upstream returns 429, 5xx, or an auth/quota error (401, 402, 403), or a network/timeout error occurs, it automatically switches to the next candidate: one provider’s key expiring or running dry is no reason to fail the request. Any other 4xx fails immediately — except one carrying a vendor code that means “this host cannot serve it” (an exhausted balance, an overloaded engine), which fails over like a 429.
  • Switch order — it first tries the same model’s alternate providers (altProviders, e.g. DeepInfra → Novita), then moves on to the next candidate model.
  • Tracing — the attempted path is recorded in the attempts array of the response metadata and the x-warp-attempts header.
  • When all fail — it responds with 502 upstream_unavailable.
  • Budget downgrade — when a key or its team is over budget and the policy is downgrade, every request on that key is forced to Tier 3: automatic routing, an explicitly named model, and warp/nitro alike. See Governance.

Response metadata

Every response carries the routing outcome in the warp body field and the x-warp-* headers.

response.json
{
  "id": "chatcmpl-…",
  "object": "chat.completion",
  "model": "moonshot/kimi-k2.7-code",
  "choices": [ … ],
  "usage": { "prompt_tokens": 21, "completion_tokens": 96, "total_tokens": 117 },
  "warp": {
    "model": "moonshot/kimi-k2.7-code",
    "provider": "moonshot",
    "tier": 2,
    "classifier_score": 0.41,
    "cache_hit": null,
    "cost_usd": 0.000122,
    "saved_usd": 0.003886,
    "latency_ms": 842,
    "pii_masked": 0,
    "attempts": [],
    "dial": "balanced",
    "sticky": true,
    "pipeline": ["difficulty:0.41→tier2", "context:fit=3/3", "sticky:applied"],
    "guardrails": { "mode": "mask", "findings": 0, "blocked": false }
  }
}
HeaderValue
x-warp-modelThe catalog model id that actually served the request
x-warp-tierThe routed tier (1–3). Absent when the request has no tier.
x-warp-cacheexact | semantic | miss
x-warp-cost-usdThe cost of this request (USD, 6 decimal places)
x-warp-saved-usdSavings against the Tier 1 baseline (USD)
x-warp-attemptsAttempt notes recorded for this request (a fallback, for instance)
x-warp-dialThe applied intent dial — balanced · strict-quality · max-savings · low-latency
x-warp-stickytrue | false — whether sticky routing pinned to a cache-warm provider. Absent on cache hits, which return before routing.
x-warp-guardrail-findingsThe number of guardrail findings (present even at 0) — see Tiered guardrails

With streaming the cost isn’t known up front, sox-warp-model · x-warp-tier · x-warp-dial · x-warp-strategy · x-warp-sticky · x-warp-attempts · x-warp-shadow · x-warp-guardrail-findings go out as headers at the start; the stream’s final data chunk (choices: []) carries the full usage and warp metadata, followed by data: [DONE].