Reflection Loops Are Not Free: When Self-Critique Makes the Output Worse
A critique step can only catch what was already derivable from the context — and asked to find problems, a model will find them in passages that were fine. Here's when the pattern earns its doubled token bill.
Adding a critique step to a drafting agent made its output measurably worse: longer, more hedged, and wrong in places the first draft had right. The critique step was well written. The problem was structural.
Reflection — have the model review its own output and revise — is one of the first patterns people reach for, and one of the easiest to apply where it cannot possibly help.
What reflection does mechanically
A reflection pass appends the model's own output to the context and asks for an assessment. No new information enters the system. The reviewing model has exactly what the drafting model had, plus the draft.
That framing makes the boundary obvious: reflection can only surface errors that were derivable from information already present. Internal contradictions, requirements in the prompt that the draft ignored, arithmetic that doesn't check out, a format that doesn't match the spec — all fair game. Facts the model never knew, a tool result it misread, a constraint that lives in someone's head — reflection cannot reach any of them, and asking it to will generate a confident critique anyway.
Why the second draft gets worse
Ask for a critique and you will get one. The model is being asked to find problems, so it finds problems, including in passages that were fine.
The revision then dutifully addresses them, and the characteristic damage follows: a specific claim becomes a hedged one, a clean sentence acquires a qualifier, a decisive recommendation grows an "it depends" section. Each individual change looks defensible. In aggregate the draft regresses toward mush.
The second failure mode is quieter. A correct detail gets "fixed" into an incorrect one because the critique pass asserted something plausible about it, and nothing in the loop can adjudicate between the draft and the critique. Without an external referee, the more recent statement usually wins.
✅ Where reflection genuinely pays
The pattern works when the critique has something to check against that isn't the model's own judgment:
- A verifiable oracle exists. Code that must compile, JSON that must validate against a schema, a query that must run. Reflection with a test result in the loop is not really reflection — it is iteration against ground truth, and it's one of the most reliable patterns there is.
- The criteria are explicit and checkable. "Every claim must cite one of the retrieved documents" gives the critique pass a mechanical job. "Make it better" does not.
- Retrieval happens between passes. Draft, fetch relevant material, revise with the material in context. New information enters, so the second pass can genuinely know more.
- The failure mode is omission. Checking a draft against an explicit requirements checklist catches skipped requirements well, because that comparison is mechanical.
❌ Where it usually hurts
- Open-ended prose quality with no rubric.
- Factual accuracy on anything not in context.
- Anything already correct — the pass has no way to conclude "leave it alone" unless you tell it that's an acceptable verdict.
- Cost-sensitive paths: reflection at minimum doubles the token spend for a run, and the revision re-sends the whole draft.
Two changes that fix most reflection loops
Make "no changes needed" a first-class outcome. Have the critique return a structured verdict, not prose:
{ verdict: "pass" | "revise",
violations: [{ requirement: string, location: string }] }
With violations: [] the loop skips revision entirely. This one change eliminates most gratuitous rewriting, because the model must now name a specific violated requirement instead of gesturing at improvement.
Give it a rubric drawn from the request, not from taste. Before drafting, extract the explicit requirements into a list the loop holds. The critique pass checks the draft against that list and nothing else. Anything the requester didn't ask for is out of scope — which is exactly the discipline a human editor applies and a model, left unconstrained, does not.
A quick way to test whether yours is helping
Run your eval set twice, once with reflection and once without, and compare per-item rather than in aggregate. The revealing number isn't the average — it's how many items got worse. A reflection loop that improves six items and degrades four is usually a net loss once you count the doubled cost, and the aggregate score will hide that entirely.
The takeaway
Reflection is not a general-purpose quality upgrade. It's a mechanism for checking output against something, and it is only as good as the something. Point it at a compiler, a schema, a retrieved document, or an explicit requirements list and it earns its cost. Point it at the model's own aesthetic sense and you have paid double for a hedgier draft.