跳到主要内容

Agent 自我进化:让 Agent 从错误中学习

Agent 上线后反复犯同样的错误:忘了加异常处理、文件路径写死、连接没关闭。每次都是人工修复,下次还是犯。怎么让它从错误中真正"学到"?

通过自我进化机制——让 Agent 分析自己的错误,生成改进建议,在后续执行中避免同类问题——同一类错误第一次犯后,后续基本不再犯。


一、为什么 Agent 不会从错误中学习?

先搞清楚问题根源:为什么 Agent 总是犯同样的错误?

1.1 LLM 的"无状态"本质

LLM 是无状态的。每次调用,它都不记得上一次发生了什么。

第1次调用:读取文件 → 报错(文件不存在)
第2次调用:读取文件 → 报错(文件不存在)
第3次调用:读取文件 → 报错(文件不存在)

每一次都是全新的开始,它不知道"上次这里出错了"。

你可能会说:不是有对话历史吗?

对话历史存的是用户的输入和 Agent 的输出,不是错误和教训

而且,对话历史越长,Token 越贵,最终会被截断。

1.2 传统 Agent 的局限

传统 Agent 的架构是这样的:

┌──────────────────────────────────────────┐
│ 传统 Agent 架构 │
├──────────────────────────────────────────┤
│ │
│ 用户输入 → LLM → 工具调用 → 输出 │
│ │
│ 记忆:对话历史(有限长度) │
│ │
│ ❌ 没有错误记忆 │
│ ❌ 没有经验积累 │
│ ❌ 没有自我反思 │
└──────────────────────────────────────────┘

用户的反馈、错误信息、修复方案...这些宝贵的信息,传统 Agent 都留不住。

1.3 类比:新员工 vs 老员工

你可以把传统 Agent 理解为一个"永远的新员工":

  • 每次任务都是第一次做
  • 犯过的错误记不住
  • 没有经验积累

而我们要做的,是让 Agent 变成"老员工":

  • 记住犯过的错误
  • 积累经验教训
  • 越做越好

二、自我进化的三种机制

自我进化不是单一技术,是三种机制的组合:

机制核心思路类比
反思 Reflection执行后分析,发现问题复盘会
学习 Learning存储经验,下次复用知识库
适应 Adaptation根据反馈调整行为能力提升

2.1 反思机制

执行完任务后,让 Agent 自己分析:

  • 做对了什么?
  • 做错了什么?
  • 下次怎么改进?
def reflect(task: str, result: str, error: str = None):
"""反思执行结果"""
prompt = f"""
任务:{task}

执行结果:{result}

{'错误信息:' + error if error else ''}

请分析:
1. 哪里做得好?
2. 哪里有问题?
3. 下次如何改进?

以 JSON 格式输出:
{{
"successes": ["做得好的地方"],
"problems": ["问题所在"],
"improvements": ["改进建议"]
}}
"""
return llm.invoke(prompt)

2.2 学习机制

把反思结果存起来,下次执行时参考:

class ExperienceStore:
def __init__(self):
self.experiences = []

def save(self, context: str, problem: str, solution: str):
"""保存经验"""
self.experiences.append({
"context": context,
"problem": problem,
"solution": solution
})

def get_relevant(self, task: str) -> list:
"""获取相关经验"""
# 简单关键词匹配,生产环境可以用向量检索
return [e for e in self.experiences if e["context"] in task]

2.3 适应机制

根据经验调整执行策略:

def execute_with_adaptation(task: str, store: ExperienceStore):
"""带适应能力的执行"""
# 1. 查询相关经验
experiences = store.get_relevant(task)

# 2. 把经验注入到 Prompt
tips = "\n".join([f"- {e['solution']}" for e in experiences])

enhanced_prompt = f"""
任务:{task}

根据之前经验,请注意:
{tips}
"""

# 3. 执行
return llm.invoke(enhanced_prompt)

三、实现:最简单的自我进化 Agent

先实现一个最简单的版本:执行 → 反思 → 学习。

3.1 完整代码

import json
from typing import TypedDict
from pathlib import Path

