An agent that hasn't been evaluated is a demo. An agent that has been evaluated once is a beta. An agent that has an eval loop in place — one that runs on every prompt change, every tool change, every model upgrade — is the thing you can actually ship. This piece is about that third option.

It picks up where Inside the Agent Loop leaves off, and assumes the same vocabulary: the agent loop has six stages, and each stage can be the layer that breaks. The eval workflow here is the answer to "how do you know which layer broke, and how do you keep it from breaking next time."

It also assumes the reader has read the agent loop glossary entry at least once. If the term intake, termination, or persistence is unfamiliar, start there.

The four layers you should test

The mistake most operators make is testing only the model. They write a few canned prompts, run them through the API, check that the answers look plausible, and call it shipped. That misses three of the four layers that can fail.

The four layers, in order from cheapest to most expensive to test:

1. The model alone. Send canned prompts to the model directly, with no agent loop wrapping it. Check that the model produces the expected shape of answer. This isolates prompt and base-model behavior from everything else. 2. The agent loop. Run canned scenarios through the full loop, with all real tools but a controlled environment (a sandbox, a fixture database, a mock external service where one is needed). Check that the loop terminates, takes a sensible path, and produces the expected final state. 3. The tool layer. Send synthetic inputs to each tool the agent uses — edge cases, malformed inputs, rate-limit conditions, auth failures, empty results. Check that each tool returns a sensible result and a sensible error. 4. The system end-to-end. Run canary tasks against the full stack in a production-like environment. These are real tasks, not canned ones; they exercise every layer in combination. Check the canary's outcome against the operator's stated success criteria.

Each layer catches a different class of failure. The model-alone layer catches prompt regressions and base-model drift. The loop layer catches logic regressions (the agent makes a bad decision) and stage failures (the loop doesn't terminate, or terminates too early). The tool layer catches interface regressions (a tool changed its return shape) and contract failures (a tool now requires a parameter the agent doesn't pass). The system layer catches composition failures — the things that look fine in isolation but break when combined.

A useful mental model: if you can name the layer that broke, you're already halfway to fixing it. If you can't, you're going to spend the afternoon reading logs.

A 30-line harness, in prose

Below is a sketch of what a minimum-viable eval harness looks like. Not a real script — the real thing depends on your stack — but the structure is portable.

load_eval_set("path/to/cases.json")           # one file per layer
for each layer:
    for each case in layer.cases:
        run case through layer
        score case against expected outcome
        record {layer, case, score, transcript, latency}
        if score below threshold:
            fail the run
            attach the transcript to the failure
            exit with non-zero
aggregate scores per layer
emit summary + diff against last green run

What this gives you, concretely:

  • A single file per layer that lists the cases. Adding a case is appending a line. Removing a case is deleting a line. Reviewing the eval set is reading a JSON file.
  • A score per case. The score is the smallest thing you can check that tells you whether the case passed. For the model layer, it might be "did the model mention X by name." For the tool layer, "did the tool return a 200." For the loop layer, "did the agent call tool Y exactly twice." For the canary layer, "did the canary end in the expected final state."
  • A transcript per case. When something fails, the transcript is the first thing you read. Without it, you're guessing.
  • A diff against the last green run. Most regressions are visible as "case 17 used to pass, now it doesn't." The diff is what tells you whether to roll back or fix forward.

What this harness deliberately doesn't do:

  • It doesn't try to be a general agent benchmark. It tests your system, on your tasks, against your criteria. External benchmarks are useful for catching model regressions; they are useless for catching your regressions.
  • It doesn't try to be clever about scoring. A yes/no score per case is fine. "How close" scoring is a research project, not an eval workflow.
  • It doesn't try to run in CI on every commit unless the eval set is small. For larger sets, run it on every prompt change, every tool change, and every model upgrade — that's the cadence described later in this piece.

The full harness, with file IO and error handling, is on the order of 30 lines of Python or 50 lines of shell. If your harness is longer than that, you are probably trying to do too much.

What to do when an eval fails

The temptation, when an eval fails, is to read the failing transcript, guess at the cause, and patch the prompt. This is how you ship three regressions for every one you fix.

The right sequence is the same one an SRE uses on a failing deploy: replay, identify, fix, re-run.

