Everything that reliably works in LLM evaluation, everything that reliably doesn't, and the shortest path from “we think it's good” to a number you'd bet a release on.
7 Aug 2026Time-boxed: 120 min9 figuresSources: Airbnb ×2, Hamel + Shreya, arXiv, 2026 field reports
Two hours is enough to get the whole discipline, because the discipline is small. Most of what's written about evals is tooling noise around five ideas. This walks the five ideas in order, marks every claim as works or doesn't, and ends with a 30-minute exercise that produces a real artefact.
works proven, do itcaveats useful within limitsdoesn't costs you a quarter
Block 015 minutes
The whole thing in ten claims
If you read nothing else, read this. Every claim below is defended later with a source and a number.
Benchmarks tell you which model is smartest. Evals tell you whether your system works. Confusing the two is the single most common failure mode in the field right now.
Looking at your data beats any framework. Run 100 examples, read every output by hand, write down what went wrong. That habit outperforms every tool you could buy.
Build evaluators only for failures you have actually observed. Imagined failure modes produce metrics nobody acts on.
Off-the-shelf metrics ("helpfulness", "coherence", BLEU, ROUGE) are worse than useless on real products. They give a number that moves without telling you anything, which is worse than having no number.
Three layers, cheapest first: deterministic code checks → LLM-as-judge → human review. Never send to a judge what a regex can catch.
One judge, one dimension, binary output. Three to five sharp judges beat twenty-to-thirty noisy ones. Likert 1–5 scales are a trap.
An uncalibrated judge is worse than no judge — it manufactures false confidence. Calibrate against 50–100 human-labelled examples (including bad ones) and hit high-80s to 90s agreement before you trust it.
Judges are measurably biased: ~10–15 points of win-rate swing from answer order, 15–30 points of inflation for longer answers, 10–25% self-preference. Engineering problems with known mitigations, not reasons to give up.
For agents, the final answer is not the unit of evaluation. Score the trajectory and the tool calls too — a 20-step agent at 95% per-step reliability succeeds end-to-end ~36% of the time.
Eval speed is a product feature. Airbnb went from weeks to same-day mostly by caching judge scores so runs became deterministic — boring systems engineering, not better models.
60–80%of dev time on a production AI system goes to error analysis and evaluation
~100traces to read before your failure taxonomy stops changing
3–5calibrated judges — the right number, not 20–30
~92test cases for statistical power on a medium effect
Block 0215 minutes
The mental model: benchmarks are not evals
A benchmark answers which model is smartest in general. MMLU, SWE-bench, GPQA. Useful once a quarter when you pick a base model. Irrelevant to whether your support assistant hallucinates refund policy.
An eval answers does my system do its job on my traffic. It is built from your failure modes, on your data, with your definition of correct. It is a property of your product, not of the model. You cannot download it.
Fig. 1The scope difference. Swapping to a model that scores five points higher on a benchmark tells you nothing about retrieval, prompt assembly, tool calls or parsing — and that's where most production failures actually live.
The reframe that makes everything else click
An eval is a unit test whose assertion is fuzzy. Everything hard about evals is the work of making a fuzzy assertion trustworthy enough to gate a release on. That's it. That's the discipline.
The three-layer stack
Airbnb's architecture, and the consensus shape across every serious team: escalate only what the cheaper layer can't decide.
Fig. 2The escalation ladder. Each layer exists to protect the budget of the layer below it. Human labels flow back up as the calibration signal for everything — which is why the human layer never disappears, it just shrinks.
Check
Cost to build
Cost to run
Use it for
Assertion / regex / schema
minutes
~0
Anything with a right answer you can express in code
Reference comparison
hours
~0
Tasks with a golden output
LLM-as-judge
100+ labels, then weekly upkeep
$$ per run
Semantic dimensions only code can't touch
Human review
ongoing
$$$$
Ground truth, arbitration, discovery
Doesn't work
Reaching for an LLM judge first. Judges are the expensive layer — they need 100+ labelled examples to validate and weekly maintenance to stay honest. If a broken-JSON failure can be caught by json.loads(), catching it with a judge is paying dollars for a worse answer. Fix the obvious gaps in your prompt before you build eval infrastructure at all.
Block 0325 minutes
The loop that works: error analysis
This is the core. Everything else is scaffolding around it. It comes from Hamel Husain and Shreya Shankar and it is the closest thing the field has to a settled method.
Fig. 3Open coding then axial coding — borrowed from qualitative social science, and the reason the resulting metrics are yours rather than generic. Step 2 is the one people try to skip; it is the one that builds the product intuition everything downstream depends on.
How it actually goes
Sample ~100 real traces. Production traffic if you have it, realistic inputs if you don't. Fewer than 100 and your taxonomy is still moving.
Open coding. Read each output. Write a free-form sentence about what's wrong. No categories yet — categories imposed early are the ones you imagined, not the ones you have. Do this yourself. Delegating open coding to an LLM saves an hour and costs you the product intuition the whole exercise exists to build.
Axial coding. Now group the notes into 5–10 named failure modes. An LLM is genuinely useful here — clustering notes you wrote is fine; writing the notes is not.
Count. Pivot table, failure mode by frequency. This is your priority queue, and the answer to "what should we work on" for the next month.
Fix the top one. Usually a prompt change. Then re-sample and see whether the distribution moved.
The worked example
Airbnb's fictionalised support-policy assistant. 100 test inputs through a first prototype produced four failure modes — and the counts immediately tell you what to build:
Fig. 4The pivot table is the whole output. The counts say: build a faithfulness judge first, and stop arguing about the JSON bug — just fix it. Without the counts this is a meeting; with them it's a plan.
The contradiction you'll hit — and it isn't one
Airbnb brands this "Eval-Driven Development", an explicit analogy to TDD. Hamel Husain writes "don't practise eval-driven development."
They agree completely. Both mean: write evaluators only for failures you have observed in data. Hamel is attacking the TDD reading where you write evals up front for imagined problems; Airbnb's own definition is "discover, encode, and continuously test for failure modes as they emerge." The disagreement is over the name. Don't let the branding confuse you about the method — the method is the loop above, and everyone serious runs it.
Works
Building a scrappy custom annotation UI for your own data. Teams consistently report it being ~10× faster than bending a general-purpose tool to their workflow. It's an afternoon of work and it's the surface you'll live in weekly.
Block 0430 minutes
Judges you can actually trust
This is where most teams' evals quietly stop meaning anything. A judge that isn't calibrated still returns a confident number every run, that number goes on a dashboard, and decisions get made from it. Airbnb's phrasing is the one to remember: a judge without calibration is worse than no judge at all, because it gives you false confidence.
Four design rules, in order of how much they matter
1. One judge, one dimension
No "God evaluator" scoring overall quality. One judge for faithfulness, one for tone, one for conciseness. Compound rubrics can't be debugged — when the score drops you don't know which thing broke. Airbnb's target: 3–5 sharply calibrated judges, not 20–30 noisy ones.
2. Binary, not Likert
Pass/fail. Not 1–5. Likert scales invite the question "what separates a 3 from a 4?", which neither your annotators nor your model can answer consistently; they push mass to the middle; and they need larger samples to detect a real difference. Binary forces the rubric to be sharp, which is the actual goal. This is the 2026 consensus and one of the highest-leverage changes you can make to an existing eval suite.
3. The rubric is the work
Ambiguity in a rubric means humans can't agree either, and if humans can't agree you cannot automate. Airbnb's rule: if your experts disagree on labels, stop. Fix the human disagreement first. Automating an ambiguous standard just scales the ambiguity.
A rubric that works looks like this — criterion, explicit fail conditions, worked examples on both sides:
READABILITY — score 1 or 0.
Score 1 when the text is clean, natural language a guest would read
without friction.
Score 0 when ANY of these hold:
· tone is too formal, too casual, or robotic
· uses internal terminology ("listing entity", "host ops")
· formatting issues: sentence fragments, missing end punctuation
· grammatical errors
· needlessly complex sentence structure
PASS: "This place is a 10-minute walk from the beach and has a full
kitchen."
FAIL: "The listing entity provides beach proximity (approx. 10 min
ambulatory) and comprehensive culinary facilities"
→ internal terminology, robotic tone.
4. Judge with a different model than you generate with
Self-preference is measured at 10–25%. Using the same model as generator and judge builds that bias directly into your release gate. Use a different family, and give the judge chain-of-thought before its verdict.
The calibration protocol — and where the value actually is
You are measuring your judge against a human. That means a 2×2, and the two off-diagonal cells are worth more than the two on-diagonal ones.
Fig. 5Why aggregate accuracy lies. If 90% of your outputs are fine, a judge that always says PASS scores 90% accuracy — with a TPR of zero. Track TPR and TNR separately, always.
Build a golden set of 50–100 examples, human-labelled by someone who knows the domain. Include bad examples. A golden set of only good outputs tests nothing — you're measuring whether the judge can say yes.
Run the judge against it.
Measure agreement. Cohen's kappa or Krippendorff's alpha (they correct for agreement-by-chance, which raw accuracy doesn't). Target high 80s to 90s. Track TPR and TNR separately.
Read the disagreements. The step people skip and where the information is. Airbnb's faithfulness judge started at 78%; reading disagreements revealed it was marking accurate paraphrases as unfaithful. Rubric refinement plus new few-shot examples took it to 88%.
Recalibrate on a schedule. Failure modes evolve, models get silently updated, rubrics age faster than the system under test.
The number to internalise
78% → 88% came from reading the disagreements, not from a better model or a better framework. This is the highest-return activity in the entire discipline and it costs an hour.
The biases, with measured magnitudes
Fig. 6The bias is bigger than the effect. Bars show reported ranges across studies; the three metrics are related but not identical units (win-rate swing, preference inflation, self-preference rate), so read them as magnitudes, not as a single scale.
Bias
Magnitude
Mechanism
Mitigation that works
Position
10–15 pt
Judge prefers a slot, not an answer
Run both orders, average; discard cases that flip
Verbosity
15–30 pt
Longer reads as more thorough
Length-matched pairs; state in the rubric that length is not evidence
Self-preference
10–25%
Perplexity familiarity — a model rates text resembling its own output higher
Different judge family than the generator; never judge with the model you ship
Drift & non-determinism
~1% / run75% of references differ
Sampling plus silent model updates
Cache scores; pin judge versions; treat the judge as a versioned dependency
Doesn't work
Majority-voting or Bayesian-modelling your way out of judge noise. Airbnb tried the instinct and rejected it: it is far cheaper to stabilise the inputs — cache references and scores so identical inputs return identical results — than to model the instability. If your signal margin is 1–3% and your judge drifts 1% per run, no amount of statistics rescues the measurement.
Block 0520 minutes
Technique catalogue: what works, what doesn't
Every named technique you'll hear, placed by what it costs to run against how much it actually tells you about your product.
Fig. 7Live in the top-left. Code assertions are nearly free and tell you the truth — exhaust them before spending anywhere else. The bottom-right is the trap: real money spent on numbers that say nothing about your product. Positions are judgement calls, not measurements.
Technique
What it is
Verdict
When
Error analysisopen + axial coding
Read traces, name failure modes, count them
works
Always. Start here. Nothing else is worth doing first.
Code assertions
Schema, regex, bounds, required fields
works
Everything expressible in code. Cheap, deterministic, ungameable.
Binary LLM judgecalibrated, one dimension
Stronger model applies a sharp rubric, pass/fail
works
Semantic dimensions, after you've validated it against humans.
Pairwise / arena
Judge picks between two outputs rather than scoring one
works
Model and prompt selection. Humans and judges are both better at comparing than at absolute scoring — the cost is you lose an absolute number.
G-Eval
Judge that auto-generates chain-of-thought steps from your criterion, then scores via a form-filling prompt weighted by token log-probabilities
caveats
Good default for subjective dimensions. See below.
DAG / decision-tree evals
Explicit conditional logic; deterministic branches, G-Eval only at the leaves
works
When part of your criterion is objective. More debuggable than a monolithic judge — the 2026 direction of travel.
Rubric-based reward models
Rubrics as the reward signal for RL on non-verifiable tasks
frontier
Post-training research. Not your problem unless you're training models.
Agent-as-judge
Evaluator that can call tools and inspect intermediate state, not just read final text
promising
Multi-step agents where the final answer hides the failure. Early but real.
Distilled judges
Fine-tune a small open model on a frontier judge's labels
for scale
Only once your rubric is stable and judge cost is genuinely the bottleneck. Distillation loses capabilities silently — re-validate against humans, not against the teacher.
Off-the-shelf metrics"helpfulness", "coherence"
Pre-built rubrics shipped by eval libraries
doesn't
Never, on a real product. Generic rubrics produce confidently wrong scores on specialised applications.
BLEU / ROUGE
Lexical overlap with a reference
doesn't
Dead for generative quality. A correct paraphrase scores badly; a fluent hallucination scores well.
Benchmarks as product gates
MMLU, SWE-bench & friends
doesn't
Base-model selection only. Frontier models saturate them; they say nothing about your system.
Vibes / spot-checking
Someone tries ten prompts and says it feels better
doesn't
Fine for the first hour of a prototype. Past that you're shipping on anecdote.
G-Eval, specifically — because you'll be asked about it
Three mechanisms stacked: (1) it turns your natural-language criterion into explicit evaluation steps automatically, (2) a form-filling prompt lets one pass assess several fields — input, output, expected output, retrieved context, (3) it weights the score by token-level log-probabilities instead of taking the raw integer, giving finer granularity than a model that emits "4" every time.
The original paper reported 0.514 Spearman correlation with human judgment on summarisation — the best of its baselines on coherence, consistency, fluency and relevance. That's a real result, and also worth reading honestly: 0.51 is a moderate correlation, not a substitute for human labels.
What G-Eval does not fix
Judge-family lock-in — log-prob weighting needs an API that exposes log-probs.
Position, verbosity and self-preference bias — all still present.
Calibration drift across model versions — your signal silently changes meaning when the judge model updates.
Cost — it's an LLM call per span.
Auto-generated steps are themselves probabilistic — in production, write the steps explicitly rather than letting them be regenerated.
Verdict: a good structured default for subjective dimensions, and strictly better than asking a model "rate this 1–5". Not a replacement for calibrating against humans, and no answer to any of the bias problems.
Tooling, in one paragraph
Experienced teams converge on two tools, not one: a lightweight library for CI gating (DeepEval, Promptfoo, or RAGAS if you're RAG-heavy) plus a platform for human annotation, regression tracking and dashboards (Braintrust, LangSmith, Arize/Phoenix). LangSmith is the path of least resistance inside LangChain; RAGAS is the specialist for retrieval metrics; Promptfoo is strongest for CLI red-teaming and cross-model matrices. But note the ordering: none of these matter until you've done error analysis, because every one of them will happily hand you generic metrics that mean nothing about your product.
Block 0615 minutes
Agents, speed, and production
Agents: the final answer is the wrong unit
Start from the arithmetic that governs everything.
Fig. 8Why per-step measurement is not optional. 0.9520 ≈ 0.36. Scoring only the final answer tells you the agent failed; it can't tell you which step to fix, and the curve says that's the only question that matters.
Three levels, all of which need evals:
Level
What you score
How
Final answer
The last message
Judge or assertion, as above
Trajectory
The sequence of steps taken
Trajectory match against a reference path; step count; loop detection
Per-step / tool call
Right tool, right arguments
Deterministic where args are exact; LLM-judged functional equivalence where they aren't
Practically: tracing is the backbone. Reconstruct execution paths from spans by tree traversal, then attach evals to specific subagents. Without traces you can see that something failed but not where — and "where" is the only actionable part.
Making evals fast enough to iterate on
The second Airbnb piece is really a systems-engineering story, and the most transferable part of the whole set. Their problem wasn't model quality — an eval cycle took weeks, so nobody could iterate.
Separate the two noise sources. Epistemic uncertainty (the judge/model is limited) versus aleatoric uncertainty (the task itself is ambiguous). Conflating them makes you sample more data to fix a problem more data can't fix.
Cache both axes. References keyed by sample ID + generation config; judge scores keyed by sample + model output + judge config + metric. Identical inputs return cached results, so evaluation becomes deterministic and runs become comparable. This is the whole trick.
Bounded mutation instead of retraining. Micro-adapters — LoRA patches of rank <50, under an hour on one GPU — with rules to fuse co-triggering patches and auto-unload unused ones. Days → an hour.
End-to-end validation on representative inputs, stratified across high-volume segments, long-tail locales and prior incidents. Component tests pass while the seams fail.
The line worth stealing
“The debt accumulates at the seams, not in the components.” The leverage was in boring, well-understood systems engineering applied to where LLMs create new failure modes — caching, keying, versioning, determinism. Not in a cleverer metric.
Offline evals, online evals, guardrails — three different jobs
Fig. 9Three jobs, three latency budgets. Confusing them is expensive: a guardrail that takes two seconds is a broken product, and an eval that must run in 50 ms can't do anything interesting. The dashed loop is the part teams forget to build.
The statistics you can't skip
~92 test cases gets you reliable detection of a medium effect (w=0.5) at α=0.005 with 0.90 power. Most benchmarks sit at 261–599 per split, comfortably above. This is why "100 examples" keeps appearing — it's not folklore.
Bootstrap your confidence intervals. Resample with replacement, 500–1,000+ replicates, recompute the metric. If two systems' 95% CIs don't overlap, the difference is real. If they overlap, you're looking at noise. Watch the cost: bootstrapping an LLM judge naively multiplies your API bill by the replicate count — bootstrap over cached scores, not fresh calls.
A 100% pass rate means your eval is too easy. A suite sitting around 70% is doing more work for you than one at 100%. Optimising the pass rate rather than the product is a real and common failure.
Block 075 minutes
Anti-pattern cheat sheet
The consolidated "doesn't work" list. Most of these cost a quarter each.
Anti-pattern
Why it fails
Do instead
Buying an eval platform before doing error analysis
You get generic metrics on a dashboard nobody acts on
Read 100 traces by hand first. Tools after.
Using shipped "helpfulness"/"coherence" metrics
Confidently wrong on specialised apps
Build metrics from your observed failure modes
Writing evals for imagined failures
You test what you feared, not what happens
Only encode failures you've seen in data
One "overall quality" judge
Can't debug a drop; can't act on it
One judge per dimension
1–5 Likert scoring
Ambiguous mid-range, mass at the middle, needs bigger samples
Binary pass/fail
Shipping an unvalidated judge
False confidence — the expensive kind of wrong
50–100 golden labels, kappa in the high 80s, read the disagreements
Judging with the model you ship
10–25% self-preference baked into your gate
Different model family for the judge
Golden set of only good examples
Tests agreement, not discernment
Include known-bad examples deliberately
Outsourcing open coding to a vendor or an LLM
You lose the failure→product feedback loop, which was the point
Domain expert reads the traces; LLM clusters afterwards
Majority-voting away judge non-determinism
Costs N× and doesn't fix the drift
Cache and key results so runs are deterministic
Scoring only the agent's final answer
Hides where a 20-step chain actually broke
Trajectory + tool-call + final, over traces
Optimising for a 100% pass rate
Means the eval is too easy to be informative
Keep the suite hard enough to fail (~70%)
Unversioned prompts
You can't attribute a metric change to anything
Prompts in version control alongside code
Treating benchmark scores as product quality
Different question entirely
Benchmarks for model choice; evals for your system
Block 08Do it
The 30-minute exercise
Reading this gets you the map. This gets you the skill. Pick any LLM feature you or your team already ship — a summariser, an extractor, an agent step, anything with real traffic.
(10 min) Open code 20 outputs. Real ones. One free-form sentence per output on what's wrong, in a spreadsheet. Don't categorise yet. Don't let a model do this.
(5 min) Axial code. Group your notes into named failure modes. You'll get 3–6. Count them. You now have a prioritised list nobody in the org has.
(5 min) Sort them by layer. Which are catchable in code? Which need a judge? Which are just prompt bugs you can fix right now? Usually at least one is a ten-minute fix.
(10 min) Write one binary rubric for the most frequent judge-shaped failure. Criterion, explicit fail conditions, one passing and one failing example — the readability rubric above is the template.
What you should have at the end:
A counted failure taxonomy for one real feature
One binary rubric, written down
At least one fix you can ship today
A concrete sense of what your golden set needs to contain
If you only change one thing
Put 30 minutes a week on the calendar to read 10–20 production traces. Not a dashboard review — the raw traces. Every team that has good evals does this, and it is the only practice on this page that requires no tooling, no budget, and no one's approval.
LLM Evals: Everything You Need to Know — Hamel Husain & Shreya Shankar. Open/axial coding, sample sizes and saturation, binary over Likert, TPR/TNR judge validation, CI vs production, the "don't do this" list.
G-Eval: The Definitive Guide — Confident AI. Mechanism (auto-CoT, form-filling, log-prob weighting), the 0.514 Spearman result, DAG evals.