Your Verifier Agent Just Said 'PASS' — Here's Why That Single Word Should Scare You
Why this matters
Here's what nobody tells you when you bolt a verifier agent onto your pipeline: the day it starts printing a verdict is the day your engineers stop reading the diff. That's not a side effect — that's the job you hired it for. But if the only thing it ever says is one word, you haven't built review. You've built a rubber stamp that launders unreviewed code into production, one merged PR at a time, and nobody notices until something breaks.
The PASS a human caught in ten seconds
Picture the setup: builder agent writes a diff, verifier agent reviews it, prints PASS, PR merges. Weeks later a human is skimming that same file for an unrelated reason and spots it immediately — a null check missing on a field that's optional in production payloads. A crash waiting for the right input. The verifier had the exact same diff. Same context. Arguably more patience than the human scrolling past it on a Friday afternoon. It still said PASS. Don't reach for 'we need a smarter model' here — that's not the failure. The failure is the output format. A verdict can't be checked, so nobody checks it. Not your engineers, not you, not eventually anyone.
Name the mechanism: pass/fail is a trust exploit
Think about how you actually treat a teammate who says 'looks good' — you still ask what they looked at, what they skipped. That instinct disappears completely when an agent prints PASS, because it doesn't read like an opinion, it reads like a system output. That gap is the exploit: we trust confident, structured-looking text more than we trust an equally confident person. The format trains your team to stop reading diffs — which, sure, was the goal — but it does that without giving you the one thing that would make it safe: something you could glance at for five seconds and prove wrong. A verdict gives you permission to stop looking. It never earns that permission.
Where this sits in the pipeline you've already built
Days 1 through 5 got you a builder agent (maybe several) that produces diffs, plus enough orchestration to route work between them. The verifier is different in kind, not degree — it's the first agent in your pipeline whose entire job is judgment, not production. And judgment agents fail in a way builders don't. A wrong builder still hands you readable, catchable bad code. A wrong verifier hands you false confidence — which is worse than skipping review entirely, because it actively talks the human out of looking. That's why I care more about the verifier's interface than its raw accuracy. An 85%-accurate verifier that's forced to show its work is safer in production than a 95%-accurate one that only says PASS — because the first one's mistakes are visible, and the second one's aren't.
What we run at PhoenixDX: force a schema, not a verdict
We don't let our verifier say pass or fail. Full stop — that token doesn't exist in its output space. All it's allowed to produce is a list of findings, and every finding has to fit a fixed shape: file and line, plus a concrete failure scenario — a specific input, and specifically what breaks. Skip a field and the finding gets bounced; the agent retries or drops the claim. And zero findings is a legitimate outcome — that's what 'this diff is fine' looks like here. There's no separate PASS token hiding behind it, because there's nowhere for one to hide.
{
"finding": {
"file": "services/payments/charge.py",
"line": 142,
"claim": "refund_amount is not validated against original charge amount",
"failure_scenario": {
"input": "POST /refund with refund_amount=99999.99 on a $10 charge",
"observed_break": "process_refund() sends the raw amount to the payment\nprovider with no bound check against charge.amount, issuing a\nrefund larger than the original charge"
}
}
}
// Enforcement rule: a finding missing file, line, input, or
// observed_break is rejected before it reaches the human —
// the agent must retry or drop the claim, never soften it into prose.Strip away the framing and this is just structured-output validation with retry — the same pattern you already use for tool calls. We're not inventing a new mechanism, just pointing an old one at a place teams still default to accepting free text: the review step itself.
Why this exact schema: falsifiable beats thorough
File:line plus a concrete failure scenario isn't a rubric I picked because it sounded rigorous — it's the smallest claim a human can check without redoing the whole analysis themselves. 'This could be a bug' forces the reader to rebuild the reasoning from zero, which is precisely the work the verifier existed to save them. In practice, that means it never gets checked — it gets rubber-stamped or waved through. Compare that to: 'at line 142, refund_amount=99999.99 causes an over-refund.' Ten seconds. Open the file, find the line, picture the input, see if it holds. That ten-second check is the entire point of the schema. If a claim can't survive it, it's not a review artifact — it's decoration with extra steps.
The tradeoff: slower, pickier, quieter
- ▹It's slower — reasoning to a specific input and a specific broken line burns more inference than emitting a verdict, and rejected findings mean extra retry rounds.
- ▹It's pickier — an agent that can't hide behind 'looks risky' has to either produce something real and specific, or produce nothing. Vague-but-plausible concerns get filtered out by design.
- ▹It will report zero findings on plenty of diffs, and that's not the agent phoning it in. A clean bill with no evidence would be the dangerous outcome; zero findings that survived an enforced schema is the trustworthy one.
- ▹Resist the urge to 'fix' those quiet runs by loosening what counts as a finding — that's the exact path back to pass/fail with extra ceremony bolted on.
Checklist: audit your verifier's output contract
- ▹Can a finding exist in your schema without a file and line number? If yes, there's a loophole straight back to vague prose.
- ▹Does 'no findings' look identical to 'verifier didn't run' or 'verifier errored'? If you can't tell those apart, silence tells you nothing.
- ▹Is there any path where a malformed finding still reaches a human? If enforcement is advisory rather than hard, agents drift back to summaries the moment anything's under pressure — speed, cost, an ambiguous diff.
- ▹Grab five recent findings at random. Can you falsify each one in under 30 seconds using only the file:line and scenario given — no extra digging? If not, the schema's too loose.
- ▹Are your engineers still opening the diffs the verifier passed, or have they quietly started trusting the report instead? That behavior shift is the real tell on whether the format is working.
Day 7 picks up exactly here: what you actually do with a stack of schema-compliant findings — how to route them back into the generator loop instead of just dumping them on a human, and where a human still has to stand in that loop regardless.
Extend your knowledge
- ▹Pull your last 20 verifier-agent reports (if you're already running one) and run each finding through the ten-second falsifiability test above — count how many actually survive.
- ▹Look at how structured-output/JSON-schema validation with retry is implemented for tool calls in the Anthropic API docs, then apply that same enforce-and-reject pattern to your review-step prompts instead of function calls.
- ▹Read up on 'LLM-as-judge' evaluation design — it's a well-trodden pattern in eval literature, the same unfalsifiable-verdict failure mode shows up there, and the fixes overlap heavily with what's covered here.
- ▹Draft the finding schema for your own pipeline now, before Day 7 — you want it ready to wire into a feedback loop, not retrofitted after the fact.
Discussion
Chat with Chi Cong (AI) about this article. Your conversation is private to you — you can publish a summary for others when you're done.