Self-Evolution & Learning: Agents That Improve Over Time¶
Overview¶
Static prompts get stale. Agents need to adapt and improve based on feedback.
Self-evolution is the path from prototype to production-grade systems.
Learning Mechanisms¶
Type 1: Prompt Optimization¶
class PromptOptimization:
"""Learn better prompts over time"""
def __init__(self):
self.base_prompt = "You are a helpful assistant."
self.learned_modifications = {}
def execute(self, task):
"""Execute with learned prompt improvements"""
# Start with base
current_prompt = self.base_prompt
# Add learned improvements for this task category
category = self.categorize_task(task)
if category in self.learned_modifications:
current_prompt += self.learned_modifications[category]
return self.llm.call(current_prompt + task)
def learn_from_feedback(self, task, output, feedback):
"""Learn prompt modifications"""
if feedback.success:
# Extract what worked
successful_modification = self.extract_key_phrases(output)
category = self.categorize_task(task)
self.learned_modifications[category] = successful_modification
# Save to persistent storage
self.persist_learning(category, successful_modification)
def extract_key_phrases(self, output):
"""Find what made this output successful"""
# Analysis might show: "think step by step" was key
# Or: "be concise" worked better
# Or: specific format was crucial
analysis_prompt = f"""
What instructions or approach led to this good output?
Output: {output}
Extract the implicit instructions.
"""
return self.llm.call(analysis_prompt)
Type 2: Tool Discovery¶
class ToolDiscovery:
"""Agent discovers useful tools"""
def __init__(self):
self.available_tools = []
self.learned_tools = {} # Tools discovered by agent
def execute_with_tool_learning(self, task):
"""Discover and use useful tools"""
# Combine pre-defined + learned tools
all_tools = self.available_tools + self.get_learned_tools()
agent = Agent(tools=all_tools)
result = agent.execute(task)
# Did agent use tools effectively?
if result.used_unexpected_tools:
# Learn: these tools are useful
for tool in result.unexpected_tools:
self.learn_tool_utility(tool, task, result)
return result
def learn_tool_utility(self, tool, task, result):
"""Record tool effectiveness"""
if result.success:
# Tool helped!
if tool not in self.learned_tools:
self.learned_tools[tool] = {
'success_count': 0,
'use_cases': []
}
self.learned_tools[tool]['success_count'] += 1
category = self.categorize_task(task)
self.learned_tools[tool]['use_cases'].append(category)
Type 3: Pattern Learning¶
class PatternLearning:
"""Agent discovers effective patterns"""
def __init__(self):
self.successful_patterns = {}
def learn_from_success(self, task, solution, feedback):
"""Extract patterns from successful solutions"""
if not feedback.success:
return
# Analyze solution
pattern = self.extract_pattern(task, solution)
task_type = self.categorize_task(task)
if task_type not in self.successful_patterns:
self.successful_patterns[task_type] = []
self.successful_patterns[task_type].append(pattern)
def extract_pattern(self, task, solution):
"""What approach worked?"""
prompt = f"""
Task: {task}
Successful solution: {solution}
What pattern or approach led to success?
Format: "When task is [type], [approach] works well"
"""
return self.llm.call(prompt)
def apply_learned_patterns(self, task):
"""Use patterns learned from past success"""
task_type = self.categorize_task(task)
if task_type not in self.successful_patterns:
return None
patterns = self.successful_patterns[task_type]
prompt = f"""
Task: {task}
Successful patterns for this type:
{format_patterns(patterns)}
Apply these patterns to solve the task.
"""
return self.llm.call(prompt)
Learning Safeguards¶
Preventing Dangerous Learning¶
class SafeLearning:
"""Learn but prevent harmful drift"""
def __init__(self):
self.learning_enabled = True
self.max_drift_allowed = 0.15 # 15% behavior change
self.performance_baseline = None
def learn_with_safeguards(self, task, output, feedback):
"""Learn but stay within bounds"""
if not self.learning_enabled:
return
# Record learning
learning = self.extract_learning(task, output, feedback)
# Simulate application
simulated_performance = self.simulate_learning(learning)
# Check against baseline
performance_change = abs(
simulated_performance - self.performance_baseline
)
if performance_change > self.max_drift_allowed:
# Too much change! Don't learn
self.alert(f"Learning blocked: {performance_change} drift")
return
# Safe to apply
self.apply_learning(learning)
self.update_baseline(simulated_performance)
def extract_learning(self, task, output, feedback):
"""What would we learn?"""
return {
'modification': self.compute_modification(output),
'category': self.categorize_task(task),
'confidence': feedback.confidence
}
def simulate_learning(self, learning):
"""Estimate performance if we learn"""
# Run Monte Carlo simulation
# Test against past tasks
test_results = []
for past_task in self.memory.get_past_tasks():
# What would we do with the new learning?
simulated_output = self.simulate_with_learning(
past_task,
learning
)
# Evaluate
score = self.evaluate_output(past_task, simulated_output)
test_results.append(score)
return sum(test_results) / len(test_results)
Long-Term Adaptation¶
Detecting When to Stop Learning¶
class LearningGracePeriod:
"""Know when to stop learning"""
def __init__(self):
self.learning_active = True
self.performance_history = []
self.stagnation_threshold = 10 # iterations
def check_learning_progress(self):
"""Is learning still helping?"""
recent = self.performance_history[-self.stagnation_threshold:]
# Check for improvement
improvement = recent[-1] - recent[0]
if improvement < 0.01: # No improvement
return 'stagnant'
# Check for oscillation
variance = self.compute_variance(recent)
if variance > 0.05: # Bouncing around
return 'oscillating'
# Check for degradation
if recent[-1] < recent[0]:
return 'degrading'
return 'healthy'
def maybe_stop_learning(self):
"""Decide if learning should stop"""
status = self.check_learning_progress()
if status == 'stagnant':
self.learning_active = False
self.alert("Learning stopped: performance plateau")
elif status == 'oscillating':
self.learning_active = False
self.alert("Learning stopped: unstable")
elif status == 'degrading':
# Rollback
self.rollback_last_learning()
self.alert("Learning rolled back: performance dropped")
3 Warnings ⚠️¶
Warning 1: Catastrophic Forgetting¶
# ❌ WRONG
# Learn new task, forget old capability
agent.learn_new_task(task_b)
# But now agent is worse at task_a!
# ✅ RIGHT
# Test performance on old tasks before learning
old_performance = test_on_old_tasks()
learn_new(task_b)
new_performance = test_on_old_tasks()
if new_performance < old_performance:
rollback() # Don't corrupt old knowledge
Warning 2: Compounding Errors¶
# ❌ WRONG
# Learn from potentially wrong feedback
agent.learn_from_feedback(user_input)
# But user feedback might be wrong!
# Wrong learning compounds over time
# ✅ RIGHT
# Verify feedback quality
if verify_feedback_confidence(user_input) > 0.8:
agent.learn_from_feedback(user_input)
else:
discard() # Don't learn from low-confidence feedback
Warning 3: Prompt Injection Learning¶
# ❌ WRONG
# Learn from user-provided feedback
user_feedback = parse(request)
agent.learn(user_feedback)
# Adversary: "I'll teach you to delete things"
# Agent learns bad behaviors
# ✅ RIGHT
# Only learn from verified internal feedback
if verify_feedback_source(source) == 'internal':
agent.learn(feedback)
else:
log_attempt(source) # Track attacks
Last Updated: August 9, 2026