Building an Eval Harness

Metrics and judges are ingredients; a harness is the kitchen. An evaluation harness is the system that takes a dataset of test cases, runs your LLM system over them, scores the outputs, and reports the results — reproducibly, every time. Building one well is what turns evaluation from a one-off spreadsheet into an engineering asset you run on every change, like a test suite.

We have metrics (post 2) and LLM judges (post 3). Now we assemble them into something you can actually run repeatedly. A harness is the difference between “I evaluated it once, by hand” and “evaluation runs automatically on every change and blocks regressions.” This post is about its anatomy: the dataset, the runner, the scorers, and the report.

The four parts of a harness

Strip away the tooling and every eval harness has the same shape:

  1. A dataset — a collection of test cases, each an input (and often an expected output or grading rubric).
  2. A runner — code that feeds each input to the system under test and collects the output, handling the messy realities of API calls.
  3. Scorers — the metrics and/or judges from the previous posts, applied to each output to produce per-case scores.
  4. A report — aggregation and presentation: overall scores, breakdowns by category, and per-case detail for debugging.

Existing frameworks (EleutherAI’s lm-evaluation-harness, OpenAI’s evals, and others) implement exactly this shape; understanding the parts lets you use them well or build a lean one yourself. The value is in the parts working together reproducibly, not in any particular tool.

The dataset is the hard part

Everything downstream is only as good as the test cases. A weak dataset produces confident, meaningless numbers. Good eval datasets share a few properties:

A recurring question is where the cases come from: hand-written by domain experts (highest quality, slowest), sampled and labeled from real production logs (most representative), or synthetically generated by a model (fast, scalable, but risks baking in a model’s blind spots). A blend is typical — seed with expert cases, expand with labeled production traffic, augment with synthetic edge cases you then review.

The golden set

A special, high-value artifact is the golden set: a curated, stable collection of cases with carefully verified correct answers, treated as the authoritative benchmark for your system. It changes rarely and deliberately. Its stability is the point — because it doesn’t move, scores across it are comparable over months, so you can say “we went from 82% to 89% on the golden set since the spring” and mean it. Keep it version-controlled, review changes to it like code, and never edit it casually to make a number look better (that’s tampering with your own scale).

The runner: handling reality

The runner looks trivial — loop over cases, call the model — but production LLM APIs are hostile to naive loops:

The report: aggregate and drill down

Finally, turn per-case scores into decisions. A good report does two things at once:

The most useful report of all is a comparison: candidate vs. baseline, showing not just the score delta but which specific cases flipped from pass to fail and back. This directly answers the question that drives every change — “did this help, and what did it cost me?” — and surfaces the silent regressions that averages hide.

Wire it into CI

The final move that makes a harness pay off: run it automatically. Just as unit tests run on every commit, your eval suite should run on every meaningful change to prompts, models, or system code — ideally in CI, gating deploys on a minimum score and flagging regressions before they merge. (We’ll return to CI gating in the production post.) A harness you run by hand once a month is a nice report; a harness wired into CI is a safety net that makes fearless iteration possible.

Key takeaways

Further reading

Sources & References

An open eval framework implementing the harness shape