Smart Routing
How sansa-auto picks the best model for each request, including sticky sessions and reasoning behavior
With sansa-auto, Sansa picks the best model for each request, balancing quality and cost, and returns the standard response plus a sansa metadata object. To compare it with calling a model directly, see Models.
How to call it
Set model to "sansa-auto" on Chat Completions, Responses, or Messages. On Chat Completions and Responses, null or an omitted model routes too.
{
"model": "sansa-auto",
"messages": [{"role": "user", "content": "Plan a week-long trip to Kyoto."}]
}Any other value is a direct model call (e.g. "openai/gpt-5.4") with no routing; an unknown ID returns 400 invalid_model.
See the code panel for full TypeScript, Python, and curl examples.
What the response tells you
A routed response is a normal response, with:
model: the model that served the request (e.g."anthropic/claude-sonnet-4.6"), not"sansa-auto".usage.cost: the billed cost in USD.sansa: routing metadata. See Thesansaresponse object.
What the router considers
For text requests, the router reads the request and selects a model based on:
- Message content: the main signal.
- Tools: only models that support tool calling are eligible, and
tool_choiceis respected. - Reasoning: see Reasoning with smart routing.
- Input types: image or audio input goes to a model that can read it.
Among the eligible models, the router picks the one that best balances quality and cost.
Sticky sessions for multi-turn
Each sansa-auto request is routed on its own unless you send a prompt_cache_key (or session_id). Send the same one on every turn of a conversation, and Sansa keeps the conversation on one model so its prompt cache stays warm. See Prompt Caching.
See the code panel for curl, TypeScript, and Python examples.
Reasoning with smart routing
On sansa-auto, omitting reasoning defaults to effort: "high", so only models that reason at high effort are considered. This applies to Chat Completions and Responses; Messages treats omitted thinking as disabled. Direct model IDs get no default.
To route to models that don't reason, opt out with "reasoning_effort": "none" or "reasoning": { "enabled": false }:
{
"model": "sansa-auto",
"messages": [{"role": "user", "content": "What is the capital of France?"}],
"reasoning_effort": "none"
}Any reasoning object counts as present, so { "enabled": false } or { "effort": "none" } never triggers the default.
An explicit effort is kept: only models that support it are considered, and the selected model runs at it. See Reasoning for both formats.
What sansa-auto accepts
Reasoning effort is none, low, medium, high or xhigh. minimal is served as low, and max (Messages) as xhigh. none returns 400 when no model can serve the request without reasoning.
These fields return 400 unsupported_parameter on sansa-auto, on every endpoint. Name a model to send them.
temperature,top_p,top_k,frequency_penalty,presence_penalty,seed,logit_biasprediction,service_tier,verbosity,prompt_cache_retention,store: true- A reasoning token budget:
reasoning.max_tokens, orthinking.budget_tokenson Messages modalitiesother than["text"]
Failover
The router ranks several candidate models. If the selected model is rate-limited, down, or returns a transient error, Sansa tries the next one. You get a single response, billed at the rate of the model that answered.
Pricing
Billed at the rate of the model that served the request. See Pricing.