Skip to content

Self-Verification: What Asking a Model to Check Its Work Catches

5 min read · updated August 3, 2026

“Now check your answer” is the cheapest-looking quality improvement available, and the published evidence on it is much more negative than its popularity suggests. The reason is a single information-theoretic point that also tells you exactly when it does work.

The rule that predicts the results

A verification step can only catch an error if the check has information the generation did not use. That is the whole rule, and almost every result in this area falls out of it.

If the model produced a wrong answer because it lacked a fact, asking the same model to review the answer changes nothing — the fact is still missing, and now you have paid twice. If it produced a wrong answer because it violated a constraint that is checkable against the output text, the reviewing pass genuinely does have something the generating pass did not: it can read the finished output all at once, rather than committing to each token without seeing what comes after.

So the design question is never “should I add a verification step”. It is “what does the verifier know that the generator did not”. If the answer is nothing, do not build it.

What the studies found

Huang and colleagues at Google published Large Language Models Cannot Self-Correct Reasoning Yet (2023), which examined intrinsic self-correction — the model revising its own answer with no external feedback and no oracle telling it whether it was wrong. Their central finding was that performance on reasoning benchmarks degraded rather than improved under this setup, and that several earlier positive results had leaked information by using ground-truth labels to decide when to stop revising. When the model has to decide for itself whether to revise, it revises correct answers into incorrect ones often enough to wipe out the gains.

Stechly, Marquez and Kambhampati reported a similar picture in a 2023 study of self-critique on graph colouring: the model’s own verification of its solutions was unreliable enough that the iterative loop did not improve results, while replacing the critic with a sound external verifier did. Related work from the same group on planning benchmarks found the same shape.

These results are consistent, and they are consistent with the rule. Intrinsic self-correction adds a pass with no new information. Adding a verifier that knows something — a compiler, a test suite, a solver, a retrieved document — is a different intervention with a different track record, covered in verifiers at inference time.

A different model is not the same as the same model

One variation does add information and is routinely confused with intrinsic self-correction: having a different model criticise the output. A second model has a different training mix, different gaps and different biases, so it can genuinely notice things the first could not. This is a real technique with a real effect, and it should not be dismissed by citing results about a model reviewing itself — those results are about a strictly weaker setup.

The caveats are the ones you would expect. The critic needs to be comparably capable, or it will mostly object to things it did not follow. Two models from the same family often share the same blind spots, which shrinks the benefit considerably. And you are now paying for two systems and maintaining two prompts, which is a real cost to weigh against simply routing the hard cases to a better model in the first place.

Where it does work

The exceptions are real and they all satisfy the rule.

Error classDescription
format violationsMissing field, wrong enum value, invalid JSON. The output is fully self-describing against a schema, so the check has everything it needs. Prefer a real validator, but a critique pass works.
explicit constraint checks"Does this answer mention a price? Does it stay under 80 words? Does it avoid naming a competitor?" A concrete checklist against finished text. This is reading comprehension, not reasoning.
source contradictionChecking each claim against the documents you supplied. The verifier has the documents in front of it and only one claim to consider at a time, which is genuinely easier than generating while tracking all of them.
recomputationRe-deriving an arithmetic result in isolation, away from the narrative that produced it. Best done by executing code rather than by asking again.
internal contradictionTwo parts of a long answer disagreeing. The generator could not see the end while writing the beginning; the critic can see both.

Notice that none of these is “is this answer right”. Every one is a specific, closed question with a stated criterion. That is the practical difference between a critique pass that earns its cost and one that produces confident approval of whatever it is shown.

A critique loop that is not a placebo

const CHECKS = [
  { id: "schema",   run: (o) => validate(SCHEMA, o) },        // real validator
  { id: "arith",    run: (o) => recompute(o.lineItems, o.total) },
  { id: "sourced",  run: (o) => everyClaimCited(o, docs) },   // model, but
                                                             // one claim at a time
];

async function produce(prompt, docs) {
  let out = await call(MODEL, prompt);

  for (let attempt = 0; attempt < 2; attempt++) {
    const failed = CHECKS.map(c => ({ c, r: c.run(out) }))
                         .filter(x => !x.r.ok);
    if (failed.length === 0) return out;

    // Repair against the NAMED failures only. Never "improve this".
    out = await call(MODEL, repairPrompt(out, failed.map(f => f.r.message)));
  }

  throw new UnverifiedOutput(out);   // escalate, do not ship it quietly
}

Three properties make this different from asking a model to review itself. The checks are enumerated in advance rather than invented per call. Two of the three are code, not inference. And the loop terminates in an explicit failure rather than in whatever the third attempt produced — an unbounded refine loop will eventually declare success on something, and that something is not usually the best of the three.

The failure mode to watch for

Instrument the loop for corrections that made things worse. The Huang result is not an abstraction: on a poorly designed loop, a meaningful share of revisions take a correct answer and break it, because the critic found something to say — as critics asked for criticism reliably do.

Two mitigations, both cheap. Give the critic an explicit “nothing to change” output and make it the expected result, rather than a prompt that presupposes a problem. And keep every version, so that when you compare the pre- and post-critique answers on your eval you can see the flip counts in both directions rather than the net — the same instrumentation argument as the flip-rate test in overthinking.

Finally, ask whether the check belongs earlier. A great deal of what a critique pass catches would never have happened with a stricter output schema, a better-specified prompt, or a tool the model could have called instead of guessing. A verification stage catches errors you decided to allow; preventing them is cheaper, deterministic, and does not add a second model call to every request. Reach for self-critique for the residue, not for the bulk — and when you do, write down which error class each check is meant to catch, so that a check which has never fired in a month can be deleted rather than inherited by whoever maintains this next.

Self-Verification: What Asking a Model to Check Its Work Catches · Multigrid