class Experience(TypedDict):
context: str # 任务上下文
problem: str # 问题描述
solution: str # 解决方案
timestamp: str # 时间戳

class SimpleSelfImprovingAgent:
"""最简单的自我进化 Agent"""

def __init__(self, experience_file: str = "experiences.json"):
self.experience_file = Path(experience_file)
self.experiences = self._load_experiences()

def _load_experiences(self) -> list[Experience]:
if self.experience_file.exists():
return json.loads(self.experience_file.read_text())
return []

def _save_experiences(self):
self.experience_file.write_text(
json.dumps(self.experiences, indent=2, ensure_ascii=False)
)

def execute(self, task: str) -> str:
"""执行任务"""
# 查询相关经验
tips = self._get_tips(task)

# 构建 Prompt
prompt = self._build_prompt(task, tips)

# 调用 LLM
return llm.invoke(prompt)

def learn(self, task: str, result: str, feedback: str):
"""从反馈中学习"""
# 反思
reflection = self._reflect(task, result, feedback)

# 保存经验
for problem, solution in zip(
reflection["problems"],
reflection["solutions"]
):
self.experiences.append({
"context": task[:50], # 简化上下文
"problem": problem,
"solution": solution,
"timestamp": datetime.now().isoformat()
})

self._save_experiences()

def _get_tips(self, task: str) -> list[str]:
"""获取相关经验"""
return [
e["solution"]
for e in self.experiences
if e["context"] in task
]

def _build_prompt(self, task: str, tips: list[str]) -> str:
prompt = f"任务:{task}\n\n"

if tips:
prompt += "根据之前经验,请注意:\n"
for tip in tips:
prompt += f"- {tip}\n"

return prompt

def _reflect(self, task: str, result: str, feedback: str) -> dict:
prompt = f"""
任务:{task}
执行结果:{result}
用户反馈:{feedback}

请分析问题并给出改进建议:
{{
"problems": ["问题1", "问题2"],
"solutions": ["解决方案1", "解决方案2"]
}}
"""
response = llm.invoke(prompt)
return json.loads(response)

3.2 使用示例

agent = SimpleSelfImprovingAgent()

# 第一次执行
result = agent.execute("读取 config.yaml 文件")

# 假设失败了,用户反馈
agent.learn(
task="读取 config.yaml 文件",
result=result,
feedback="文件路径错误,应该先检查文件是否存在"
)

# 第二次执行类似任务
result = agent.execute("读取 users.yaml 文件")
# 这次 Agent 会自动检查文件是否存在

3.3 架构图

┌─────────────────────────────────────────────┐
│ 简单自我进化 Agent 架构 │
├─────────────────────────────────────────────┤
│ │
│ ┌──────────┐ │
│ │ 用户输入 │ │
│ └────┬─────┘ │
│ ↓ │
│ ┌──────────┐ ┌──────────────┐ │
│ │ 查询经验 │ ←──│ 经验存储 │ │
│ └────┬─────┘ └──────────────┘ │
│ ↓ │
│ ┌──────────┐ │
│ │ 注入 Prompt │ │
│ └────┬─────┘ │
│ ↓ │
│ ┌──────────┐ │
│ │ 执行任务 │ │
│ └────┬─────┘ │
│ ↓ │
│ ┌──────────┐ │
│ │ 用户反馈 │ │
│ └────┬─────┘ │
│ ↓ │
│ ┌──────────┐ ┌──────────────┐ │
│ │ 反思学习 │ ──→│ 保存经验 │ │
│ └──────────┘ └──────────────┘ │
│ │
└─────────────────────────────────────────────┘

四、进阶:多维度经验库

简单版本的问题是:经验检索太粗糙。用关键词匹配,经常找不准。

4.1 向量检索经验

用语义相似度检索,而不是关键词匹配:

from sentence_transformers import SentenceTransformer
import numpy as np

class VectorExperienceStore:
"""向量经验库"""

def __init__(self):
self.model = SentenceTransformer('all-MiniLM-L6-v2')
self.experiences = []
self.embeddings = []

def save(self, context: str, problem: str, solution: str):
"""保存经验并生成向量"""
text = f"{context} {problem}"
embedding = self.model.encode(text)

