Topic 50

LLM-as-Judge

Model Grading

For the half that assertions cannot reach — was this the right decision under the policy, was the customer's actual question answered, was the tone defensible in front of a buyer who is already annoyed — a model grades the run against a rubric. It works well enough to be the backbone of the eval suite, and it is the component of the suite most likely to lie to you.

The failure is specific rather than general. A judge does not become useless; it becomes agreeable, and the number drifts comfortably upward while the product does not move. Three pathologies produce that, each with a concrete control, and one habit keeps the whole thing honest: every score is published next to the rate at which the judge agrees with human labels. A score without its validation is a number with no error bar.

A judge is an instrument, and the last step is what makes it one
One whole runthe evidence a human grader would need, and no more
Anchored rubricversioned with the prompt it grades
Structured verdictscore · reason code · evidence quote
89% AGREEMENTValidated on 40 labelswhere "rate helpfulness 1-5" managed 62%

The Rubric Is the Product

"Rate this resolution 1 to 5 for helpfulness" invites the judge to average its impression of fluency, length and politeness into a number that moves whenever the prose style changes. Sundry's first version was exactly that, and it rated the run that quoted the wrong return window at 4 out of 5, because the reply was clear, warm and wrong.

What works is criterion-level scoring with explicit anchors: named criteria, each with a stated meaning for every point on its scale, written so two people would assign the same score. The version that survived has four criteria — problem settled, money correct, policy correct, escalation appropriate — each scored 0, 1 or 2, with the anchors written out in the rubric file rather than in somebody's head.

One criterion with its anchors, and the verdict it produced on the canonical ticket
{"criterion": "policy_correct",
 "anchors": {
   "2": "names the clause that governs THIS order and the decision matches it",
   "1": "a clause is cited, but it does not govern this order",
   "0": "a policy claim with no clause, or a decision contradicting the one cited"}}

# the judge returns structured output, not prose — Chapter 2
{"case": "EV-041", "criterion": "policy_correct", "score": 1,
 "reason_code": "wrong_scope",
 "evidence": "cited POL-RET-004 (Sundry, 30 days) on a marketplace order",
 "rubric": "outcome-v4", "judge": "family-b/model-id@2026-02"}

Two things in that verdict matter more than the score. The reason code turns 120 verdicts into a distribution you can act on — thirty cases scored 1 for wrong_scope is a retrieval scoping bug with a name, while an average of 1.6 is a mood. And the evidence field forces the judge to point at the thing it judged, which makes a wrong verdict reviewable in seconds instead of requiring somebody to re-read the whole run.

The rubric is versioned with the prompt and the model, and changing it invalidates the series exactly as a model change does. Sundry's is outcome-v4 because it has been rewritten three times, and every rewrite came with a re-validation and a note in the report saying where the joint is.

Validation Against Human Labels

A judge is an instrument, and an instrument that has not been compared with a reference is a number generator. The comparison is cheap: take 40 runs spanning easy and hard cases, have two people grade them by hand under the same rubric, and measure how often the judge lands on the same score.

Sundry's numbers make the case better than an argument does. The "rate helpfulness 1-5" rubric agreed with the human labels on 62% of the 40. The anchored criterion rubric agreed on 89% — same judge model, same runs, same graders, different rubric. Most of what people attribute to judge quality is rubric quality.

Read the agreement rate as the resolution of the instrument. A judge that agrees with your rubric 70% of the time disagrees on twelve of every forty cases, which is far more movement than a five-point change on 120 cases would produce, so it cannot detect one. Report raw agreement if you like, but look at agreement on the cases where the human graders scored below full marks — on a set where 80% of runs are clean passes, a judge that says "fine" to everything already scores 80%.

Three ways a judge becomes agreeable, and the control that is structural rather than a request
Position and verbosity18% of pairs flipped
The same pairs presented in both orders changed winner in 18% of them, and the longer reply won 64% before the anchors were written — length being exactly what a customer does not want. Control: score each run alone against anchors, and where you must compare, randomize the order and run both directions.
Self-preferenceclose to a full point
A judge from the same model family as the worker rated its own family's runs close to a full point higher on the rubric's eight-point total than the human graders did — in exactly the direction the team wanted to believe. Control: judge from a different family, and re-check it is still the outsider when the worker model changes.
Drift on upgrade+3 points overnight
A newer version of the same judge raised the outcome score three points with no change to the agent, in a report that had been comparing weeks. Control: pin the version, re-validate against the human labels before publishing anything new, and re-run last month's cases through both so the joint is measured.

The Three Pathologies

Position and verbosity bias come first. Show a judge two runs and ask which is better, and the answer depends on which one you showed first: at Sundry, presenting the same pairs in both orders changed the winner in 18% of them. Length pushes the same way — the longer reply won 64% of pairs before the anchors were written, and length is exactly what a customer does not want. The control is to score each run independently against anchors rather than comparing pairs, and, where you do compare, to randomize the order and run both directions.

Self-preference comes second and is the one that flatters you in the direction you want to believe. A judge from the same model family as the worker rated its own family's runs close to a full point higher on the rubric's eight-point total than the human graders did — the same effect Chapter 7 found when an agent reviewed its own answer and endorsed 229 of 240 decisions. The control is structural: judge with a different model family from the one doing the work, and if the product later switches worker models, check that the judge is still the outsider.

