Auto Router
Send liquid.auto as the model and Auto chooses for you. It ranks the models that pass your rules. It
compares a published score for each model with the estimated charge, within your cap. The auction then
runs as usual, and the receipt records why Auto chose that model.
Artificial Analysis publishes the score of each model. It does not measure the deployment that answers your request, so a higher score does not guarantee a better answer.
Send a request
Add a preference to the name: liquid.auto:premium, liquid.auto:balanced or liquid.auto:economy.
Set a cap, because Auto pays more for a higher score and needs a price bound.
curl https://router.inference.ai.exchange/v1/chat/completions \
-H "Authorization: Bearer $LIQUID_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "liquid.auto:balanced",
"messages": [{"role": "user", "content": "Write a SQL query that finds duplicate emails."}],
"exchange": {"cap_usd": 0.05}
}'
The response says which model answered. The x-liquid-auto-task header says which score ranked the
request. A bare liquid.auto ranks as the exchange sets it, by price or by Auto. See
A router model that ranks by Auto.
Price bounds
One bound is enough:
exchange.rank.cost_tierother thanany: only models whose published rates are within the tier compete.exchange.limits.price.output_usd_per_mtok: only offers at or below this output rate compete.cap_usd, or thex-liquid-cap-usdheader: offers with a higher worst case for this request do not compete. A cap also refuses an unusually large request.
A bound in the preset that the request names, or in the preset linked to your API key, also counts. If no
bound applies, liquid.auto uses its own cap_usd, shown in GET /v1/exchange/routers. The receipt
shows the cap that applied. A basket that asks for Auto has no cap of its own, so the exchange refuses
its request with auto_requires_price_bound.
Choose a preference
The preference sets how many score points each doubling of the estimated charge must buy. A model that costs twice as much wins only if its score is at least that many points higher.
| Preference | Points for each doubling |
|---|---|
premium |
0.5 |
balanced |
2 |
economy |
5 |
To rank by score alone, send liquid.auto:smartest. It ignores the charge, so it needs a price bound.
To rank by speed, send liquid.auto:fastest. See Axis routing.
Without a suffix, set the preference in a strategy:
{ "exchange": { "rank": { "strategy": { "kind": "auto", "preference": "economy" } } } }
A client that can send only headers, such as Claude Code, can use the x-liquid-policy header, or a
preset whose strategy is Auto. See "Presets" in Purchasing rules. If Auto is off, the
exchange refuses to save such a preset with 400 auto_unavailable. If a router model ranks by Auto and
you send no preference, it uses balanced.
Choose the models
liquid.auto ranks every listed model, and the models of your own cloud accounts for your workspace only.
To rank fewer, send exchange.candidates.models.allow: a model name, a deployment symbol or a pattern with *. See "The
basket" in Purchasing rules.
{
"model": "liquid.auto:balanced",
"messages": [{ "role": "user", "content": "Summarise this contract clause." }],
"exchange": {
"candidates": { "models": { "allow": ["gpt-oss-*"] } },
"cap_usd": 0.05
}
}
A preference suffix and "rank": {"strategy": {"kind": "price"}} in one request conflict, and the exchange
refuses the request with axis_conflict.
To rank your own basket, send architect.basket with exchange.candidates.models.allow and
"rank": {"strategy": {"kind": "auto"}}.
What Auto reads from your prompt
Auto ranks by one of two Artificial Analysis scores: the intelligence index for a general request, or the coding index for a coding request. To choose, Auto can ask Jev, a hosted classifier. Jev reads the system prompt and your messages. It does not read assistant turns, tool calls or tool results.
Auto calls Jev only if your data rules allow it:
exchange.privacy.retentionis notnone. If you do not set it, Auto sends the request to Jev.- No region restriction on the request, or on the preset linked to your key, excludes the processing region of the classifier. If the exchange has not named that region, any region restriction stops Auto from calling Jev.
If the classifier or its vendor must not see your requests, set exchange.privacy.retention to none. Auto then
ranks by the general score, and none also limits the offers to those that can obey it.
If a conversation is too long for Jev, Auto cuts the middle of each long message and keeps its start and end. If Auto does not call Jev, or cannot use the answer, it ranks by the general score. The receipt names the reason. See Classifier fallbacks.
Sessions and the cache
Send the same prompt_cache_key on every turn of a conversation. Without a key, the exchange uses a
digest of the first block of the prompt. The exchange records which deployment served the previous turn.
If the cache that turn wrote has more value than another model, Auto keeps the next turn on that
deployment, and the receipt records kept_for_cache. Under exchange.cache.mode: "off" the exchange drops the key and keeps no session. See
Prompt caching.
Response
Two headers arrive before the first token:
x-liquid-auto-task: the score that ranked the request,generalorcoding.x-liquid-auto-fallback: present after a fallback. It holds a classifier fallback reason, such astimeout, orno_eligible_coding_score.
The receipt records the decision in exchange.addressing.auto. See Receipt fields.
Errors
503 auto_unavailable: Auto is off, or the exchange has no score snapshot yet.503 auto_scores_stale: the exchange's copy of the scores is older than its limit.503 no_eligible_offer: no offer passed.eligibility.excludedlists why, anderror.autoholds the decision.400 auto_version_unknown: the version is not 1 to 8.400 auto_requires_price_bound: the request, its preset and the key set no cap, no cost tier other thananyand no output-rate ceiling.400 auto_preference_unsupported: the version does not accept the preference.400 auto_policy_unsupported: the version does not accept the preference sent asexchange.policyorx-liquid-policy.400 strategy_conflicts_with_address: a model, or a router model with no cap, was sent with anautostrategy.400 auto_pin_unsupported: the request sentx-liquid-pin-offer.400 auto_reasoning_unsupported: Auto has no scores for the reasoning effort. Send another effort, a token budget, or none.
Two exclusion reasons are specific to Auto: score_unmapped (no score for the offer's deployment at the
request's reasoning setting) and score_missing (no score for the task). See Errors.
Reference
A router model that ranks by Auto
A router model, such as liquid.auto, ranks its offers by price or by Auto when a request names no
ranking. GET /v1/exchange/routers shows this as ranking, and shows the cap_usd of a router model
that offers Auto.
When it ranks by Auto, a request with no strategy gets Auto at version 8 and balanced. Your choices
always win:
:premium,:balancedand:economyrank by Auto at that preference, even where the router model ranks by price.- A strategy,
exchange.policyor thex-liquid-policyheader sets the ranking that you name. :smartestranks by score alone.:cheapest,:fastestand{"kind": "price"}take the call out of Auto.
The work of the request
If the router model chose the preference, the work of the request can move it one step. Two reads decide the effort:
-
Jev. It rates how much reasoning the latest turn needs: light, standard or heavy. The exchange asks in the same call as the task. It needs a retention policy that is not
none. An answer with a probability of 0.6 or more decides. A light answer does not lower a request that has tool results. -
The envelope. Without a confident answer, the exchange reads token counts, tools, tool results and the reasoning setting, and not the messages. Heavy work in the envelope stays heavy whatever Jev says.
-
heavy: a prompt of 30,000 tokens or more, 4 or more tool results, a reasoning effort ofhigh,xhighormax, or a budget of 8,000 or more. The preference moves one step towardpremium. -
light: a prompt of 800 tokens or less, no tools, no reasoning setting and 3 messages or fewer. It moves one step towardeconomy. -
standard: anything else. It stays.
The preference never moves past premium or economy. It does not move if you chose it or sent a
suffix. The receipt records effort, effort_source (classifier or envelope) and, if the preference
moved, preference_before_effort.
When Auto cannot rank the call
A bare call to a router model that ranks by Auto ranks by price, and does not fail, when Auto is off, the
exchange has no current scores, the request sends x-liquid-pin-offer, or the reasoning setting has no
scores. The receipt shows the reason in exchange.addressing.auto_fallback, such as auto_unavailable
or auto_scores_stale. If you ask for Auto with a suffix or a strategy, the exchange refuses the request
with the code in Errors.
Jobs that are not priced per token
A router model that ranks by Auto buys an image, speech or video job at the lowest estimated charge. Scores are measured on text, so Auto does not rank these jobs, and the cost tier and first-token limit of the router model do not apply. A router model that ranks by price is refused on these endpoints. An embedding job is refused for both. See Modalities.
Classifier fallbacks
The receipt names the reason when Auto ranks by the general score because Jev did not decide: disabled,
not_permitted, input_too_large, unsupported_content, overloaded, timeout, unavailable,
invalid_response, model_mismatch or low_confidence. A Jev answer of coding below the confidence
threshold is low_confidence.
In version 2, a coding request ranks by the general score if offers pass your rules and none has a
coding score. The receipt records routing_fallback: "no_eligible_coding_score". Version 1 finds no
offer and excludes each offer that has no score with score_missing.
Versions
A released version never changes, and a pinned version keeps its rules. Choose one in
exchange.rank.strategy.version, such as {"kind": "auto", "version": "2"}. If you choose none, Auto uses
version 8. The exchange refuses a version other than 1 to 8 with auto_version_unknown.
- 1: score alone. Accepts only
premium.balancedoreconomyreturnsauto_preference_unsupported. - 2: preferences of 0.5, 2 and 5 points. Default
balanced. - 3: available only when the exchange enables it. It has the preferences of version 2 and scores each
exact model. An exact model with no score cannot receive an Auto award. A deployment with no score of
its own uses the score of its exact model.
exchange.addressing.auto.score_originrecords the source. - 4: score alone, and the general score when a coding request has no coding score.
:smartestand{"kind":"smartest"}select it. Accepts onlypremium. - 5: the preferences of version 2, and a session pin.
- 6: version 5, and a few more points for a faster group. See Speed.
- 7: version 6, with three changed rules. See Price guard and Effort in version 7.
- 8: the rules of version 7, ranked by more task classes. See Task classes. The exchange lists it only when an operator turns it on.
Versions 2 and later default to balanced. Versions 1 and 4 default to premium.
Price guard
In versions before 7, a free offer made every other model look very dear. A charge below $0.000000001
counted as that amount, so a model at $0.008 was 23 doublings above a free model and lost 11 points at
premium. Version 7 counts a charge below $0.00001 as $0.00001 and stops the price term at 30 points.
A strong model that costs almost nothing now beats a weak free one. These
numbers are a first setting that no pilot has measured.
Effort in version 7
Versions 2 to 6 move the preference one step for heavy or light work. Version 7 keeps the preference and changes how much price counts. For heavy work it also sets a floor on the score.
| Effort | economy |
balanced |
premium |
|---|---|---|---|
light |
5 points per doubling | 4 points per doubling | 1 point per doubling |
standard |
5 points per doubling | 2 points per doubling | 0.5 points per doubling |
heavy |
2, and a floor of 8 | 0.5, and a floor of 4 | 0, and a floor of 0 |
A floor removes every model that scores more than that many points below the best model that can win. The best model always stays. The numbers are a first setting that no pilot has measured. They apply only when the router model chose the preference.
The envelope can raise the effort to heavy, and it cannot lower it to light, because the size of a
prompt cannot show that a question is easy. Only a Jev answer of 0.6 or more gives light. If Jev is off
or unsure, the effort is standard. The receipt shows envelope_floor as the source when this stopped a
light reading.
Task classes
Version 8 ranks by the score that fits the request. If a class has a score for fewer than half of the models, or no offer that passed your rules has it, Auto ranks by the general score and the receipt says so.
general: Jev, or any fallback. Artificial Analysis intelligence index.coding,math: Jev. Artificial Analysis coding and math indexes.reasoning: Jev. The mean of GPQA and HLE.knowledge,instruction: Jev. MMLU-Pro and IFBench.agentic: a tool definition and at least one tool result. The mean of tau2-bench and Terminal-Bench Hard.long_context: a prompt of 30,000 tokens or more. Artificial Analysis long-context reasoning.
A coding request keeps coding. A tool loop is agentic, and a long prompt with no tool loop is
long_context. A model needs every benchmark of its class to rank. A Jev label needs a probability of at
least 0.5, because it has no held-out measurement yet. Writing, translation and vision have no class,
because no published score covers them.
Speed
Version 6 reads the median output speed that the exchange measured for each provider and model over the last 7 days, when at least 5 timed jobs back it. A provider's own claim earns nothing. A group earns 0.5 points for each doubling of its speed over the slowest measured group, and never more than 1 point. A group with no measured speed earns nothing and loses nothing. So speed breaks a near tie and cannot outbid a gap of more than 1 point. These numbers are a first setting that no pilot has measured.
Session pin
A long conversation is cheap only while the same deployment holds its cache. Versions 5 and later keep a
session on the deployment that served the previous turn. The session needs a stable key: a
prompt_cache_key, an x-session-id header or the first block of the prompt. The deployment stays first
while all of these are true:
- It passes your rules, cap and budget, and its offer can win an award.
- It sells cache reads at a rate below its input rate.
- Jev reads the same task class as on the previous turn.
- Its estimated charge is at most 10% above the same charge at the rates of the previous turn.
- No other deployment has a value more than the margin above it. The margin is 2 score points, added to the value of the pinned deployment.
When one condition is false, the session is released and the normal order decides. The receipt's pin
field says what happened.
Versions 5 and later also price the cache from your workspace. When a deployment has too little history, Auto uses the share of repeated input that providers served from cache for your workspace in the last 7 days. It assumes 50% only when the workspace has no history either.
Two rules in the exchange block control the pin:
exchange.session.pin:on(the default of versions 5 to 8) oroff.offranks every turn again.exchange.session.margin: score points, 0 to 50. A rival must have a value this far above the pinned deployment before the session moves.
Versions before 5 ignore both rules.
Discovery
If Auto is available, two endpoints list it with the same descriptor:
GET /v1/modelshas a card for each router model that offers Auto, withmatch_type: "router"and anautoobject.GET /v1/exchange/routershas an entry with anautoobject, itsrankingand itscap_usd.
default_policy and policies are the version's default preference and accepted preferences. tasks
lists the task classes. effort is preference_step or weight_and_floor. models lists the models that
unpinned Auto can choose now. If Auto is off, neither endpoint lists it.
{
"name": "liquid.auto",
"default_version": "8",
"versions": [
{ "version": "1", "default_policy": "premium", "policies": ["premium"] },
{
"version": "7",
"default_policy": "balanced",
"policies": ["premium", "balanced", "economy"],
"tasks": ["general", "coding"],
"effort": "weight_and_floor"
}
],
"price_bounds": ["cap_usd", "cost_tier", "max_output_usd_per_mtok"],
"models": ["gpt-oss-120b"]
}
Receipt fields
The exchange.addressing.auto object on the receipt records the decision:
-
mode_version,policy,points_per_doubling: the version, the preference and the points per doubling that ranked the request. -
effort,effort_source,preference_before_effort: see A router model that ranks by Auto. -
task,score_field: the score that ranked the request (generalorcoding) and its Artificial Analysis field. -
classification:task, andoutcome:{"kind": "classified"}or{"kind": "fallback", "reason": …}.evidenceholds Jev's answer, when it gave one. -
routing_fallback:no_eligible_coding_score, when a coding request ranked by the general score. -
snapshot_id,scores_validated_at: the score snapshot, and when the exchange last validated its copy. -
score,estimated_charge_usd: the awarded model's score and the estimated charge that ranked it. The actual charge ischarge.total_usd. -
higher_score: a higher score that was passed over, its estimated charge, andreason:value,competitionorunavailable. -
kept_for_cache:expected_cached_tokens,hit_rateandcold_charge_usd, when the cache kept the award on the previous deployment. The estimated saving iscold_charge_usdminusestimated_charge_usd. -
pin: present when the session pin applied.outcomeisheldorreleased;deployment_idandmarginsay which.reasonsays why the session left:incumbent_unavailable,no_cache_discount,task_changed,price_rose,rival_cheaperorrival_above_margin.
A receipt written before these fields existed lacks the fields after task. If a request finds no offer,
error.auto holds the same decision, without score, estimated_charge_usd, higher_score or
kept_for_cache.