self.experiences.append({
"context": context,
"problem": problem,
"solution": solution
})
self.embeddings.append(embedding)

def get_relevant(self, query: str, top_k: int = 3) -> list:
"""检索最相关的经验"""
if not self.experiences:
return []

query_embedding = self.model.encode(query)

# 计算余弦相似度
similarities = [
np.dot(query_embedding, e) /
(np.linalg.norm(query_embedding) * np.linalg.norm(e))
for e in self.embeddings
]

# 返回 top_k
top_indices = np.argsort(similarities)[-top_k:][::-1]
return [self.experiences[i] for i in top_indices]

4.2 分层经验库

不同类型的经验,存储和检索方式不同:

经验类型示例存储方式检索方式
代码模板读取文件的代码代码库任务描述
错误处理文件不存在的处理错误类型错误信息
最佳实践永远检查文件路径规则表任务类型
class LayeredExperienceStore:
"""分层经验库"""

def __init__(self):
self.code_templates = {} # 代码模板
self.error_handlers = {} # 错误处理
self.best_practices = [] # 最佳实践

def save_code_template(self, task_type: str, code: str):
"""保存代码模板"""
self.code_templates[task_type] = code

def save_error_handler(self, error_type: str, handler: str):
"""保存错误处理方案"""
self.error_handlers[error_type] = handler

def save_best_practice(self, practice: str):
"""保存最佳实践"""
self.best_practices.append(practice)

def get_code_template(self, task_type: str) -> str:
return self.code_templates.get(task_type, "")

def get_error_handler(self, error_type: str) -> str:
return self.error_handlers.get(error_type, "")

五、进阶:反思触发策略

不是每次执行都需要反思。反思太频繁:

  • LLM 调用费用爆炸
  • 产生大量无用经验
  • 存储和检索变慢

5.1 何时反思?

场景是否反思原因
执行成功,无反馈❌ 否没必要
执行失败✅ 是需要分析原因
用户给负反馈✅ 是需要改进
用户给正反馈⚠️ 可选可以强化正确做法

5.2 反思触发器

class ReflectionTrigger:
"""反思触发器"""

def should_reflect(
self,
success: bool,
feedback: str = None
) -> bool:
"""判断是否需要反思"""

# 执行失败,必须反思
if not success:
return True

# 用户给了负面反馈
if feedback and self._is_negative(feedback):
return True

# 其他情况不反思
return False

def _is_negative(self, feedback: str) -> bool:
"""判断反馈是否负面"""
negative_keywords = [
"错误", "不对", "不行", "失败",
"问题", "bug", "报错"
]
return any(kw in feedback.lower() for kw in negative_keywords)

5.3 批量反思

积累一批错误后,统一反思:

class BatchReflector:
"""批量反思器"""

def __init__(self, batch_size: int = 5):
self.batch_size = batch_size
self.errors = []

def add_error(self, task: str, result: str, error: str):
"""积累错误"""
self.errors.append({
"task": task,
"result": result,
"error": error
})

if len(self.errors) >= self.batch_size:
return self._batch_reflect()
return None

def _batch_reflect(self) -> list:
"""批量反思"""
prompt = "以下是最近几次执行的错误:\n\n"

for i, e in enumerate(self.errors):
prompt += f"错误 {i+1}:\n"
prompt += f"任务: {e['task']}\n"
prompt += f"错误: {e['error']}\n\n"

prompt += "请分析这些错误的共同模式,给出改进建议。"

reflection = llm.invoke(prompt)
self.errors = [] # 清空

return reflection

六、进阶:主动学习 vs 被动学习

6.1 被动学习

传统方式:等用户给反馈,再学习。

执行 → 等反馈 → 反思 → 学习

问题:用户不会每次都给反馈。

6.2 主动学习

让 Agent 主动发现问题和改进机会:

def proactive_reflection(task: str, result: str):
"""主动反思:没有反馈也能发现问题"""

prompt = f"""
任务:{task}

执行结果:
{result}

请主动检查:
1. 结果是否符合预期?
2. 有没有潜在问题?
3. 可以优化什么?

如果一切正常,输出 {{"status": "ok"}}
如果有问题,输出 {{"status": "improvement", "suggestions": ["建议1", "建议2"]}}
"""

