Skip to content

Reflection & Self-Critique

Overview

Humans catch their own mistakes by reviewing their work. Agents can do the same.

Self-critique is one of the most effective ways to improve agent quality—simple to implement and powerful in practice.


How Reflection Works

Basic Reflection Loop

class ReflectiveAgent:
 """Agent that critiques its own work"""

 def solve_with_reflection(self, task):
 """Generate solution, then critique it"""

 # Step 1: Initial solution
 solution = self.generate_solution(task)

 # Step 2: Self-critique
 critique = self.self_critique(task, solution)

 # Step 3: Evaluate critique
 if critique.has_errors:
 # Step 4: Revise based on critique
 revised = self.revise_solution(
 task, 
 solution, 
 critique
)
 return revised

 return solution

 def generate_solution(self, task):
 """Generate initial attempt"""

 prompt = f"""Solve this task: {task}

 Provide your solution."""

 return self.llm.call(prompt)

 def self_critique(self, task, solution):
 """Critique the solution"""

 prompt = f"""
 Task: {task}
 Proposed solution: {solution}

 Critique this solution. What's wrong with it?
 What could be improved?
 """

 critique_text = self.llm.call(prompt)
 return self.parse_critique(critique_text)

 def revise_solution(self, task, solution, critique):
 """Improve solution based on critique"""

 prompt = f"""
 Task: {task}
 Original solution: {solution}
 Critique: {critique.text}

 Provide a revised solution that addresses the critique.
 """

 return self.llm.call(prompt)

Chain-of-Criticism Pattern

Multi-Round Reflection

class ChainOfCriticism:
 """Multiple rounds of critique"""

 def solve_with_iterations(self, task, max_iterations=3):
 """Iteratively improve through critique"""

 solution = self.generate_solution(task)

 for iteration in range(max_iterations):
 # Critique
 critique = self.critique(task, solution)

 # Analyze
 score = self.score_solution(task, solution, critique)

 # Check stopping criterion
 if score > 0.9: # Good enough
 break

 if critique.is_unsalvageable:
 break

 # Improve
 solution = self.improve(task, solution, critique)

 return solution

 def score_solution(self, task, solution, critique):
 """Rate solution quality"""

 scoring_prompt = f"""
 Task: {task}
 Solution: {solution}
 Critique: {critique}

 Rate solution quality 0-1. Be harsh, not generous.
 """

 score_text = self.llm.call(scoring_prompt)
 return float(score_text.strip())

When to Use:

  • Complex problems requiring multiple passes
  • High-stakes decisions
  • When initial attempts are often wrong

Cost: 3-4x tokens for 3 iterations Quality Improvement: +20-35% accuracy


Specific Critique Prompts

Code Review Critique

class CodeReviewCritique:
 """Critique code for common issues"""

 def critique_code(self, code, language):
 """Comprehensive code critique"""

 critique_areas = [
 "correctness", # Does it work?
 "efficiency", # Is it efficient?
 "readability", # Is it understandable?
 "security", # Are there vulnerabilities?
 "maintainability", # Is it maintainable?
 "edge_cases" # Does it handle edge cases?
]

 critiques = {}

 for area in critique_areas:
 prompt = f"""
 Review this {language} code for {area} issues:

 {code}

 List specific {area} problems. Be thorough.
 """

 critique = self.llm.call(prompt)
 critiques[area] = critique

 return critiques

 def suggest_improvements(self, code, critiques):
 """Generate improved version"""

 prompt = f"""
 Original code:
 {code}

 Issues found:
 {format_critiques(critiques)}

 Provide improved code that addresses all issues.
 """

 return self.llm.call(prompt)

Feedback-Driven Reflection

Learning from External Critique

class FeedbackReflection:
 """Agent learns from human feedback"""

 def solve_and_get_feedback(self, task):
 """Solve, get feedback, improve"""

 solution = self.generate_solution(task)

 # Ask human for feedback
 feedback = self.request_human_feedback(task, solution)

 if feedback.approved:
 # Good! Learn from this
 self.learn_from_success(task, solution, feedback)
 return solution
 else:
 # Not good. Learn from error
 self.learn_from_failure(
 task, 
 solution, 
 feedback.critique
)

 # Improve and retry
 improved = self.improve_from_feedback(
 task,
 solution,
 feedback.critique
)

 return improved

 def learn_from_failure(self, task, solution, feedback):
 """Record what went wrong"""

 learning_record = {
 'task': task,
 'failed_solution': solution,
 'feedback': feedback,
 'category': self.categorize_error(feedback)
 }

 self.memory.add_learning(learning_record)

 def improve_from_feedback(self, task, solution, feedback):
 """Generate improved version"""

 prompt = f"""
 Task: {task}
 Failed attempt: {solution}
 Human feedback: {feedback}

 Generate an improved solution that addresses the feedback.
 """

 return self.llm.call(prompt)

Avoiding Over-Critique

When NOT to Critique

class SmartCritique:
 """Only critique when needed"""

 def should_critique(self, task, solution):
 """Decide if critique is worth it"""

 factors = {
 'confidence': solution.confidence,
 'task_difficulty': self.estimate_difficulty(task),
 'expected_error_rate': self.base_error_rate(task),
 'critique_cost': 0.3 # Roughly 30% token cost
 }

 # Only critique if:
 # - Low confidence AND
 # - High difficulty AND
 # - Worth the token cost

 if factors['confidence'] > 0.85:
 return False # Already confident

 if factors['task_difficulty'] < 0.3:
 return False # Too easy, not worth it

 if factors['critique_cost'] > self.token_budget:
 return False # Can't afford

 return True # Critique is worthwhile

3 Warnings

Warning 1: Critique Blindness

# WRONG
# Agent critiques own work and misses obvious errors
solution = agent.generate()
critique = agent.self_critique(solution)
# Agent doesn't see its own mistakes

# RIGHT
# Use external critic (different model)
solution = agent.generate()
critic_model = different_model() # GPT-4 critiques Claude output
critique = critic_model.critique(solution)
# Different perspective catches errors

Warning 2: Infinite Refinement

# WRONG
while True:
 solution = generate()
 critique = self_critique(solution)
 if critique.perfect:
 break
 solution = improve(critique)

# Never good enough, loops forever
# Wastes tokens

# RIGHT
for iteration in range(max_iterations):
 solution = generate()
 critique = self_critique(solution)
 score = score_solution(critique)

 if score > 0.9 or iteration == max_iterations - 1:
 break

 solution = improve(critique)

Warning 3: Critiquing Wrong Things

# WRONG
# Critique code for security in simple script
code = "print('hello')"
security_critique = critique_for_security(code)
# Wastes tokens on non-issue

# RIGHT
# Critique only relevant aspects
if is_production_code(code):
 security_critique = critique_for_security(code)
elif is_performance_critical(code):
 efficiency_critique = critique_for_efficiency(code)
else:
 readability_critique = critique_for_readability(code)

# Focused critique

-

Last Updated: August 9, 2026