Replay. Run the failing case again, on purpose, in isolation. If it fails the same way, the failure is deterministic and you can debug it. If it passes, the failure was flaky and you need a bigger sample before drawing conclusions. Flakiness is a real signal — it usually means the eval case is underspecified, not that the system is unreliable.

Identify. Read the transcript. Decide which layer broke. The four-layer model gives you the choice set: was this a model failure (wrong shape of answer), a loop failure (bad decision or non-termination), a tool failure (wrong return or contract mismatch), or a system failure (everything looks right but the combination is wrong)?

Most failures land in one of two places. The first is the loop layer: the agent made a decision that didn't match the canary's expected path. Read the transcript and ask which stage of the agent loop the bad decision happened at. The fix is usually in the prompt at that stage, not in the system prompt as a whole. The second is the tool layer: a tool now returns a different shape, or fails on inputs that used to work. The fix is in the agent's tool description, not in the agent's reasoning.

The third place — less common, harder to debug — is composition. Each layer is fine in isolation, but the combination produces a different result. The fix here is almost always to break the composition into smaller pieces and eval each one.

Fix. Make the smallest change that addresses the identified layer. Resist the urge to fix two things at once. If the fix is a prompt change, write the new prompt, document the diff, and explain why this prompt is correct.

Re-run. Run the full eval set, not just the failing case. A fix that makes one case pass while breaking two others is a regression, not a fix. The whole point of having a set is to catch this.

When the eval is green again, commit the change with the transcript and the diagnosis attached. The eval history is the documentation that explains why the system behaves the way it does.

Eval cadence

Eval is not a one-time event. The system changes; the model changes; the tools change. The eval has to change with them, or it goes stale and stops catching the regressions it was built to catch.

The minimum cadence that actually catches things:

  • Every prompt change. Before merging any prompt change, run the eval set. If the set goes red, do not merge the change.
  • Every tool change. Before merging any change to a tool the agent uses — schema, return shape, error behavior, rate limits — run the eval set. The model and the loop didn't change; the surface they call into did.
  • Every model upgrade. When the underlying model is swapped — for a newer checkpoint, a different provider, a quantization — run the eval set. Even a small model change can produce a large behavior change. The eval is the only way to know whether the change is safe.
  • Every state-graph change. When the workflow moves from a loop to a state graph, or the graph itself is edited, run the eval set with extra weight on the cases that exercise the changed transitions. State-graph bugs are usually silent until they aren't.

What this cadence deliberately doesn't include: running the eval set on a timer, in the background, with no human watching. Eval results that arrive without a human are eval results that get ignored. Run them when a human is going to look at them.

The minimum viable eval

If the previous sections felt like too much, this one is for you. A minimum viable eval, for an agent system that does roughly one thing, fits on the back of a napkin:

  • Three canned prompts for the model layer. Pick the three things the agent most often has to do well. Write a prompt for each. Score each on whether the model produced the expected shape of answer.
  • One canned scenario for the loop layer. Pick the most common real task the agent runs. Run it through the full loop in a sandbox. Score it on whether the loop terminated in the expected final state.
  • One canary for the system layer. Pick one task that, if it broke, would tell you within an hour. Run it on every prompt change and every tool change.

Three prompts, one scenario, one canary. Total: five cases. You can write this set in an afternoon. You can run it in under a minute on most stacks. And you will catch the majority of the regressions you would otherwise ship.

The trap with the minimum viable eval is leaving it at minimum forever. Once the system has been running for a month, the failures you've already debugged are the natural candidates for new cases. Add them. The eval set should grow with the system.

What this workflow doesn't do

It doesn't grade subjective quality. "Did the agent sound helpful" is not a yes/no question, and trying to score it as one produces scores that don't mean anything. Eval catches regressions; it does not catch mediocrity. That is a different problem.

It doesn't replace judgment. The operator still has to look at the eval results, read the transcripts, and decide whether the fix is correct. The harness is a tool, not a verdict.

It doesn't generalize across stacks. Every stack has its own shape of tool, its own shape of loop, its own shape of failure. The four-layer model is portable; the specific cases are not. Write your own.

That's the workflow. Five cases is the floor. Run them on every change. Read the transcripts. Most of the time, you don't need more than that.

Triadive Editorial