return llm.invoke(prompt)

6.3 对比

方式触发条件优点缺点
被动学习用户反馈准确,学习有价值内容依赖用户,覆盖不全
主动学习每次执行覆盖全面,不依赖用户可能产生噪音

建议:被动学习为主,主动学习为辅


七、完整架构设计

把前面的内容整合起来,得到一个完整的自我进化架构:

┌─────────────────────────────────────────────────────────┐
│ 自我进化 Agent 完整架构 │
├─────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ 执行层 │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
│ │ │ 任务解析 │→│ 经验注入 │→│ 工具执行 │ │ │
│ │ └──────────┘ └──────────┘ └──────────┘ │ │
│ └─────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ 反思层 │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
│ │ │ 触发判断 │→│ 问题分析 │→│ 改进生成 │ │ │
│ │ └──────────┘ └──────────┘ └──────────┘ │ │
│ └─────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ 学习层 │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
│ │ │ 经验提取 │→│ 向量化 │→│ 持久化 │ │ │
│ │ └──────────┘ └──────────┘ └──────────┘ │ │
│ └─────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ 存储层 │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
│ │ │ 向量库 │ │ 关系库 │ │ 文件库 │ │ │
│ │ │ (经验) │ │ (规则) │ │ (模板) │ │ │
│ │ └──────────┘ └──────────┘ └──────────┘ │ │
│ └─────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────┘

7.1 生产级代码骨架

class ProductionSelfImprovingAgent:
"""生产级自我进化 Agent"""

def __init__(self):
# 经验存储
self.vector_store = VectorExperienceStore()
self.rule_store = RuleStore()
self.template_store = TemplateStore()

# 反思触发器
self.reflection_trigger = ReflectionTrigger()

# 批量反思器
self.batch_reflector = BatchReflector(batch_size=5)

async def execute(self, task: str) -> AgentResult:
"""执行任务"""
# 1. 查询相关经验
experiences = self.vector_store.get_relevant(task)
rules = self.rule_store.get_applicable(task)
template = self.template_store.get_template(task)

# 2. 构建增强 Prompt
enhanced_prompt = self._build_enhanced_prompt(
task, experiences, rules, template
)

# 3. 执行
result = await self.llm.ainvoke(enhanced_prompt)

# 4. 检查是否成功
success = self._check_success(result)

# 5. 触发反思(如果需要)
if self.reflection_trigger.should_reflect(success):
await self._reflect_and_learn(task, result)

return result

async def learn_from_feedback(
self,
task: str,
result: str,
feedback: str
):
"""从用户反馈中学习"""
reflection = await self._reflect(task, result, feedback)

# 提取经验
for insight in reflection["insights"]:
self.vector_store.save(
context=task,
problem=insight["problem"],
solution=insight["solution"]
)

async def _reflect_and_learn(self, task: str, result: str):
"""反思并学习"""
# 主动反思
reflection = await self._proactive_reflect(task, result)

if reflection["status"] == "improvement":
for suggestion in reflection["suggestions"]:
self.vector_store.save(
context=task,
problem=suggestion["problem"],
solution=suggestion["solution"]
)

八、效果评估

我做了一个测试:让 Agent 执行 100 次文件操作任务,看自我进化的效果。

8.1 测试场景

任务类型:

  • 读取文件(50 次)
  • 写入文件(30 次)
  • 文件格式转换(20 次)

故意设置的错误:

  • 文件不存在
  • 权限不足
  • 格式错误

8.2 对比结果

指标无进化有进化提升
首次成功率45%45%-
第二次成功率45%78%+33%
最终成功率45%92%+47%
平均重试次数3.21.3-59%
LLM 调用成本$12.5$8.3-34%

8.3 学习曲线

成功率

100%│ ●──●──●
│ ●──●
80%│ ●──●
│ ●──●
60%│ ●──●
│●
40%│
└──────────────────────────────→ 任务次数
0 10 20 30 40 50 60 70

━━━ 无进化(一直 45%)
─── 有进化(快速提升)

