# Reflexion patterns: letting agents correct themselves

[Skip to content](#lm-inhoud)Network/[NL](/en/reflexion-patronen-agents-zichzelf-laten-corrigeren)EN[Hubhub.llmnet.nlCompare models on task, language, cost and licence.](https://hub.llmnet.nl/en/)[Communitycommunity.llmnet.nlPrompt techniques, patterns and system prompts.](https://community.llmnet.nl/en/)[APIapi.llmnet.nlLLMs in production: rate limits, routing, structured output.](https://api.llmnet.nl/en/)[Consultancyconsultancy.llmnet.nlRolling out AI in an organisation, pilot to production.](https://consultancy.llmnet.nl/en/)[Newsnieuws.llmnet.nlAI developments, explained for the Netherlands.](https://nieuws.llmnet.nl/en/)[Benchmarkbenchmark.llmnet.nlMeasure AI quality yourself, on your own tasks.](https://benchmark.llmnet.nl/en/)[Careersvacatures.llmnet.nlAI roles, salaries and career paths in the Netherlands.](https://vacatures.llmnet.nl/en/)[Learnleren.llmnet.nlAI concepts in plain language, beginner to builder.](https://leren.llmnet.nl/en/)[Guidegids.llmnet.nlRun AI privately on your own Mac, PC, NAS or home server.](https://gids.llmnet.nl/en/)[Directorydirectory.llmnet.nlMapping the AI ecosystem: tools, models, companies.](https://directory.llmnet.nl/en/)[Radarradar.llmnet.nlSignals from X, research and communities for indie developers.](https://radar.llmnet.nl/en/)[Appsapps.llmnet.nlReviews of AI apps and open-source repos, with tips for builders.](https://apps.llmnet.nl/en/)[llmnet.nl — main site](https://llmnet.nl/en/)[](https://x.com/intent/post?url=https%3A%2F%2Fcommunity.llmnet.nl%2Fen%2Freflexion-patronen-agents-zichzelf-laten-corrigeren&text=Reflexion%20patterns%3A%20letting%20agents%20correct%20themselves)[](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcommunity.llmnet.nl%2Fen%2Freflexion-patronen-agents-zichzelf-laten-corrigeren)[](https://www.reddit.com/submit?url=https%3A%2F%2Fcommunity.llmnet.nl%2Fen%2Freflexion-patronen-agents-zichzelf-laten-corrigeren&title=Reflexion%20patterns%3A%20letting%20agents%20correct%20themselves)[](#)[](https://x.com/intent/post?url=https%3A%2F%2Fcommunity.llmnet.nl%2Fen%2Freflexion-patronen-agents-zichzelf-laten-corrigeren&text=Reflexion%20patterns%3A%20letting%20agents%20correct%20themselves)[](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcommunity.llmnet.nl%2Fen%2Freflexion-patronen-agents-zichzelf-laten-corrigeren)[](https://www.reddit.com/submit?url=https%3A%2F%2Fcommunity.llmnet.nl%2Fen%2Freflexion-patronen-agents-zichzelf-laten-corrigeren&title=Reflexion%20patterns%3A%20letting%20agents%20correct%20themselves)[](#)

 
# Reflexion patterns: letting agents correct themselves

 By Ivo Donker — compiled with AI assistance (Claude & Gemini)

 When a language model performs a complex task, reasoning errors, incorrect tool calls, or invalid data formats inevitably occur. In traditional software environments, this leads to hard exceptions or crashing scripts. In autonomous AI systems, a simple retry often accomplishes little: with the same input prompt, the model simply makes the same mistake again. The Reflexion pattern solves this fundamental problem by introducing dynamic self-reflection. Instead of updating weights through expensive fine-tuning, the system learns during runtime by verbally analyzing errors and storing these insights in a temporary episodic memory.

 This article explains step by step how Reflexion architectures are built, which components are strictly necessary, how memory is managed, and how pitfalls such as infinite reflection loops are avoided. Anyone making the move from loose prompts to complex rule systems will discover here how self-correction makes an agent robust against unpredictable input.

 
## The anatomy of the Reflexion framework

 The Reflexion pattern splits the execution of a task into three separate roles: the Actor, the Evaluator and the Self-Reflection model. This separation prevents a model from uncritically approving its own work and ensures a reproducible feedback cycle.

 The interaction follows a fixed rhythm:

 
 
- The Actor generates actions: The Actor receives the initial task and any earlier reflections from memory. Based on this, it generates an answer, executes a series of function calls, or produces structured code.
 
- The Evaluator tests the outcome: The Evaluator inspects the produced output. This can be a deterministic test (such as a linter, unit test, or schema validator) or an LLM-based judge. The outcome is a binary success/fail signal or a specific error message with details.
 
- The Reflector analyzes the mismatch: If the task fails, the Reflector receives the task description, the failed trajectory, and the error message from the Evaluator. The Reflector generates a concise, constructive analysis that specifies exactly what went wrong and how the next attempt should be adjusted.
 
- Memory storage: This reflection text is added to an episodic buffer and passed directly to the Actor for the next iteration.
 

 For a broader overview of how loops and state machines relate to static prompts, read the foundation in [from prompt engineering to graph engineering](https://community.llmnet.nl/en/van-prompt-naar-graph-engineering).

 
## Why ordinary prompt loops fail without verbal reflection

 Many developers build a simple feedback loop in which, on an error, the raw traceback is simply sent back to the model with the message: "This failed, try again". In practice, this turns out to be remarkably ineffective for complex reasoning tasks. Without an explicit reflection step, the model's attention mechanism stays fixed on its earlier reasoning path.

 The crucial difference lies in the verbal representation of the error. By forcing the model to formulate an intermediate analysis ("I chose API method X because I assumed parameter Y was optional, but the validation requires parameter Y. On the next attempt I need to check parameter Y first"), the context is transformed. The generated reflection acts as dynamic system information that helps the model avoid stepping into the same logical trap again.

 A detailed breakdown of basic tool calls and planning structures is described in [prompt patterns for AI agents](https://community.llmnet.nl/en/prompt-patronen-voor-agents).

 
## Managing the episodic reflection memory

 The episodic memory forms the working memory of the Reflexion agent throughout one specific task. Because every context window is finite and unnecessary tokens drive up costs, not every failed intermediate result can remain in the prompt in full. The memory must stay compact and focused.

 There are two common strategies for memory management in production systems:

 
 
- Sliding window (FIFO): Only the last two or three reflections are kept. Older failure trajectories are discarded. This keeps the prompt short, but carries the risk that an agent repeats an earlier mistake after four attempts.
 
- Semantic reflection aggregation: After each failed attempt, the Reflector summarizes earlier reflections into one consolidated list of lessons learned and constraints. This keeps the token count nearly constant, regardless of the number of iterations.
 

 
 
 
 
 Memory strategy | 
 Token impact | 
 Complexity | 
 Suitable for | 
 

 
 
 
 Full history | 
 Very high (exponential) | 
 Low | 
 Short tasks (maximum 2 iterations) | 
 

 
 Sliding window (k=2) | 
 Low (linearly bounded) | 
 Low | 
 Standard code generation and parsing | 
 

 
 Aggregated lessons | 
 Constant | 
 Medium | 
 Complex multi-step research tasks | 
 

 
 
 

 
## Evaluator mechanisms: Deterministic versus LLM-as-a-Judge

 The reliability of a Reflexion loop stands or falls with the quality of the Evaluator. When the Evaluator wrongly approves a faulty solution (false positive) or rejects a correct solution (false negative), the agent gets thrown off track.

 In robust architectures, preference is always given to deterministic evaluators wherever possible. Think of JSON Schema validation, TypeScript compilation tests, or sandboxed runs with Pytest. Deterministic evaluators provide unambiguous feedback and don't consume extra tokens for the judging step.

 When the quality of free text, summaries, or creative argumentation needs to be assessed, a deterministic check is insufficient. In those cases, a secondary language model is deployed as LLM-as-a-Judge. The prompt for this evaluator must contain strict rubrics with binary scoring criteria. Avoid vague instructions such as "Judge whether this answer is good"; instead, define explicit checkpoints (for example: "Does the answer contain all three required sources? Is the format strictly Markdown? Does it contain no hallucinations relative to the supplied context?").

 For specific patterns around direct schema repairs without a full memory buffer, consult the guide on [recovery prompts for failed validation of LLM output](https://community.llmnet.nl/en/herstelprompts-bij-gefaalde-validatie-van-llm-output).

 
## Implementation: A complete Reflexion loop in Python

 Below is a concrete, modular Python example in which an agent performs a data transformation task. The loop combines an Actor, a deterministic validator, and a Reflector that generates and stores feedback directly on errors.

 import json
from typing import List, Dict, Any, Optional

class ReflexionEngine:
 def __init__(self, llm_client, max_trials: int = 3):
 self.llm = llm_client
 self.max_trials = max_trials
 self.reflections: List[str] = []

 def execute_task(self, instruction: str) -> Optional[Dict[str, Any]]:
 for trial in range(1, self.max_trials + 1):
 # 1. Actor genereert output met historische reflecties
 actor_prompt = self._build_actor_prompt(instruction)
 candidate_output = self.llm.generate(actor_prompt)

 # 2. Evaluator valideert het resultaat
 is_valid, error_log = self._evaluate(candidate_output)
 if is_valid:
 return json.loads(candidate_output)

 # 3. Reflector analyseert de fout bij mislukking
 if trial < self.max_trials:
 reflection = self._reflect(instruction, candidate_output, error_log)
 self.reflections.append(f"Poging {trial} fout: {reflection}")

 return None

 def _build_actor_prompt(self, instruction: str) -> str:
 memory_context = "\n".join(self.reflections)
 return f"""Taak: {instruction}

Lessen uit eerdere mislukte pogingen:
{memory_context if memory_context else "Geen eerdere pogingen."}

Genereer uitsluitend geldige JSON die voldoet aan de taakeisen."""

 def _evaluate(self, raw_output: str) -> (bool, str):
 try:
 data = json.loads(raw_output)
 if "id" not in data or "status" not in data:
 return False, "Sleutels 'id' en 'status' zijn verplicht."
 if not isinstance(data["id"], int):
 return False, "Veld 'id' moet een integer zijn."
 return True, ""
 except json.JSONDecodeError as err:
 return False, f"Ongeldige JSON syntaxis: {str(err)}"

 def _reflect(self, task: str, failed_output: str, error: str) -> str:
 reflect_prompt = f"""Je bent een reflectiemodel. Analyseer de fout.
Taak: {task}
Gefaalde output: {failed_output}
Foutmelding: {error}

Geef een bondige analyse van maximaal twee zinnen: wat ging er mis
en welke specifieke wijziging lost dit op in de volgende poging?"""
 return self.llm.generate(reflect_prompt)

 
## Pitfalls: Reflection drift, vicious cycles, and hallucination

 Although Reflexion can significantly increase the accuracy of agents, it also brings specific failure mechanisms that must be actively managed:

 
 
- Hallucination of the reflection (reflection drift): The Reflector comes up with an incorrect explanation for the error (for example: "The query failed because the table doesn't exist", while the query actually failed due to a missing comma). The Actor blindly adopts this incorrect assumption and tries to fix the problem in a place where there is no error.
 
- Vicious correction cycles: The agent alternates between two faulty states. In attempt 1 it uses method A (fails on memory), in attempt 2 it reflects and chooses method B (fails on timeout), and in attempt 3 it reflects again and falls back to method A.
 
- Over-correction: After a minimal error message, the agent rewrites its entire reasoning path, causing correct intermediate steps to be lost.
 

 To curb these problems, three mitigating measures are applied:

 
 
- Lowering the temperature: Set the Reflector's temperature lower (for example between 0.0 and 0.2) than the Actor's. This enforces analytical, deterministic analysis.
 
- Hard failure limit: Strictly set the maximum number of attempts to 3 to 5. More iterations rarely still produce a breakthrough and lead to token waste.
 
- Backtracking and deterministic context injection: Always give the Reflector the exact error messages from the underlying system, so it doesn't have to guess at the cause.
 

 Anyone wanting to dig deeper into stalled cycles and infinite calls will find practical diagnostics in the article on [debugging agentic loops](https://community.llmnet.nl/en/agentic-loops-debuggen).

 
## Cost, latency, and performance trade-offs in production

 Introducing a Reflexion loop brings substantial cost and latency with it. Every extra attempt requires at least two LLM calls (one for the Reflector and one for the Actor's new attempt). For a task that only succeeds after three iterations, total token consumption can quadruple compared to a single-shot call.

 
 
 
 
 Architectural pattern | 
 Average latency | 
 Relative cost | 
 Success rate on complex tasks | 
 

 
 
 
 Single-shot prompting | 
 Low (1x) | 
 1x (baseline) | 
 Moderate to low | 
 

 
 Chain-of-Thought (static) | 
 Low to medium (1.5x) | 
 1.5x | 
 Medium | 
 

 
 Naive retry loop | 
 High (3x - 5x) | 
 3x - 5x | 
 Moderate | 
 

 
 Reflexion (Actor + Reflector) | 
 High (3x - 6x) | 
 3.5x - 7x | 
 High | 
 

 
 
 

 The trade-off is therefore clear: Reflexion is rarely suitable for latency-sensitive, interactive applications such as real-time consumer chat applications. However, the pattern excels in asynchronous background processes, such as automated code refactoring, complex ETL extraction pipelines, and report generation, where a faulty outcome would require manual human intervention.

 
## Testing and monitoring Reflexion agents

 Because an agent with a Reflexion pattern reasons across multiple iterations, traditional input/output monitoring is insufficient. It's not enough to only check whether the final outcome is correct; the path leading there must also be visible.

 Key metrics to track when testing reflection loops:

 
 
- First-Trial Accuracy: The percentage of tasks that succeed directly on the first attempt, without reflection. A low score points to shortcomings in the Actor's base prompt.
 
- Reflection Recovery Rate: The percentage of tasks that still get completed successfully after an initial failure, thanks to reflection. This is the direct gauge of the Reflector's effectiveness.
 
- Loop Exhaustion Rate: How often the maximum iteration limit is reached without a valid solution being found.
 
- Token Multiplier: The ratio between the tokens consumed on successful first-trial runs and runs that go through the reflection loop.
 

 To systematically measure whether introducing reflection steps increases your success rate without disproportionately driving up costs, check the measurement methods in the overview of [agent evaluation and trajectory analysis](https://benchmark.llmnet.nl/en/agent-evaluatie).

 
## Practical rules of thumb for implementation

 The following guidelines offer support when designing self-correcting agent architectures:

 
 
- Keep reflections concise: Instruct the reflection model to formulate the core error and the solution in a maximum of two sentences. Long essays pollute the context and cause the Actor to lose focus.
 
- Isolate the evaluation: Never let the Actor judge itself. Use deterministic code or a strictly prompted evaluator model.
 
- Remove raw error logs after reflection: Once the Reflector has made a useful synthesis of a traceback, the hundred-line error message no longer needs to remain in the context window. The concise reflection is enough.
 
- Set hard limits on iterations: Limit the number of attempts to a maximum of three for standard tasks and a maximum of five for heavy programming tasks.
 

 By consistently applying these design principles, a fragile chain of LLM calls transforms into a resilient, self-learning system that recovers independently from unforeseen errors.
