Cut cost with a model fallback
Route every request to a cheaper tier first and escalate to a stronger model only when the cheap answer fails an inline quality check — so the bill drops without quality cliffs, and you only enforce it once the evidence says it wins.
Last updated
On this page
Serve every request from a cheap tier first, grade the cheap response inline, and
escalate to a stronger tier only for the rows the cheap tier can’t handle. The
mechanism is a cascade node in the routing policy:
stages try tiers in order, an accept_when predicate grades each attempt, and a
required final tier is the escalation floor. You promote it to route mode only after
shadow evidence proves the cheaper path holds quality.
Prerequisites
- A running TokenTriage with at least two tiers ordered cheapest → most capable (e.g.
cheapandfrontier) and a decision log configured (ledger.decision_log.path). - The oracle judge configured (
classifier.oracle) — the inline cascade judge reuses it. Without a wired judge, ajudge: truestage yieldsoutcome.judge.available = falseand theaccept_whenbelow escalates rather than inventing a verdict. shadow.duplicateavailable for the promotion step (below).
1. Write the cheap-first cascade policy
routing.policy is the v2 routing form and is mutually exclusive with the legacy
routing.rules list — a config sets exactly one. Make the root a cascade: try cheap,
run the inline judge, and escalate to frontier only when the attempt isn’t a clean,
non-refusing, judge-approved 200.
routing:
default_tier: frontier # fail-safe target on classifier error (never a downgrade)
policy:
version: 1
root:
cascade:
stages:
- id: try-cheap
to: { tier: cheap }
judge: true # run the inline shadow judge before accept_when
accept_when: 'outcome.status = 200 and outcome.refusal_markers = 0 and outcome.judge.available and outcome.judge.ok'
final: { tier: frontier } # always accepted — the escalation floor
Only outcome-scope inputs are legal inside accept_when: outcome.status,
outcome.refusal_markers, outcome.judge.ok, outcome.judge.available,
outcome.finish_reason, outcome.latency_ms, and the token/byte facts. An absent
outcome.judge.available reads false, so the ... and outcome.judge.available and outcome.judge.ok form escalates when the judge is down — it never accepts on a fabricated
verdict.
Validate it strictly before running:
$ tokentriage validate --config configs/tokentriage.yaml
2. Climb the ladder: run it in shadow first
Don’t flip straight to route. Set the top-level mode: shadow and turn on shadow
duplication so TokenTriage grades the cheaper tier against the stronger one on the same
query — the only data that can prove the cheaper path holds quality:
mode: shadow # observe + grade the counterfactual; client bytes unchanged
shadow:
duplicate:
enabled: true
sample_rate: 0.01
max_usd_per_day: 5.00 # hard cap; the sampler stops when exhausted
judge: oracle
In shadow mode the client still sees identical bytes — you’re accumulating graded rows,
not enforcing. Let traffic run, then read the shadow-savings total:
$ tokentriage report --log ~/.tokentriage/decisions.jsonl
=== TokenTriage shadow-savings report ===
routed rows: 560 of 560 (rows with a routing decision + would_usd)
not-routing spend: $3.731000 (served on the top tier)
routed spend: $1.305850 (under the routing decision)
savings: $2.425150 (65.0% vs not routing; 455 of 560 rows routed cheaper)
(Illustrative output — your totals come from your own log.)
3. Read the honesty verdict before you promote
report shows the savings; eval --quality shadow answers the question that licenses
enforcement — does the cheaper routing actually beat a blind model mix at its own cost?
Only the shadow (counterfactual) source can return a BEATS verdict:
$ tokentriage eval --quality shadow --log ~/.tokentriage/decisions.jsonl
=== TokenTriage honesty eval ===
verdict: routing BEATS zero-router by 0.2500 (counterfactual: judged shadow duplication)
quality source: shadow (labeled iff judged-shadow grade present (chosen_ok != nil); counterfactual per-cost verdict from both tiers' grades)
labeled rows: 8 of 8
… (per-tier TIER POINTS table elided)
FRONTIER (per-cost verdict basis: router quality vs zero-router at the router's own cost)
router quality: 1.0000 @ cost $5.500000
zero-router @ router: 0.7500
delta: +0.2500
If instead you see insufficient labels to judge routing or a served-model source sitting
ON the observed-model frontier (Δ 0.0000), you do not have a promotable win yet —
oracle/outcome labels score only the tier that served each row and can never show routing
skill. Keep it in shadow and let judged-shadow grades accumulate.
4. Promote to route mode
Once the verdict is a BEATS and the promote gate is satisfied, enforce it:
mode: route # enforce the cascade — cheap first, escalate on failure
You should see the cheap tier serving the accepted rows and only the failing rows carrying
a frontier attempt. Inspect a decision’s cascade with policy explain, which prints
cascade: attempts=N final=<tier> and one line per stage (id tier model accepted cost=$…):
$ tokentriage policy explain --req-id <req-id> --log ~/.tokentriage/decisions.jsonl
(The accept_when reads and the block-level judge_cost are recorded in the decision-log
cascade block itself — the JSON row / dashboard drawer — rather than printed by this command.)
Related: availability fallback vs. quality escalation
The cascade above is a quality fallback — it escalates on a graded outcome. If instead
you want an availability fallback — try tiers in a deliberate order and serve the first
one that isn’t cooling down — use a select with the first_eligible selector over an
ordered candidate list. It picks the first survivor of the where filter and never draws
randomness:
routing:
policy:
version: 1
root:
select:
from: { tiers: [mid, frontier, cheap] } # deliberate order, not cost rank
where: 'candidate.healthy'
by: { selector: first_eligible }
on_empty: { refuse: { status: 503, reason: "all_upstreams_cooling" } }
This cuts cost by preferring a cheaper-but-healthy tier and only failing over on a cooldown — it does not grade the response, so pair it with the cascade above when you also need a quality safety net.