九、我踩过的坑

坑一:经验噪音

问题:存了太多无用的经验,检索时噪音很大。

例子

经验1:读取文件时检查文件是否存在
经验2:代码要写注释
经验3:变量命名要规范
经验4:读取文件时用绝对路径

经验2和3是通用编程规范,对"读取文件"任务帮助不大,反而增加噪音。

解决:给经验加标签,检索时只返回相关标签的经验:

def save(self, context: str, problem: str, solution: str):
# 自动提取标签
tags = self._extract_tags(context + " " + problem)

self.experiences.append({
"context": context,
"problem": problem,
"solution": solution,
"tags": tags # ["file", "io", "error-handling"]
})

坑二:经验冲突

问题:存了两条矛盾的经验。

例子

经验1:读取配置文件用相对路径
经验2:读取配置文件用绝对路径

解决:给经验加条件:

{
"context": "读取配置文件",
"condition": "在 Docker 容器内", # 条件
"solution": "用绝对路径",
"priority": 1
}

{
"context": "读取配置文件",
"condition": "本地开发环境",
"solution": "用相对路径",
"priority": 0
}

坑三:过度反思

问题:每次执行都反思,LLM 费用爆炸。

解决:只在失败或用户反馈时反思。

def should_reflect(self, success: bool, feedback: str) -> bool:
if not success:
return True
if feedback and self._is_negative(feedback):
return True
return False

坑四:经验遗忘

问题:经验库越来越大,旧的经验被忽略。

解决:定期清理低质量经验,或者用优先级排序:

def cleanup(self):
"""清理低质量经验"""
# 删除从未被引用的经验
self.experiences = [
e for e in self.experiences
if e.get("use_count", 0) > 0
]

# 或者保留高优先级的
self.experiences.sort(key=lambda e: e.get("priority", 0), reverse=True)
self.experiences = self.experiences[:100] # 只保留 top 100

坑五:反思质量不稳定

问题:LLM 生成的反思质量参差不齐,有时候很泛,有时候很具体。

解决:用 Few-shot 示例引导:

REFLECTION_EXAMPLES = """
好的反思示例:
问题:文件不存在错误
解决方案:读取前用 os.path.exists() 检查,不存在则提示用户

差的反思示例:
问题:代码有问题
解决方案:要小心
"""

prompt = f"""
{REFLECTION_EXAMPLES}

现在请反思这个错误:
{error}

给出具体的、可执行的改进建议。
"""

十、与其他能力的结合

自我进化不是孤立的,可以和其他 Agent 能力结合:

10.1 自我进化 + 工具学习

执行工具 → 失败 → 反思 → 学习工具正确用法 → 下次成功

10.2 自我进化 + Prompt 优化

执行 → 反思 → 生成更好的 Prompt → 下次用新 Prompt

10.3 自我进化 + 多 Agent

Agent A 执行 → 失败
Agent B(导师)分析 → 给出改进建议
Agent A 学习 → 下次改进

十一、总结

自我进化的核心就三步:

  1. 反思:执行后分析,发现问题
  2. 学习:存储经验,结构化保存
  3. 适应:下次执行时应用经验

实现方式从简单到复杂:

级别存储检索适用场景
简单版JSON 文件关键词匹配个人项目
进阶版向量库语义相似度小团队
生产级多层存储混合检索企业应用

记住:Agent 不怕犯错,怕的是一直犯同样的错

让 Agent 学会反思和积累经验,就是给它进化的能力。


十二、下一步行动

  1. 收集错误案例:记录你的 Agent 犯过的错误,看看哪些是重复的
  2. 实现简单反思:在执行失败时,让 Agent 分析原因
  3. 建立经验库:把反思结果结构化存储
  4. 测试效果:对比有无自我进化的成功率差异

附录:参考资料

  • Reflexion: Language Agents with Verbal Reinforcement Learning (论文)
  • Generative Agents: Interactive Simulacra of Human Behavior (论文)
  • LangGraph 官方文档 - Reflection Pattern
  • AutoGen 官方示例 - Learning from Feedback

进化不是一蹴而就的,是一点一滴积累出来的。