Skip to content
AI360XpertBeta

Self Reflection Agents

A self-reflection agent reads its own draft like a reviewer, names what is wrong, and rewrites once before the answer ships.

A self-reflection agent drafts a mean function, the critic rejects it for a missing empty-list guard, and the revision passes all four checks.
A self-reflection agent drafts a mean function, the critic rejects it for a missing empty-list guard, and the revision passes all four checks.

Why Does This Exist?

A single model call ships its first draft. Ask for a mean function and it writes sum(xs) / len(xs), which is correct on every list except the empty one, where it divides by zero. In a demo you shrug. In a pipeline the crash pages someone at night.

A self-reflection agent adds a reviewer between the draft and the user. The generator writes, a critic checks the draft against a short list of requirements, and the generator rewrites once with the critique in front of it. The loop catches the errors a first draft almost always carries.

This page covers that draft-critique-revise loop and its stop rule. The step-by-step loop underneath is ReAct. Breaking the job into steps first lives in task decomposition. Splitting the work across people instead of drafts lives in supervisor subagent patterns.

Basics first: the critic never solves the task. It reads a draft plus the requirements and returns either PASS or a named miss. Generation and judgment stay in separate calls so the second can disagree with the first.

Think of It Like This

The cook who tastes before plating

A line cook finishes a sauce and does not send it out. They spoon a taste, find it under-salted, add a pinch, and taste again. The first taste is the draft. The wince is the critique. The pinch is the revision. The second taste that passes is the stop rule.

Map it point for point. The recipe is the task. The spoon is the test the critic runs. The salt gap is the named miss. The re-taste is the second draft checked against the same spoon.

Where it stops: a cook trusts one tongue. An agent should not trust one model twice on hard tasks, because the same blind spot can approve its own error. That is why the critic gets a checklist and a low temperature while the generator stays creative.

How It Actually Works

Two roles circle one draft. Call the draft d1d_1, the critique cc, the revision d2d_2, and the requirement list RR. Here RR has four checks: correct mean on [2, 4, 6], correct mean on [5], empty list returns 0.00.0 instead of crashing, and no side effects. The critic returns PASS only when all four hold.

The three calls

  • Generate. The generator sees the task plus RR and writes d1d_1. No tools, one call, first attempt kept honest by the checklist in the prompt.
  • Critique. The critic sees the task, d1d_1, and RR, and runs each check. It writes cc: which checks passed, which failed, and the smallest fix. It never rewrites the code itself.
  • Revise. The generator sees the task, d1d_1, and cc, and writes d2d_2. Then the critic reads d2d_2 once more. PASS ships it. Anything else stops at the turn cap.

Worked example

Task: "Write mean(xs) over [2, 4, 6], [5], and []."

Draft d1d_1 is return sum(xs) / len(xs). Score it by hand. On [2, 4, 6] the sum is 2+4+6=122 + 4 + 6 = 12, divided by 33 gives 4.04.0. Correct. On [5] the sum is 55, divided by 11 gives 5.05.0. Correct. On [] the sum is 00 and the length is 00, so 0/00 / 0 raises. That is 33 of 44 checks, and the critic writes: "Fail: empty list divides by zero. Fix: return 0.00.0 when the list is empty."

Revision d2d_2 adds the guard first, then the division. Score it again: 4.04.0, 5.05.0, 0.00.0, no side effects. That is 44 of 44, so the critic returns PASS. Two drafts plus one critique make 33 model calls against 11 for single-pass, which is the price of the catch.

Use this loop for code, math, and plans a reviewer can check. Skip it for chat, where a second call buys polish nobody asked for and doubles the bill.

Code

The point here is the checklist, not a model API. This stdlib-only script replays the same drafts and counts the same checks, so the numbers match the worked example:

def draft_v1(xs: list[float]) -> float:    return sum(xs) / len(xs)

def draft_v2(xs: list[float]) -> float:    if not xs:        return 0.0    return sum(xs) / len(xs)

def checks(fn) -> int:    score = 0    if fn([2.0, 4.0, 6.0]) == 4.0:        score += 1    if fn([5.0]) == 5.0:        score += 1    try:        ok = fn([]) == 0.0    except ZeroDivisionError:        ok = False    if ok:        score += 1    if fn([2.0, 4.0, 6.0]) == 4.0:  # pure: same input, same output        score += 1    return score

print(checks(draft_v1))  # -> 3print(checks(draft_v2))  # -> 4print((2.0 + 4.0 + 6.0) / 3)  # -> 4.0

Draft one scores 33, draft two scores 44, and the mean line reproduces 4.04.0. The guard is one if statement, and that statement is the whole difference between shipping and paging.

Watch Out For

The reviewer who approves its own error

Symptom: generator and critic share one model, one temperature, one prompt style, and PASS arrives on a draft that still crashes. The critic shares the blind spot it was asked to check.

Give the critic a written checklist, a low temperature, and no permission to rewrite. On important tasks use a stronger model for the critic than the generator. Agreement without a checklist is not a review.

A revision loop with no cap

Symptom: the trace shows draft three, critique three, draft four, each slightly reworded, the bill climbing with every call. The pair disagrees forever and nothing ships.

Cap the loop at two or three drafts in code, not in prose, and ship the best-scoring draft when the cap hits. Log every score so you can see whether revision three ever beats revision one.

The Quick Version

  • Self-reflection splits one task into a generator that drafts and a critic that checks against a written list.
  • A worked mean function scores 3 of 4 on draft one and 4 of 4 on draft two after adding an empty-list guard.
  • The critic returns PASS or one named miss, and the loop stops on PASS or a cap near three drafts.
  • Two drafts plus one critique cost 3 model calls against 1 for single-pass generation.
  • A shared model reviewing itself needs a checklist and low temperature, or approvals mean nothing.