Skip to content

The Agent Loop and Acting

Reflection and self-correction

Reflexion, self-critique loops

An agent's first attempt is a draft. Reflection is the discipline of turning that draft into a better one: the model reads its own previous attempt plus a signal about what went wrong, and produces a fix. Done right, it is how a coding agent goes from red tests to green with no human in the loop. Done wrong, it is a model cheerfully congratulating itself on a broken answer. The whole difference is one ingredient, an external verifier.

Reflection is sequential self-improvement

In the canonical anatomy of an LLM agent, planning has three sub-capabilities: decomposition (break the goal into steps), reasoning (think each step through), and reflection (critique past actions and refine).[1] You met the first two in the previous lesson. This one is the third leg, the loop that lets an agent learn from its own mistakes within a single task, without any training.

Reflection is sequential: attempt to feedback to better attempt, each one conditioned on the last. That makes it fundamentally different from simply retrying from scratch (which throws the mistake away) and from (which votes across independent samples and never reads a result). Reflection's power, and its danger, is that the model is grading and revising its own work.

The evaluator-optimizer loop

The simplest useful shape is a two-role workflow that Anthropic calls : one LLM generates a candidate, another evaluates it against explicit criteria and returns feedback, and the loop repeats until the criteria are met.[2]

Tap a node to see what it does.

The evaluator-optimizer workflow. If the candidate fails, the evaluator's feedback loops back to the generator for another round, worth it only when the criteria are clear and iteration measurably helps.

The catch is in that last clause. This pattern earns its cost only when you have clear evaluation criteria and refinement demonstrably improves the result.[2] If "the criteria" is just the same model's opinion, you have built a machine for agreeing with yourself. Hold that thought, it is the crux of this lesson.

Reflexion: write the post-mortem, then retry

(Shinn et al., 2023) is the canonical algorithm that makes reflection concrete and gives it a memory.[3] Four moving parts:

  1. Actor. An LLM (often a ReAct-style loop) attempts the task and produces a trajectory.
  2. Evaluator. Turns the outcome into a reward signal: binary/scalar, from unit tests, or from environment feedback.
  3. Self-reflection model. Converts that sparse signal plus the trajectory into verbal feedback: a natural-language note on what went wrong and how to fix it.
  4. Episodic memory. Stores that reflection (the working buffer holds ~3 recent ones) and prepends it as context on the next trial. Then the actor retries.

No weights are updated, the model improves purely by reading its own written post-mortems. The authors call this "verbal reinforcement learning."[3] On code generation it reached 91% pass@1 on HumanEval, beating the then-GPT-4 baseline of 80%, precisely because the evaluator was a suite of unit tests, i.e. ground truth.[3]

Tap a node to see what it does.

The reflect to retry loop. A failure triggers a verbal reflection; the reflection is written to episodic memory; the actor retries with its own post-mortems in context. The loop exits when the evaluator passes. Nothing improves without that evaluator being a real signal.

Two built-in failure detectors

Reflexion also watches the trajectory for two stuck patterns and triggers a reflection when it sees them:[1] inefficient planning (the trajectory runs too long without success) and hallucination (a run of identical actions producing identical observations, the agent is spinning in place). Both are cheap heuristics you can wire into any loop, no ground-truth reward required.

Worked example: a coding agent fixing itself

Here is the loop on one concrete task, implement median(nums). The evaluator is a unit test, so the feedback is ground truth, and the reflection is carried forward in memory.

