This example demonstrates the Reflection Agent design pattern - an AI agent that iteratively improves its responses through self-reflection and revision.
The Reflection pattern is a technique where an AI agent:
- Generates an initial response
- Reflects on its own output, critiquing quality and identifying improvements
- Revises the response based on the reflection
- Repeats until the response is satisfactory or max iterations are reached
This creates a feedback loop that produces higher-quality outputs than single-pass generation.
User Query → Generate → Reflect → Satisfied?
↑ ↓ No
└──── Revise ←─────────┘
↓ Yes
Final Response
- Generate Node: Creates initial response or revised version
- Reflect Node: Evaluates the response quality and suggests improvements
- Routing Logic: Decides whether to continue improving or finalize
- Max Iterations: Prevents infinite loops
- ✅ Iterative Improvement: Multiple rounds of refinement
- ✅ Self-Critique: AI reflects on its own outputs
- ✅ Customizable: Flexible prompts for different use cases
- ✅ Separate Models: Optionally use different models for generation vs reflection
- ✅ Smart Stopping: Automatically detects when output is satisfactory
go get github.com/smallnest/langgraphgopackage main
import (
"context"
"fmt"
"log"
"github.com/smallnest/langgraphgo/prebuilt"
"github.com/tmc/langchaingo/llms"
"github.com/tmc/langchaingo/llms/openai"
)
func main() {
// Create LLM
model, err := openai.New(openai.WithModel("gpt-4"))
if err != nil {
log.Fatal(err)
}
// Configure Reflection Agent
config := prebuilt.ReflectionAgentConfig{
Model: model,
MaxIterations: 3,
Verbose: true,
}
// Create agent
agent, err := prebuilt.CreateReflectionAgent(config)
if err != nil {
log.Fatal(err)
}
// Prepare query
initialState := map[string]any{
"messages": []llms.MessageContent{
{
Role: llms.ChatMessageTypeHuman,
Parts: []llms.ContentPart{
llms.TextPart("Explain the CAP theorem"),
},
},
},
}
// Invoke agent
result, err := agent.Invoke(context.Background(), initialState)
if err != nil {
log.Fatal(err)
}
// Extract final response
finalState := result.(map[string]any)
draft := finalState["draft"].(string)
fmt.Println(draft)
}config := prebuilt.ReflectionAgentConfig{
Model: generationModel,
ReflectionModel: reflectionModel, // Use separate model for reflection
MaxIterations: 3,
Verbose: true,
// Custom generation prompt
SystemMessage: "You are an expert technical writer.",
// Custom reflection prompt
ReflectionPrompt: `Evaluate for:
1. Technical accuracy
2. Clarity and organization
3. Completeness
4. Use of examples
Be specific in your feedback.`,
}| Option | Type | Default | Description |
|---|---|---|---|
Model |
llms.Model |
required | LLM for generation and reflection |
ReflectionModel |
llms.Model |
nil |
Optional separate model for reflection |
MaxIterations |
int |
3 |
Maximum refinement cycles |
SystemMessage |
string |
Default | Prompt for generation step |
ReflectionPrompt |
string |
Default | Prompt for reflection step |
Verbose |
bool |
false |
Enable detailed logging |
🎨 Generating initial response...
📝 Draft generated (1247 chars)
🤔 Reflecting on the response...
💭 Reflection:
**Strengths:**
- Clear definition of CAP theorem
- Good use of examples
**Weaknesses:**
- Missing trade-offs discussion
- Could explain practical implications better
**Suggestions for improvement:**
- Add section on real-world applications
- Include comparison of different database choices
🔄 Revising response (iteration 2)...
📝 Draft generated (1856 chars)
🤔 Reflecting on the response...
💭 Reflection:
**Strengths:**
- Comprehensive and well-structured
- Excellent examples and practical applications
- Clear trade-off discussions
**Weaknesses:**
- No major issues
**Suggestions for improvement:**
- No improvements needed
✅ Response is satisfactory, finalizing
=== Final Response ===
[Improved CAP theorem explanation...]
Generate high-quality documentation with multiple rounds of refinement.
config := prebuilt.ReflectionAgentConfig{
SystemMessage: "You are an expert technical writer creating clear documentation.",
ReflectionPrompt: "Evaluate for clarity, completeness, examples, and structure.",
}Provide thoughtful, constructive code review feedback.
config := prebuilt.ReflectionAgentConfig{
SystemMessage: "You are an experienced software engineer providing code review.",
ReflectionPrompt: "Evaluate for constructiveness, completeness, and professionalism.",
}Create blog posts, articles, or educational content with iterative improvement.
config := prebuilt.ReflectionAgentConfig{
SystemMessage: "You are a skilled content creator writing engaging articles.",
ReflectionPrompt: "Evaluate for engagement, accuracy, structure, and readability.",
}Generate well-reasoned solutions to complex problems.
config := prebuilt.ReflectionAgentConfig{
SystemMessage: "You are a problem-solving expert providing thorough analysis.",
ReflectionPrompt: "Evaluate for logical reasoning, completeness, and clarity.",
}export OPENAI_API_KEY=your_key
cd examples/reflection_agent
go run main.goThe example demonstrates three scenarios:
- Basic Reflection: Explaining CAP theorem
- Technical Writing: Creating API documentation
- Code Review: Reviewing Go code
The agent maintains the following state:
{
"messages": []llms.MessageContent, // Conversation history
"draft": string, // Current response draft
"reflection": string, // Latest reflection feedback
"iteration": int, // Current iteration count
"is_satisfactory": bool, // Whether response is good enough
}- Higher Quality: Outputs are refined through multiple iterations
- Self-Correcting: Agent identifies and fixes its own mistakes
- Consistent: Follows evaluation criteria systematically
- Flexible: Customizable for different domains and use cases
- Transparent: Verbose mode shows the improvement process
| Feature | Single-Pass | ReAct | Reflection |
|---|---|---|---|
| Quality | Variable | Good | High |
| Iterations | 1 | Variable | Controlled |
| Self-Critique | No | No | Yes |
| Refinement | No | Limited | Yes |
| Use Case | Simple tasks | Tool use | Quality writing |
| Latency | Low | Medium | High |
- Simple tasks: 2-3 iterations
- Complex tasks: 3-5 iterations
- Critical content: 5+ iterations
Focus on specific evaluation criteria:
ReflectionPrompt: `Evaluate for:
1. [Specific criterion 1]
2. [Specific criterion 2]
3. [Specific criterion 3]
Be concrete and actionable in feedback.`- Same model: Simpler, more consistent
- Different models: Can leverage different strengths
- GPT-4 for generation, GPT-3.5 for reflection (cost optimization)
- Specialized models for domain-specific reflection
Enable verbose mode during development to understand the reflection process.
Too few: May not reach quality threshold Too many: Diminishing returns, higher cost
Solution: Check reflection prompt. Make sure it's not too lenient. The reflection should identify areas for improvement in early drafts.
Solution:
- Check if reflection prompt is too critical
- Verify the satisfactory detection logic
- Consider increasing max iterations for complex tasks
Solution: Provide more specific evaluation criteria in the reflection prompt with concrete examples of what to look for.
You can modify the isResponseSatisfactory function for custom logic:
// In your own implementation, you could:
// - Call LLM to rate response quality (1-10)
// - Use sentiment analysis on reflection
// - Check for specific keywords or patterns
// - Compare draft length with requirements- Experiment with different prompts for your use case
- Try using different models for generation vs reflection
- Integrate with your application's workflow
- Add custom evaluation metrics
- Combine with other agent patterns