Module 6 — Self-critique and result verification
An agent that never questions its own output produces plausible-looking wrong answers with high confidence. Adding a critique step — before the loop returns — catches a large fraction of these. This module explains three verification patterns, in order of increasing cost and increasing effectiveness, and it is honest about what none of them can catch.
Reflection: the cheapest first pass
The pattern is one extra call at the end of the loop, driven by a strict prompt.
REFLECT = """You just produced this draft answer to a research question.
Question: {question}
Draft: {draft}
Sources cited: {sources}
Check three things and answer JSON only:
1. Does every factual claim have a source in the transcript?
2. Are the sources actually about the question?
3. Is there a contradiction between two sources that the draft ignores?
Return: {{"issues": ["...", "..."], "verdict": "keep" | "revise"}}"""
If the verdict is revise, the loop reopens with the issues injected as a new user turn: "Address these problems: …". Two more iterations, capped, and the loop finishes. This adds one call in the good case and three in the bad case, for a measured 13% overhead on the running example.
Effectiveness on the same agent, measured against a 30-question evaluation set: bad citations drop from 18% to 8% of runs. That is a meaningful improvement, but the remaining 8% is telling — the very failure modes the model missed while writing the draft are the ones it also misses while reviewing it. Reflection catches shallow errors, not deep ones.
A separate model as verifier — LLM-as-a-judge
The reason reflection misses its own mistakes is the reason peer review exists: the same brain that produced the reasoning is the wrong brain to evaluate it. Using a different model — a different provider, or the same provider at a different size — for the verification call breaks that correlation.
def verify(question, draft, transcript, model="anthropic/claude-3-5-sonnet"):
reply = call_model([
{"role": "system", "content": VERIFY_PROMPT},
{"role": "user", "content": json.dumps({
"question": question,
"draft": draft,
"transcript": summarise(transcript),
})},
], model=model)
return json.loads(reply.text)
Two things matter for this to help. The verifier must not see the drafter's reasoning verbatim — feed it a summarised transcript, not the raw chain of thoughts. Otherwise, the verifier "agrees" because it re-derives the same reasoning. And the verifier must have a checklist, not an open-ended "is this correct?" — open-ended reviews rubber-stamp everything above a threshold of fluency.
Measured on the watch agent, using a different-provider verifier on top of the same-model reflection drops bad citations from 8% to 3.5%. That is another meaningful step, and the cost is one extra call to a different provider per run.
Tool-based verification: check by recomputation
The most reliable verifications are the ones that do not use the model. Three techniques recur.
Recalculate. Any numeric claim in the answer — "the release notes list 42 changes", "the page mentions 'CDC' three times" — is re-derived by a small Python function reading the fetched pages. If the recount disagrees with the answer, the answer is wrong. This eliminates the hallucination category the model cannot detect in itself.
Re-fetch a source. Every URL cited in the answer is fetched a second time, and its content is required to contain the quoted claim as a substring or as a fuzzy match. Cited but unquoted pages, cited pages that 404, and pages whose content contradicts the citation all fail this check.
Structural validation. The answer must be JSON with fields answer, sources and confidence; each source must have a URL and a quote. Rejecting a malformed answer is trivial and cheap, and it eliminates the "the model forgot to cite" class of failure.
None of these verifications ask the model whether it thinks itself right. They ask the world.
The honest limits of self-correction
Verification is not a silver bullet, and the literature is now clear on where it fails. Three limits belong in every design.
A model cannot detect what it does not know. If the training data contained a widely-held misconception, both the drafter and the verifier will believe it, no matter how many rounds of reflection you add. This is why the tool-based checks above are the only ones that improve over the model's own knowledge — they consult external evidence.
Confidence is uncalibrated. Asking the model "how sure are you?" produces a number that correlates weakly with correctness. Ranking answers by self-reported confidence and returning the top one improves quality only marginally, and can be worse than picking randomly on adversarial questions. Trust evidence, not confidence.
Reflection can decrease quality. On tasks the model handled correctly, a reflection prompt can talk it out of the right answer by looking for issues that are not there. Cap reflection iterations at one, and only trigger reflection when at least one issue exists in a first cheap check.
Where the running example uses each
The watch agent uses all three, staggered by cost.
- Structural validation on every answer: cheap, catches malformed JSON and missing citations.
- Tool-based re-fetch on every citation: moderate, catches broken and misquoted URLs.
- LLM-as-a-judge on the final draft: expensive, gated by a
--verifyflag when the question deserves it (medical, legal, financial contexts).
Turning on all three raises average latency from 14 seconds to 22 seconds, and average cost by 34%. On our evaluation set, bad-answer rate drops from 18% to 2.5%. Whether that trade is worth it depends on the cost of a bad answer, not on the cost of the extra calls.
A verified answer is still an answer produced by a language model. For anything with a legal, medical or financial consequence, verification is a filter, not a stamp of approval. The final gate must be a human — module 7 formalises this.
Summary
- Reflection is one extra call from the same model; it catches shallow errors and misses the ones baked into the reasoning.
- A different model as verifier breaks the correlation with the drafter and improves further; feed it a summary, not the raw chain of thought.
- Tool-based verification — recalculation, re-fetch, structural validation — consults the world and is the only kind that improves over the model's own knowledge.
- Self-correction has real limits: shared misconceptions, uncalibrated confidence, and the risk of talking a correct answer out of the model.
Next module: guardrails — the budgets, permissions and checkpoints that prevent an agent from harming itself, the user, or the system.