def median(nums):
    s = sorted(nums)
    return s[len(s) // 2]      # takes the upper-middle element only

# run tests -> FAILED test_median::even
#   assert median([1,2,3,4]) == 2.5   (got 3)
Attempt 1 - the actor writes code that takes the upper-middle element only, and fails the even-length test.

Reflection stored in episodic memory

"median([1,2,3,4]) returned 3, not 2.5. For an even-length list the median is the average of the two central elements, not a single index. Fix: branch on parity and average s[mid-1] and s[mid]."
def median(nums):
    s = sorted(nums)
    mid = len(s) // 2
    if len(s) % 2:                 # odd length -> single middle
        return s[mid]
    return (s[mid - 1] + s[mid]) / 2   # even -> average the middle pair

# run tests -> PASSED 4 / 4   (exit loop)
Attempt 2 - the actor retries with the reflection in context: branch on parity, average the middle pair, and pass all four tests.

Notice what actually did the work: the failing assertion named the exact input, the exact wrong output, and (implicitly) the exact contract. The reflection is a translation of a hard signal into a plan. Swap the unit test for a vague "does this look right?" and the same loop degrades into guessing.

Why does self-reflection reliably help this coding agent but often fail on closed-book reasoning?

The honest part: reflection needs a verifier

Here is the finding the demos gloss over. When the "evaluator" is the same model with no external ground truth, reflection frequently reinforces the error instead of fixing it, the model rationalizes its first answer, or sycophantically agrees that its own reasoning was fine.[2] Models are genuinely weak at self-correcting pure reasoning without a ground-truth signal to push against. Reflection is not magic introspection; it is a control loop, and a control loop with no sensor just amplifies noise.

Reflect against a real signal

  • Unit tests, a type-checker, a compiler, a linter.
  • An environment/tool that returns a real error or reward.
  • An independent checker, a different model, a rubric, or a judge with the reference.
  • A structural heuristic (loop detected, step budget blown).

Reflect against vibes

  • "Is this answer correct?" asked to the same model.
  • Self-scores with no reference to compare against.
  • Unbounded "keep improving" with no stopping condition.
  • Longer, thrashing reasoning mistaken for progress.[6]

Two ways the loop hurts you

Sycophantic self-agreement, with no external check, extra reflection rounds can talk the model out of a correct answer as easily as into one. And unbounded cost, every retry is another full trajectory; without a max_trials cap a "self-improving" agent can burn tokens forever. Always bound the loop and always give reflection a sensor it doesn't control.

Where does Self-Refine fit?

Single-model self-refine, one model plays both generator and critic, iterating on its own draft, is the evaluator-optimizer loop with the two roles collapsed into one. It works well for tasks with a checkable form (does this JSON validate? does this prose meet the rubric?) but inherits the caveat above for tasks whose correctness only the model can judge. When the critic and the author are the same weights, add an outside signal wherever you can.

Self-consistency: the parallel cousin (and why it is fading)

People often lump reflection together with , don't. Self-consistency samples many independent chains of thought and takes a majority vote on the final answer.[4] There is no feedback and no memory; it just bets that a correct answer is reachable by many valid paths and so it clusters. On 2022-era models it was a big win (+17.9% on GSM8K).[4] On modern reasoning models the edge has largely eroded: gains plateau around 5 to 10 samples and are often only +1 to 3%, while cost scales linearly with the sample count.[5]

Reflexion / self-reflectionSelf-consistency
ShapeSequential: attempt to feedback to better attemptParallel: N independent samples, then vote
Uses feedback?Yes, an external signal drives the critiqueNo, it never inspects any result
MemoryEpisodic buffer of past reflectionsNone
Best forTasks with a checkable signal (tests, env, rubric)Tasks with one discrete, votable answer
Costx number of trialsx number of samples
2026 notePersists where signals are cheap[3]Gains plateau ~5 to 10 samples[5]
Reflexion is sequential improvement driven by feedback; self-consistency is parallel variance reduction with no feedback and no memory.

How does self-consistency differ from Reflexion-style self-reflection?

When to reach for it

Anthropic's number-one rule applies here as everywhere: use the simplest thing that passes your eval, and add reflection only when it measurably helps.[2] A useful checklist before you bolt on a reflect to retry loop:

  1. Do you have a cheap, reliable signal? Unit tests, a validator, an environment reward, an independent judge. If not, build one first, reflection without it is theater.
  2. Does iteration actually improve the metric? Measure attempt-2 vs attempt-1 on real cases. Sometimes it doesn't move, or it regresses.
  3. Is the loop bounded? A hard max_trials and the stuck-loop detectors from Reflexion keep cost and runaway behavior in check.
  4. Is the memory managed? Long trajectories plus accumulated reflections eat the context window, which is exactly the discipline of context engineering (next lesson), and why the buffer holds only the last few reflections.

The one-line model

Reflection converts a signal about failure into a plan to fix it, carried forward in memory. It is a control loop, and a control loop is only as good as its sensor. Give it a real one (tests, tools, a judge) and it turns red into green on its own; give it none and it just agrees with itself louder.

Check yourself

Match each source of feedback to what it grounds the critique on.

drop here

the model re-reading its own output

drop here

a test suite, compiler, or type checker

drop here

observed effect of an action in the world

drop here

a separate model or rubric scoring it

The four moving parts of the Reflexion loop, and the one thing it never updates.

Why is it called verbal reinforcement learning? Try to state it, then check.

Lock it in

  • Reflection is sequential self-improvement: attempt to feedback to better attempt, carried forward in memory, distinct from a blind retry and from a parallel vote.
  • Reflexion is verbal reinforcement learning: actor, evaluator, a verbal self-critique, and an episodic buffer that is re-read on the next trial. No weight updates; 91% pass@1 on HumanEval because the evaluator was unit tests.
  • The verifier is everything. Models are weak at self-correcting pure reasoning; without external ground truth, reflection can reinforce the mistake or sycophantically agree with it.
  • Wire reflection to a real signal, tests, tools, an independent judge, or structural heuristics (loop / step-budget), not to the same model's opinion.
  • Bound the loop: a max_trials cap plus stuck-loop detection; and add it only when it measurably beats the simpler baseline.

Primary source

Shinn et al., Reflexion: Language Agents with Verbal Reinforcement Learning (NeurIPS 2023)

The canonical algorithm behind this lesson: the actor/evaluator/self-reflection/memory loop, the "verbal RL" framing, the stuck-loop heuristics, and the HumanEval results where a real test suite is the verifier.

Sources

  1. 1.Lilian Weng, LLM Powered Autonomous Agents (2023)
  2. 2.Anthropic, Building Effective Agents
  3. 3.Shinn et al., Reflexion: Language Agents with Verbal Reinforcement Learning (2023)
  4. 4.Wang et al., Self-Consistency Improves Chain of Thought Reasoning (2022)
  5. 5.On the diminishing returns of majority voting in reasoning models (2025)
  6. 6.Wang et al., Thoughts Are All Over the Place: Underthinking in o1-like LLMs (2025)