Self-review versus an independent reviewer
Same session reviews itself
- Carries the reasoning that produced the answer
- Tends to confirm its own earlier decisions
- Shares any misreading of the input
- One context, filled with the whole task
Separate reviewer instance
- Fresh context: output + criteria only
- No stake in the original choices
- Can be prompted to try to refute
- Can use a different model or prompt
Why a separate instance
A model reviewing its own output in the same conversation is not really a second opinion. Its context contains the reasoning, assumptions and interpretations that produced the answer, so it tends to reread the answer through them. Claude Code’s best-practices guide makes the point directly: a fresh context improves code review because Claude will not be biased toward code it just wrote. Its recommended writer/reviewer pattern uses two sessions — one implements, the other reviews — and its adversarial review step runs the reviewer as a subagent that sees only the diff and the criteria you give it.
That does not make self-checking useless. Asking a model to verify its answer against explicit criteria before finishing still catches slips, and the best newer models do much of this on their own. But self-checks share the generator’s blind spots. When the cost of a missed error is high, add an independent instance. Anthropic’s evaluation guide applies the same logic to grading: it is generally best practice to use a different model to evaluate than the one that generated the output.
| Technique | What it catches | What it misses |
|---|---|---|
| Self-check in the same turn | Slips against stated criteria | Errors that come from the model’s own misreading |
| Separate reviewer instance | Gaps the author rationalised away | Problems outside the criteria it was given |
| Multiple independent runs, compared | Inconsistent or unstable answers | Errors every run makes the same way |
| Per-item passes + integration pass | Local detail and cross-item interactions | Issues outside each pass’s criteria; costs more calls |
Splitting the work: multi-pass review
The second problem is attention. Put thirty changed files into one prompt and ask for a review, and the model spreads its attention thin — the guide calls this attention dilution (see 1.6). A multi-pass design gives each pass one job. Local passes look at one unit at a time — a file, a contract section, a patient record — with full attention. An integration pass then looks across units for problems no single unit shows: a changed function signature that a caller was not updated for, a clause that contradicts a definition elsewhere. A verification pass checks each candidate finding before anyone sees it.
A multi-pass review of a large pull request
This is essentially how Claude Code’s managed Code Review describes itself. Multiple agents analyse the diff and surrounding code in parallel, each looking for a different class of issue; a verification step then checks candidates against actual code behaviour to filter out false positives; results are deduplicated, ranked by severity and posted. The design trades time and money for precision — the docs say reviews complete in about 20 minutes on average and cost roughly $15–25 each, scaling with the size of the change.
Finding and filtering as separate stages
- Specialised finderslogic, security, regressions — in parallel
- Verify candidatesfresh instance tries to refute each one
- Dedupe and rankmerge overlaps; order by severity
- Reportonly verified findings, with evidence
Separating the stages is also what Anthropic’s Opus 5 prompting guidance recommends from the other direction: a review prompt that says “only report high-severity issues” or “be conservative” may be followed literally and report less, so ask the finder to report everything and filter in a separate pass. The finder’s job is recall; the verifier’s job is precision (4.1 covers writing the criteria each one applies).
import asyncio
from anthropic import AsyncAnthropic
client = AsyncAnthropic()
async def ask(system: str, content: str) -> str:
r = await client.messages.create(model=MODEL, max_tokens=4096,
system=system, messages=[{"role": "user", "content": content}])
return r.content[0].text
async def review(files: dict[str, str], interfaces: str) -> list[str]:
# 1. Local passes: one fresh instance per file, run in parallel
local = await asyncio.gather(*[
ask(FILE_REVIEW_PROMPT, f"<file path='{p}'>{src}</file>")
for p, src in files.items()])
# 2. Integration pass: sees findings and interfaces, not every line
cross = await ask(INTEGRATION_PROMPT,
f"<interfaces>{interfaces}</interfaces><findings>{local}</findings>")
# 3. Verification: a separate instance tries to refute each candidate
candidates = parse_findings(local, cross)
verdicts = await asyncio.gather(*[
ask(VERIFY_PROMPT, f"<finding>{c.text}</finding><code>{c.snippet}</code>")
for c in candidates])
return [c.text for c, v in zip(candidates, verdicts) if v.startswith("CONFIRMED")]Multi-instance agreement
Another multi-instance pattern runs the same task several times independently and compares the results. Anthropic’s hallucination guidance calls this best-of-N verification: run the same prompt more than once and look for inconsistencies. Where independent runs agree, confidence is higher; where they disagree, you have found exactly the cases a human should see. It is a good fit for classification and extraction on high-stakes fields, and a poor fit for long creative outputs, where runs differ legitimately.
Which review architecture fits?
- Author blind to its own errorsIndependent reviewerfresh instance, criteria only
- Too much input for one passPer-item + integrationlocal passes, then cross-cutting
- Too many false positivesVerification passtry to refute each finding
- Unstable judgementsN runs, comparedisagreement goes to a human
Traps the wrong answers are built from
| Tempting but wrong | Do this instead |
|---|---|
| Asking the generating session to review its own output as the only check | Use a separate instance that sees the output and criteria, not the reasoning. |
| Reviewing a large change set in one pass | Run per-file local passes, then a cross-file integration pass. |
| Combining “find everything” and “only report what matters” in one prompt | Let finders maximise recall; filter in a separate verification pass. |
| Giving the reviewer no criteria | State what counts as a gap and require evidence, or it will find something anyway. |
| Treating agreement between runs as proof | Use agreement to prioritise; route disagreements to people. |
You should now be able to
- Explain why a fresh-context reviewer catches errors that same-session self-review misses.
- Design a multi-pass review with local passes, an integration pass and a verification pass.
- Separate recall-oriented finding from precision-oriented verification.
- Use independent multi-instance runs to surface unstable judgements for human review.
- Weigh the latency and cost of each additional pass against the risk it addresses.