From probability to automation
The idea in one line: A calibrated probability plus a price list of mistakes tells you when to act, when to ask and when to escalate; automate the confident share, route the rest, and your savings grow as 1 / (1 − share automated).
Why this matters
Section titled “Why this matters”Accuracy is a 10% lever. Coverage is the 10x one. Coverage is the share of cases you let the model decide on its own. Suppose the big model (or person) costs 100 times the small one and every case tries the small model first. Automating 80% of cases makes the whole pipeline 4.8x cheaper; 95% makes it 16.7x cheaper; 99% makes it 50x cheaper. The order-of-magnitude win sits in the last few points of coverage, and you may only claim those points if the model’s confident cases are verifiably right. That is why the previous lesson mattered: calibration is what lets you certify coverage.
This lesson climbs from one decision to a whole system: the threshold for one case, the abstain option, guaranteed shortlists, cascades, and the arithmetic that ties them together.
Expected cost and the threshold
Section titled “Expected cost and the threshold”The intuition: an umbrella
Section titled “The intuition: an umbrella”Carrying an umbrella costs you 1 unit of hassle. Getting soaked costs 9. If the chance of rain is p, leaving the umbrella costs you 9p on average, and carrying it costs 1 for sure. Carry it when 9p ≥ 1, that is when p ≥ 1/10. You carry an umbrella at a 10% chance of rain, not at 50%, because the mistakes cost different amounts.
The precise version
Section titled “The precise version”Expected cost is each outcome’s cost weighted by its probability (from probability is the product). For a yes/no decision with probability p that the case is positive, a false positive (acting when you shouldn’t) costing C_FP, a false negative (not acting when you should) costing C_FN, and correct calls costing nothing, act when (1 − p) × C_FP ≤ p × C_FN. Rearranged:
act when p ≥ t* = C_FP / (C_FP + C_FN)Elkan derived this and showed that moving the threshold is the principled response to a new cost matrix; rebalancing the training data is the indirect equivalent (Elkan, IJCAI 2001). The umbrella: C_FP = 1 (carried it for nothing), C_FN = 9 (soaked), so t* = 1/10.
Worked example: auto-merging dependency bumps
Section titled “Worked example: auto-merging dependency bumps”A model scores each dependency bump for a bootc distro image with p = P(the bump builds and boots). The costs are invented for illustration:
- Merging a bad bump, C_FP = $400 (a broken nightly image, an hour of debugging).
- Rejecting a good bump, C_FN = $40 (redo it later, a delayed security fix).
- A human review, $20, and assume the human is always right.
Two actions (merge or reject): t* = 400 / (400 + 40) = 0.909. Merge only above 0.91.
Three actions (merge, reject or review): merging costs 400(1 − p), rejecting costs 40p, review costs a flat 20. Merge beats review when 400(1 − p) ≤ 20, so p ≥ 0.95. Reject beats review when 40p ≤ 20, so p ≤ 0.50.
One dependency bump: the cheapest action for each p
p: 0.0 0.50 0.95 1.0 |------------------|--------------------------|--------| auto-reject a person reviews it merge (40p <= 20) (a flat $20) (400(1-p) <= 20)# Pick the cheapest action for a calibrated p (costs from the example)C_FP, C_FN, C_REVIEW = 400, 40, 20 # bad merge, wrong reject, a person
def expected_costs(p): """p = P(the bump builds and boots); correct calls cost nothing.""" return {"merge": (1 - p) * C_FP, # we merged a bad bump "reject": p * C_FN, # we rejected a good bump "review": C_REVIEW} # a person decides, always right
def best_action(p): costs = expected_costs(p) return min(costs, key=costs.get)
for p in (0.40, 0.80, 0.96): print(p, best_action(p)) # 0.4 reject, 0.8 review, 0.96 mergeWhat miscalibration costs. Say the model reports 0.97, but bumps at that score really succeed 90% of the time. Each auto-merge now costs 400 × 0.10 = $40, twice the $20 review. Automation loses money on every item. If 0.97 really meant 97%, each merge costs 400 × 0.03 = $12, saving $8 against review. Same accuracy, same ranking, opposite business result.
Information is worth most at the threshold
Section titled “Information is worth most at the threshold”The expected value of perfect information is how much you would pay to know the truth before acting: the expected cost of your best action now, minus the cost if you knew the truth (zero here, since correct calls cost nothing). Without the review option it is min(400(1 − p), 40p):
| p | 0.50 | 0.80 | 0.909 (the threshold) | 0.95 | 0.99 |
|---|---|---|---|---|---|
| Value of knowing ($) | 20.0 | 32.0 | 36.4, the peak | 20.0 | 4.0 |
A check (a person, a frontier model, a CI build) is worth buying when it costs less than that. Far from the threshold, nobody needs to look; near it, information pays most. That is the formal case for cascades: send only the near-threshold band to something expensive. It only works if p is calibrated, because a miscalibrated p puts the band in the wrong place.
Why a calibrated probability beats an accurate label:
- Costs change and thresholds follow, without retraining. In a security-patch week, C_FN rises; recompute t*. A label hard-codes one threshold, usually 0.5.
- Accuracy is measured at the wrong threshold. With t* = 0.91, accuracy at 0.5 says little about cost.
- It sizes the work. The expected number of cases in the review band tells you how many reviewers you need.
- It composes. Calibrated probabilities can be multiplied through a pipeline and updated with Bayes’ rule when base rates shift.
- It makes errors auditable. “We automated above 0.95 and saw 2.1% errors against 3% predicted” is a testable contract; “the model said yes” is not.
Selective prediction: answer only when sure
Section titled “Selective prediction: answer only when sure”Selective prediction lets a model abstain. Coverage is the share of inputs it answers, and selective risk is its error rate on those. Sort cases by confidence, accept from the top, and the error rate at each coverage traces a risk-coverage curve.
A worked example with 10 made-up cases:
| Rank | Confidence | Right? | Coverage | Errors so far | Selective risk |
|---|---|---|---|---|---|
| 1 to 5 | 0.99, 0.97, 0.95, 0.93, 0.90 | all yes | 50% | 0 | 0% |
| 6 | 0.85 | no | 60% | 1 | 16.7% |
| 7 | 0.80 | yes | 70% | 1 | 14.3% |
| 8 | 0.70 | yes | 80% | 1 | 12.5% |
| 9 | 0.60 | no | 90% | 2 | 22.2% |
| 10 | 0.55 | no | 100% | 3 | 30.0% |
If you can live with 15% errors, you can automate 80% (threshold 0.70). If you need zero errors, 50% (threshold 0.90). With only 10 cases those numbers are noise, which is why the label counts matter.
Note what drives the curve: only the order of confidences (discrimination), not their calibration. Calibration matters for choosing and predicting the operating point: a calibrated model tells you threshold 0.97 means about 3% errors before you have labelled anything there. The classic result: selective classification held ImageNet top-5 error to 2% “with probability 99.9%” at “almost 60% test coverage” (Geifman & El-Yaniv, 2017-05-23). The area under the curve, AURC, summarises the whole trade-off; lower is better.
# Risk-coverage curve and the largest share you can automateimport numpy as np
def risk_coverage(conf, correct): """Accept the most confident first; error rate among accepted.""" order = np.argsort(-np.asarray(conf, float)) errs = 1 - np.asarray(correct, float)[order] k = np.arange(1, len(errs) + 1) coverage, risk = k / len(errs), np.cumsum(errs) / k return coverage, risk, risk.mean() # last value: AURC
def coverage_at_risk(conf, correct, target=0.02): """Largest coverage with selective error <= target, and threshold.""" cov, risk, _ = risk_coverage(conf, correct) ok = np.flatnonzero(risk <= target) if ok.size == 0: return 0.0, None return float(cov[ok[-1]]), float(np.sort(conf)[::-1][ok[-1]])
conf = [0.99, 0.97, 0.95, 0.93, 0.90, 0.85, 0.80, 0.70, 0.60, 0.55]right = [1, 1, 1, 1, 1, 0, 1, 1, 0, 0]print(coverage_at_risk(conf, right, target=0.15)) # (0.8, 0.7)The operating loop for any decision API:
- Label a held-out set from real traffic and compute the risk-coverage curve.
- Pick the target error rate for automated cases from business costs.
- Read off the largest coverage that meets it, and its confidence threshold.
- Confirm on a second held-out set, because a threshold tuned on one set is optimistic on that set.
- Route the rest to a person, a bigger model, or a cheaper check such as running the build.
Step 4 is not pedantry. Vals AI set a 1% error budget for Jev; it reached 95% coverage but a realised error of 1.6%, over budget. Sonnet 5.5 managed 100% coverage at 0.4% (Vals AI, 2026-10-06).
Conformal prediction: a shortlist with a guarantee
Section titled “Conformal prediction: a shortlist with a guarantee”The intuition
Section titled “The intuition”Instead of one answer, the model hands you a short list, with a promise: “the right answer is on this list 90% of the time”. A list of one means it is sure; a list of three means “one of these”; an empty list means “nothing I know fits”. Conformal prediction builds such lists around any model’s scores, using a small labelled calibration set (Angelopoulos & Bates, 2021-07-15).
A tiny worked example
Section titled “A tiny worked example”A package-triage model labels each package ok, flaky or broken. You have n = 9 labelled calibration packages and want 80% coverage, so the error rate α = 0.2.
- For each calibration package, take the probability the model gave the true label: 0.95, 0.90, 0.85, 0.80, 0.70, 0.60, 0.55, 0.40, 0.20.
- Turn each into a nonconformity score, how badly the model fit the truth: s = 1 − p, giving 0.05, 0.10, 0.15, 0.20, 0.30, 0.40, 0.45, 0.60, 0.80.
- Let k = ⌈(n + 1)(1 − α)⌉ = ⌈10 × 0.8⌉ = 8. The threshold q̂ is the 8th smallest score: 0.60.
- For a new package, include every label with 1 − p ≤ 0.60, that is p ≥ 0.40.
| New package | p(ok), p(flaky), p(broken) | Set | What to do |
|---|---|---|---|
| A | 0.55, 0.35, 0.10 | ok | One label: automate |
| B | 0.45, 0.42, 0.13 | ok or flaky | Ambiguous: a person, or run the build |
| C | 0.36, 0.34, 0.30 | empty | Nothing fits: likely unusual, flag it |
The guarantee, if new data is exchangeable with the calibration data (roughly, drawn from the same process, order carrying no information):
1 − α ≤ P(true label is in the set) ≤ 1 − α + 1/(n + 1)Here that is between 80% and 90% over many packages. But with only 9 calibration points, the coverage you actually get from this calibration draw is spread out: it follows a Beta(8, 2) distribution with mean 0.80 and standard deviation about 0.12. With n = 1,000 and α = 0.1, coverage “typically” lands between 0.88 and 0.92. To be within ±ε of target with probability 0.9 (α = 0.1), you need 22 calibration items for ε = 0.1, 102 for 0.05, 2,491 for 0.01 and 9,812 for 0.005 (Angelopoulos & Bates, Table 1).
# Split conformal prediction sets for any classifier's probabilitiesimport numpy as np
def conformal_qhat(cal_probs, cal_labels, alpha=0.1): """q-hat: the k-th smallest score s = 1 - p(true label).""" n = len(cal_labels) scores = np.sort(1 - cal_probs[np.arange(n), cal_labels]) k = int(np.ceil((n + 1) * (1 - alpha))) # finite-sample rank return np.inf if k > n else scores[k - 1] # too few points: keep all
def prediction_sets(probs, qhat): """Boolean mask (n, K): label k is in the set when p_k >= 1 - qhat.""" return probs >= 1 - qhat
# qhat = conformal_qhat(cal_probs, cal_y, alpha=0.1)# S = prediction_sets(test_probs, qhat)# coverage = S[np.arange(len(test_y)), test_y].mean() # about 0.9# automate = S.sum(1) == 1 # one-label setsOn a synthetic 10-class model, α = 0.1 gave 89.3% test coverage, but the average set held 4.7 labels because that model was only 44% accurate (the researcher’s own run). Weak models get valid but useless sets.
What conformal does and does not promise
Section titled “What conformal does and does not promise”| It guarantees | It does not guarantee |
|---|---|
| Coverage of at least 1 − α, averaged over inputs and calibration draws | Coverage for each input or each subgroup: “in the most general case, conditional coverage is impossible to achieve” |
| Finite-sample, distribution-free, for any model, black boxes included | Validity under distribution shift or feedback loops |
| No wasteful over-coverage: at most 1 − α + 1/(n + 1) | Small or useful sets |
| Correct labels: noisy calibration labels give coverage of the noisy label |
Source: Angelopoulos & Bates.
Upgrades to know:
- APS (adaptive prediction sets) adds labels in probability order until their mass passes the threshold, which covers hard cases more evenly (Romano, Sesia & Candès, 2020-06-03). RAPS trims unlikely tail labels and gave sets “often factors of 5 to 10 smaller” than a Platt-scaling baseline on ImageNet (Angelopoulos et al., 2020-09-29).
- Conformal risk control bounds “the expected value of any monotone loss function”, such as the false-negative rate, for when different mistakes cost different amounts (Angelopoulos et al., 2022-08-04).
- For LLMs, conformal factuality backs off an answer until it is correct with probability 1 − α, reaching “80-90% correctness guarantees while retaining most of the model’s original output” (Mohri & Hashimoto, 2024-02-15).
Cascades and routing
Section titled “Cascades and routing”A cascade tries a cheap model first and escalates when it is not confident. A router picks one model per query up front. Both are selective prediction with a bigger model as the fallback, and you can end the chain with a person.
C4 · L2 Container · Decision cascade
+-----------+ | [Person] | | Requester | +-----------+ | sends a case (HTTPS/JSON) v..................... Decision cascade [system] ....................: :: +----------------------+ scores (gRPC) +--------------------+ :: | [Container: Python] |---------------->| [Container: ONNX] | :: | Cascade router |<----------------| Decision model | :: | thresholds per type | distribution | tier 1, cheapest | :: +----------------------+ +--------------------+ :: | | | :: | | | logs case, answer, outcome (SQL) :: | | v :: | | +--------------------+ :: | | | [Database: SQLite] | :: | | | Outcome log | :: | | +--------------------+ :: | | :: | | queues what tier 2 +------------------+ :: | +----------------------->| [Container: Web] | :: | left unsure (SQL) | Review queue | :: | +------------------+ :: | | ::.....|........................................|...................: | escalates the | shows cases | middle band (HTTPS/JSON) | (HTTPS) v v+---------------------+ +-------------+| [External system] | | [Person] || Frontier LLM API | | Reviewer || tier 2, slower and | | tier 3, the || pricier | | last word |+---------------------+ +-------------+The router asks the small decision model first and acts on confident answers. It sends the near-threshold band to a frontier LLM, and queues whatever is still unsure for a person. Every case and its eventual outcome lands in the log, which becomes the labelled data for refitting the temperature and thresholds. New to these boxes? See how to read the diagrams.
Real examples of the pattern: a community “smart tier” runs Jev first and re-asks a reasoning model only under 0.7 confidence (JevBench results); TypeSafe’s own docs route intents to “deterministic logic, a specialist LLM, or a human” (TypeSafe docs: Patterns, read 2026-10-28).
Published savings
Section titled “Published savings”| System | Date | Published result |
|---|---|---|
| FrugalGPT | 2023-05-09 | Matches GPT-4 with up to 98% cost reduction, or +4% accuracy at equal cost (Chen, Zaharia & Zou) |
| Hybrid LLM | 2024-04-22 | Up to 40% fewer calls to the large model with no quality drop (Ding et al.) |
| RouteLLM | 2024-06-26 | Over 85% cost cut on MT Bench, 45% on MMLU, 35% on GSM8K, at 95% of GPT-4 quality (LMSYS blog) |
| BEST-Route | 2025-06-28 | Up to 60% cost cut with under 1% performance drop (Ding et al.) |
| Semantic agreement cascades | 2025-09-26 | Target-model quality at 40% of the cost, up to 60% lower latency, no training (Soiffer et al.) |
| Calibrated deferral for guardrails | 2026 | ECE 6-28% out of the box, under 2.5% after recalibration; a 2B-to-8B cascade within 1 point of the 8B at 55% lower cost (Cornacchia et al.) |
| Conformal Cascade | 2026-07-27 | Accept the small model only when its conformal set has one answer; coverage at least 1 − Kα across K tiers (Dou, Lian & Li) |
The guardrail result is the strongest evidence that recalibration is the first step of any cascade: an uncalibrated tier 1 escalates the wrong cases.
The critiques
Section titled “The critiques”- Routing collapse. One source reports that as budgets rise, existing routers send nearly 100% of queries to the strongest model, while an ideal router would need it for fewer than 20%. At the largest budget, 94.9% of queries had a near-zero quality gap between the top two models, so tiny score errors flip choices (When Routing Collapses, 2026-02).
- Savings depend on your traffic. RouteLLM’s own savings range from 35% to 85% across three benchmarks. Savings track how many queries a cheap model can answer, which is a property of your workload, not the router.
- “95% of GPT-4 quality” means losing 5% of the gap, which may be unacceptable when mistakes have lopsided costs.
- Production routers publish no savings. OpenAI’s GPT-5 router picks a fast or a reasoning model by “conversation type, complexity, tool needs, and explicit intent”, with no savings figure given (GPT-5 system card, 2025-08-13).
The arithmetic that gives 10x
Section titled “The arithmetic that gives 10x”Every case hits the small model; only the uncovered share goes on to the big one:
cost per case = c_small + (1 − coverage) × c_bigsaving vs big = c_big / cost per caseWith c_big = 100 × c_small:
| Coverage at your target error | Cost against big-only | Saving |
|---|---|---|
| 80% | 0.21 | 4.8x |
| 90% | 0.11 | 9.1x |
| 95% | 0.06 | 16.7x |
| 99% | 0.02 | 50x |
Check the first row: 1 + 0.2 × 100 = 21 units per case against 100, so 100 / 21 = 4.8x.
# Cascade saving against sending every case to the big modeldef cascade_saving(coverage, price_ratio): small, big = 1.0, float(price_ratio) # small model costs 1 unit per_case = small + (1 - coverage) * big # all cases try small first return big / per_case
for cov in (0.80, 0.90, 0.95, 0.99): print(cov, round(cascade_saving(cov, 100), 1)) # 4.8 9.1 16.7 50.0print(round(cascade_saving(0.90, 440), 1)) # 9.8: a bigger gap barely helpsThe last line is the surprise. On TypeSafe’s own table, Opus 5 costs about 440 times Jev per case ($0.1761 against $0.0004, TypeSafe evals, read 2026-10-28). Yet at 90% coverage the cascade saves only 9.8x, because the escalated 10% dominates the bill. As the price gap grows, the saving approaches 1 / (1 − coverage) and stops there: 10x at 90%, 20x at 95%, 100x at 99%. Coverage, not the price gap, sets the ceiling.
Two reality checks keep this honest:
- Other work dilutes the gain. One source, a scan of 12,759 Jev launch tweets, found a median user-reported speed-up of 7x, far below the headline multiples, because real workflows do more than decide (InfoQ, 2026-10-01). The is 5x real? lesson applies that reasoning to a distro workflow.
- The coverage must be certified. Each extra point of coverage at a fixed error rate needs labels to prove it: about 753 automated items to pin a 2% error rate within ±1 point, or 300 error-free ones to claim at most 1% (calibration).
The frontier and its open problems
Section titled “The frontier and its open problems”- Conditional guarantees. Conformal coverage is an average; per-subgroup coverage is impossible in general, and the active research is conditional validity, shift and open-ended generation (Cherian, Gibbs & Candès, 2024-06-14).
- Shift and feedback loops. Once you automate, the cases a person sees change, and so does the data you recalibrate on. Exchangeability, the assumption under every guarantee here, quietly breaks.
- Routers that over-escalate, per the routing-collapse critique, and no published savings from production routers.
- RL that erodes abstention. Reasoning fine-tuning cut abstention by 24% on average across 20 frontier models (AbstentionBench, 2025-06-10), so the big model in tier 2 may itself be bad at saying “I don’t know”.
- Vendor guarantees. No decision-model vendor publishes coverage at a stated error rate on ground-truth labels, as of October 2026. That is a gap a founder can fill.
Check yourself
Section titled “Check yourself”Blocking a legitimate payment costs $5 and letting a fraud through costs $95. Above what fraud probability should you block?
Blocking a legitimate payment is the false positive here, so t* = C_FP / (C_FP + C_FN) = 5 / (5 + 95) = 0.05. Block at a 5% fraud probability, far below 50%, because missing fraud costs 19 times more.
In the dependency-bump example, why does a model that says 0.97 but is right 90% of the time lose money on auto-merges?
The real chance of a bad merge is 10%, so each auto-merge costs 400 × 0.10 = $40 on average, more than the $20 review it replaced. A calibrated 0.97 would cost $12. Same ranking, opposite result.
Does a better-calibrated model have a better risk-coverage curve?
Not necessarily. The curve depends only on how confidences are ordered (discrimination). Calibration tells you which threshold gives which error rate before you label cases at that threshold, and lets you predict the realised error.
A conformal set for a new case comes back empty. What does that tell you, and what should the system do?
No label reached the threshold probability, so the model sees nothing plausible: the input is likely unlike the calibration data. Flag it and route it to a person or a bigger model rather than guessing.
Tier 2 costs 1,000 times tier 1, and you can automate 90%. Roughly how much cheaper is the cascade than tier 2 alone?
About 9.9x: 1,000 / (1 + 0.1 × 1,000) = 1,000 / 101. The ceiling is 1 / (1 − 0.9) = 10x however big the price gap. To go further you must raise coverage.
Go deeper
Section titled “Go deeper”- Elkan, The Foundations of Cost-Sensitive Learning, IJCAI 2001 — the threshold rule and why thresholds, not retraining, answer new costs.
- Angelopoulos & Bates, A Gentle Introduction to Conformal Prediction, 2021-07-15 — the best practical guide, with code and sample-size tables.
- Geifman & El-Yaniv, Selective Classification for Deep Neural Networks, 2017-05-23 — abstention with a guaranteed error rate.
- RouteLLM (LMSYS), 2024-07-01 — a router with published savings, and how they vary by benchmark.
- Cornacchia et al., Calibrated Deferral Routing for Cost-Efficient Guardrails, ICML 2026 workshop — why recalibration comes before any cascade.
- When Routing Collapses, 2026-02 — the strongest critique of trained routers.