AI Engineer Dojo Contents
Chapter 11

Eval-Driven Development: The Workflow

Everything so far is technique. This is the practice — how an eval engineer actually works, and the philosophy that ties the tools together.

Eval-driven development

By analogy to test-driven development: before you optimize a prompt or swap a model, you build the eval that defines "better." Then every change is a measured experiment — run the eval, compare to baseline, keep what moves the metric, discard what doesn't. Without this, prompt engineering is superstition: you tweak, it "seems better," and you've actually regressed three cases you didn't look at. The eval converts vibes into evidence.

The daily loop, and the traps

Define the metric → build/curate the dataset → establish a baseline → iterate one change at a time, watching slices → wire it into CI as a regression guard → close the loop with production. The hard-won lessons: look at your data (reading real outputs surfaces failure modes no metric named); beware Goodhart's law (once a metric is the target, it gets gamed — keep a held-out set); start simple (twenty hand-checked examples beat an elaborate auto-eval you don't trust); and track a balanced set (quality, safety, cost, latency) so you don't win one by losing another.

What the role is

Part data scientist (statistics, datasets, error analysis), part software engineer (harnesses, pipelines, CI), part product thinker (turning "good" into measurable criteria), part scientist (hypotheses, controls, evidence). You're the person who can answer, with data, the question every AI team is desperate to answer: "is this actually working, and did our change help?"

Try it · ~15 minFree · no API key

Gate a release in CI — and catch a slice regression

You'll write the regression check that runs on every change: overall must not drop below baseline, and no key slice may fall through its floor (mock eval, free). The trap: the new version raises the average — and should still fail. Find out why.

Lab code — runs free

BASELINE = 0.80                        # current production quality (in the repo)
SLICE_FLOOR = {"enterprise": 0.75}     # segments that must not regress

def mock_eval(version):
    # pretend we ran the full eval; v2 lifts the average but hurts enterprise
    return {
        "v1": {"overall": 0.80, "by_slice": {"enterprise": 0.78, "smb": 0.81}},
        "v2": {"overall": 0.83, "by_slice": {"enterprise": 0.71, "smb": 0.88}},
    }[version]

def check(version):
    r = mock_eval(version)
    assert r["overall"] >= BASELINE - 0.02, f"overall regressed: {r['overall']}"
    for s, floor in SLICE_FLOOR.items():
        assert r["by_slice"][s] >= floor, f"{s} regressed: {r['by_slice'][s]}"
    print(f"{version}: PASS")

for v in ("v1", "v2"):
    try:
        check(v)
    except AssertionError as e:
        print(f"{v}: FAIL -> {e}")
Worked solution
v1: PASS
v2: FAIL -> enterprise regressed: 0.71

v2's overall (0.83) beats v1's (0.80), so an average-only gate would have shipped it. But it cratered the enterprise slice from 0.78 to 0.71 — below the 0.75 floor — while padding the average with easy SMB gains. The slice floor catches the trade you didn't intend. This little function is eval-driven development in production: baselines and slice floors checked into the repo, enforced on every change, so quality can't silently slide.

Case study

Iterate: the gate that caught the regression

Iterate kept shipping "improvements" that fixed one thing and quietly broke another, because changes went out on the author's confidence. They adopted eval-driven development: every change to the AI system had to pass an offline eval in CI — quality couldn't drop below the baseline, or the release was blocked, exactly like a failing unit test. The first month, the gate blocked a prompt "improvement" that looked better on the three examples the author tried but regressed a key slice by nine points on the full eval set.

That one catch paid for the whole system: a regression that would have shipped and generated complaints was stopped before merge. Velocity actually rose, because engineers could change things boldly knowing the gate would catch a quality drop. The lesson: treating evals like tests — a required, automated gate on every change — is what converts risky, vibe-based iteration into fast, safe iteration.

Running case · Meridian × Remi

This chapter: Meridian wires Remi's eval into CI. Every prompt tweak, model swap, or tool change must clear the sliced eval — including the over-sampled refund slice and the red-team suite — or it can't merge. A well-meaning change that would have made Remi chattier but worse on refund accuracy is blocked automatically, before it ever reaches a customer. Remi now improves without regressing. (Ch 12: the whole stack, and how to talk about it.)

Quiz · Chapter 11

  1. Eval-driven development means:
  2. The single highest-leverage activity in eval work is:
  3. Goodhart's law warns that:
  4. Why track a balanced set of metrics rather than one?
  5. Wiring evals into CI primarily prevents:
← Back Continue →

The AI Evaluation Engineer · AI Engineer Dojo · aiengineerdojo.com