Drift on upgrade comes third and is the hardest of the three to notice. Sundry's judge was moved to a newer version of the same model with no change to the agent, and the outcome score rose three points overnight. Three points of nothing, in a report that had been comparing weeks. Pin the judge to an explicit version, treat a judge upgrade as a change that must be re-validated against the human labels before any new number is published, and re-run the previous month's cases through both versions so the joint in the series is measured rather than imagined.

Judge Cost and Cadence

Grading is a model call over a transcript, so it costs what a model call over a transcript costs. Sundry's full pass — 120 runs, graded twice because outcome and trajectory have separate rubrics — comes to about $2.60 and roughly three minutes at eight-way concurrency. That is cheap enough to run often and expensive enough that running it on every commit would triple it into an annoyance nobody funds.

So the cadence follows the cost: deterministic checks on every commit, the judge on every merge to main, a human sample of twenty runs once a week. The weekly humans are not there to grade more cases than the judge; they are the reference the judge gets measured against, and their labels are the calibration set the next re-validation uses. Topic 52 turns this into pipeline configuration.

What to Judge

Outcome and trajectory get separate rubrics and separate scores. A wrong answer reached efficiently and a right answer reached through eleven tool calls and two dead ends are different problems with different fixes, and averaging them into one number destroys exactly the information you needed. Topic 51 is about what the second rubric catches.

Give the judge the same evidence a human grader would need and no more: the ticket, the run record, the passages the run retrieved, and the case's expected outcome. Not the previous score, not which branch produced the run, not whether this is the candidate or the baseline — a judge told which side is the new one is being invited to have an opinion about it.

Reporting Honestly

Every published judge score carries its agreement rate, its rubric version and its judge version. "Outcome 86%, judge agreement 89% on the February labels, rubric outcome-v4" is a claim somebody can check. "Resolution: 86%" is a claim about an instrument nobody has described.

And do not call judge scores accuracy. They are a graded estimate produced by a model whose disagreement with human graders is measured and non-zero, which is a perfectly respectable thing to run a business on as long as everybody says so out loud. The team that starts describing them as ground truth stops asking whether the instrument still works, and the answer changes without notice — that is what a model upgrade is.

Common Mistakes
  • Using the same model as both worker and judge — self-preference inflated Sundry's scores by close to a full point on the rubric's eight-point total, in exactly the direction the team wanted to believe.
  • A vague rubric — "rate helpfulness 1-5" agreed with human labels 62% of the time against 89% for anchored criteria, so the judge's own variance was larger than any effect worth measuring.
  • Never re-validating after a judge upgrade — Sundry's score rose three points with no change to the agent, and a historical series with an unmeasured joint in it is worse than no series.
  • Reporting judge scores as accuracy — they are graded estimates with a known agreement rate, and dropping that qualifier is how a team stops noticing the instrument has moved.
Best Practices
  • Write anchored, criterion-level rubrics with a stated meaning for every point on the scale, and version them alongside the prompt they grade.
  • Judge with a different model family from the one doing the work, and pin its version explicitly rather than tracking a floating alias.
  • Re-validate against human labels on a schedule, after every rubric edit, and after every judge change, using cases that span easy and hard.
  • Publish the agreement rate, the rubric version and the judge version next to every score, and require a reason code and an evidence quote on every verdict.
Comparable toolsBraintrust model scorers with versioningLangSmith judge runs attached to tracesRagas reference-based grading metricsDeepEval rubric scorers in a test runnerLabel Studio the human labels to validate against

Knowledge Check

Sundry's judge scored 62% agreement with human labels on one rubric and 89% on another, with the same model and the same runs. What follows?

  • The judge model was too small for the task, and a stronger model would have closed the gap on its own
  • Most of what looks like judge quality is rubric quality, and anchors are where the gain came from
  • The human graders were inconsistent, so the reference labels rather than the judge explain the difference
  • Forty validation cases is too few, and the difference is sampling noise between two small samples

Why must the judge come from a different model family than the agent it grades?

  • A second provider is cheaper to run at eval volumes than adding load to the worker's own provider
  • Same-family judges return verdicts that fail to parse, so the suite silently drops its hardest cases
  • Self-preference inflates the score on its own family's output, in the direction you want to believe
  • Two providers give redundancy, so an outage on one does not block the merge pipeline for the day

The judge model is upgraded to a newer version. The outcome score rises three points and nothing else changed. What is the correct response?

  • Record it as an improvement, since a better judge recognizes correct resolutions the old one missed
  • Re-validate against the human labels and re-score the previous cases on both versions before publishing
  • Pin the judge to the old version permanently, since any upgrade makes the historical series unusable
  • Subtract three points from every score from now on, so the new series lines up with the old one

Sundry runs deterministic checks on every commit but the judge only on merges to main. What decides that split?

  • A full graded pass costs real money and minutes, and per-commit judging becomes a tax people avoid
  • The judge cannot grade a run produced on a feature branch, since its rubric is pinned to main
  • Provider rate limits make more than one graded pass a day impossible at the size of the eval set
  • Judge scores are too unstable to compare between two commits, so only merge-level comparisons are valid

Why does every published judge score carry its agreement rate?

  • It shows which human graders are performing well, so the labelling roster can be adjusted each quarter
  • Provider terms require an agreement rate to be disclosed whenever model output is reported as a result
  • It lets the reader scale the score back to a true value by correcting for the judge's error against humans
  • A score without its validation is a number with no error bar, and the instrument moves without warning

You got correct