Three deterministic verifiers most people never reach for — world-state checks, logs-as-feedback, and golden fixtures — united by one principle: the transcript is the agent's story; the environment is the truth.
Anthropic's evals framing draws a line you should tattoo onto every loop you build: a grader can evaluate either the transcript — "the complete record of a trial, including outputs, tool calls, reasoning" — or the outcome — "the final state in the environment."
The outcome is "whether a flight booking actually appears in the database, not just in the conversation." — Anthropic, Demystifying evals for AI agents
Everything in this lesson is a way of making the agent check the outcome. The unifying move: after acting, interrogate the environment — never the agent's account of the action. The payoff is huge because all three verifiers below are deterministic — top-tier trust on the taxonomy — yet they cover territory unit tests rarely reach.
The action claimed to create, write, send, or flip something. Go look at the something. Database row, file on disk, API resource, queue message — the agent runs the query itself and shows the output.
# in-prompt (Gate 1): the check rides along with the task Implement the booking endpoint, then prove it: POST a test booking with curl, then run sqlite3 app.db "SELECT id, flight, status FROM bookings ORDER BY id DESC LIMIT 1" and show me the row. The task is not done until that row exists.
The trap it kills: a 200 response (or a cheerful "Booked!") with a transaction that rolled back. Return values are claims; rows are outcomes.
Servers, daemons, background jobs — the agent can't see a running process. Ronacher's pattern: have the application always log to a file, so any agent can read runtime truth back at will. (Agentic Coding Recommendations)
# the loop: act → read the world's diary → decide Restart the dev server, wait for it to settle, then: tail -40 logs/dev.log Confirm: a "listening on :3000" line, and ZERO stack traces after it. If either fails, fix and repeat. Paste the relevant log lines as evidence.
This is verifier infrastructure: one line of logging config turns "is it actually up?" from unknowable into a grep. If your app doesn't log to a file, your agent is flying blind — add the file logger as part of loop engineering, not as an afterthought.
Commit a known-good output — a rendered report, a generated config, an API response — and the verifier is one line: "a script that diffs output against a fixture." (best practices) It catches any change, including the ones nobody thought to write an assertion for.
# scripts/golden.sh — drops into Gate 1 or a Stop hook unchanged node generate-report.js > /tmp/report.json diff -u test/golden/report.json /tmp/report.json && echo "GOLDEN: match"
The discipline that makes or breaks it: when output is supposed to change, the golden must be updated — and that update is the verification moment. Reviewing the diff line by line before blessing the new golden is the check. An agent (or human) who regenerates goldens without reading the diff has deleted the verifier while keeping its green light — the same crime as editing tests in Lesson 5.
All three are scripts or one-liners, so they slot anywhere on the gate ladder: ride-along instructions (Gate 1, as shown), a /goal condition ("the golden diff is empty and dev.log shows a clean start"), or a Stop hook for the must-never-slip cases — golden.sh exiting 2 on diff is structurally identical to demo 02's check.sh. Deterministic verifiers are gate-portable; that's much of their value.