Agent demos showed motion before they showed progress.
A system could open the right file and edit the wrong section, call an API with a stale ID, run a test while ignoring its warning, or browse several pages and cite the least relevant one. A final paragraph that sounds confident does not prove the run was correct.
The eval needs to inspect the path and the end state. For code, that may mean a passing test, a narrow diff, no unrelated edits, and no generated debris. For browser work, it may mean the right form fields were submitted without visiting a disallowed origin. For research, it may mean primary sources and no unsupported claims.
Start with a readable event log:
type AgentRunEvent =
| { type: "observe"; at: string; source: string; summary: string }
| { type: "plan"; at: string; steps: string[] }
| { type: "tool_call"; at: string; tool: string; inputHash: string }
| { type: "tool_result"; at: string; tool: string; ok: boolean; outputHash: string }
| { type: "approval"; at: string; scope: string; decision: "approved" | "denied" }
| { type: "final"; at: string; answer: string }
Hashes help avoid storing secrets or whole file contents. The record should still show what the agent observed, chose, changed, and did after failure.
Early cases should be small and awkward:
- the obvious filename is wrong
- the first result is stale
- a command succeeds with a meaningful warning
- one valid tool violates scope
- a browser page loads slowly
- a test passes because the changed path is uncovered
Keep the reason the case exists:
{
"id": "repo-edit-stale-test-output",
"task": "Fix the failing parser test",
"trap": "The first test command prints cached output.",
"expected": "Rerun with cache disabled before claiming success."
}
Autonomy needs more than completion rate. Track unsafe action attempts, unnecessary approvals, missed approvals, tool errors, recovery, unrelated changes, time, and cost. An agent that completes more tasks by widening scope is not better. An agent that asks for approval on every step is not useful.
Approval belongs in the eval too. Inspect whether the request described the effect, used a narrow scope, continued correctly after approval, and stopped after denial.
The harness should start while the agent is still simple. Five tasks, a run record, an end-state grader, and the first ugly failure are enough. Waiting until the system has memory, browser state, retries, and ten tools makes every evaluation choice harder.
The question after a demo should be simple: did it get better, or did it only move more?
Related posts

About Jeremy London
Engineering leader and builder in Denver. I write about AI platforms, agents, security, reliability, homelab infrastructure, and the parts of engineering work that have to survive production.