写 Agent 的人都会经历这个时刻:Agent 调了一个工具,返回错误。然后呢?
如果 Agent 看到错误后能理解发生了什么、换个方式重试、最终成功——这就是能自我修复的 Agent。如果它看到错误后直接放弃或瞎编一个答案——那就是不可靠的 Agent。
这篇文章讲怎么让你的 Agent 从脆弱变鲁棒。
| 错误类型 | 例子 | 可恢复? |
|---|---|---|
| 参数错误 | 传了错误的文件名、格式不对 | ✅ 通常可以 |
| 工具调用顺序错误 | 没先创建目录就写文件 | ✅ 修复前置步骤 |
| 外部服务异常 | API 超时、网络断开 | ⚠️ 重试或降级 |
| 逻辑推理错误 | 误解任务意图、选了错的工具 | ⚠️ 需要反思循环 |
| 权限/资源不足 | 文件无写权限、磁盘满 | ❌ 需要人工介入 |
错误恢复的第一步不是 Agent 的代码,而是工具的错误消息质量。模型只能根据你给它的信息做决策——给它垃圾错误信息,它就做垃圾决策。
# ❌ 无用的错误
def read_file(path):
try:
return open(path).read()
except:
return "Error" # 模型:什么错误?怎么办?
# ✅ 有用的错误
def read_file(path):
try:
return open(path).read()
except FileNotFoundError:
return json.dumps({
"success": False,
"error": f"文件不存在: {path}",
"suggestion": "尝试列出目录内容确认文件路径",
"parent_dir": str(Path(path).parent)
})
except PermissionError:
return json.dumps({
"success": False,
"error": f"无权限读取: {path}",
"suggestion": "检查文件权限或尝试其他路径"
})
对于网络超时、API 限流这类瞬时错误,不需要 Agent 去「思考」——直接重试就对了。
import time, random
def retry_with_backoff(fn, max_retries=3, base_delay=1):
"""指数退避重试:1s → 2s → 4s。"""
for attempt in range(max_retries):
try:
return fn()
except (TimeoutError, ConnectionError) as e:
if attempt == max_retries - 1:
raise # 最后一次,不再重试
delay = base_delay * (2 ** attempt) + random.uniform(0, 1)
time.sleep(delay)
return None
把这个包装在所有可能瞬态失败的工具外层:
def search_web_robust(query):
return retry_with_backoff(lambda: search_web(query))
def run_python_robust(code):
return retry_with_backoff(lambda: run_python(code), max_retries=5)
重试搞不定的错误——参数错了、路径不对、工具选错了——需要 Agent 理解错误并修正自己的行为。这就是自愈循环。
关键改造:把错误信息结构化地喂回给模型,让模型自己决定下一步。
def run_agent_with_recovery(user_input: str, max_turns: int = 15):
messages = [{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": user_input}]
consecutive_errors = 0
for turn in range(max_turns):
response = client.chat.completions.create(
model="gpt-4o", messages=messages, tools=TOOLS
)
msg = response.choices[0].message
if not msg.tool_calls:
return msg.content
for tool_call in msg.tool_calls:
fn_name = tool_call.function.name
fn_args = json.loads(tool_call.function.arguments)
result = execute_tool(fn_name, fn_args)
# 解析错误
error_info = parse_error(result)
if error_info:
consecutive_errors += 1
# 把结构化错误喂给模型
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": json.dumps({
"success": False,
"tool": fn_name,
"error": error_info["message"],
"suggestion": error_info["suggestion"],
"attempts_left": 3 - consecutive_errors
})
})
# 连续失败太多 → 终止
if consecutive_errors >= 3:
return f"连续 {consecutive_errors} 次失败,请人工检查。最后错误: {error_info['message']}"
else:
consecutive_errors = 0 # 成功,重置计数器
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": result
})
messages.append(msg)
return "达到最大轮次,任务未完成。"
光有机制不够,模型需要知道「遇到错误该怎么办」。在 system 消息里加入明确的错误处理指引:
SYSTEM_PROMPT = """你是用户的 AI 助手。你可以使用工具完成任务。
## 错误处理规则
1. 工具返回 "success": false 时,不要放弃。
2. 根据 error 字段理解发生了什么。
3. 根据 suggestion 字段的提示调整你的操作。
4. 如果 suggestion 建议换个路径,就列出目录找到正确路径。
5. 如果 suggestion 建议重试,换个参数再试一次。
6. 连续 3 次失败后,如实告诉用户发生了什么,不要编造结果。
## 工具使用原则
- 先用 ls/list_dir 确认文件和目录存在,再操作
- 网络操作可能超时,准备好备用方案
- 不确定参数格式时,先查文档或帮助信息"""
有些错误不是工具调用层面的——是逻辑层面的。Agent 完成了任务但结果不对。
反思机制让 Agent 在输出最终答案之前,再检查一遍自己的工作:
def reflect_and_refine(task, result, tools_used):
"""让模型反思结果质量。"""
reflection_prompt = f"""你刚完成了以下任务:
任务: {task}
使用工具: {tools_used}
得到结果: {result}
请检查:
1. 结果是否完整回答了任务?
2. 有没有遗漏的子任务?
3. 数据是否准确(有没有用不相关的数据)?
4. 有没有更好的方式?
如果没问题,回复 "OK"。
如果有问题,说明问题并修正。"""
check = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": reflection_prompt}]
).choices[0].message.content
if "OK" in check[:50]:
return result
return check # 用反思后的修正版本
| 防线 | 处理什么 | 成本 | 效果 |
|---|---|---|---|
| ① 好错误消息 | 所有错误 | 零 | ✅ 基础 |
| ② 指数退避 | 瞬时故障 | 延迟 | ✅ 自动修复 |
| ③ 自愈循环 | 参数/逻辑错误 | 额外 token | ✅ 自适应 |
| ④ 反思 | 结果质量 | 翻倍 token | ✅ 质量保证 |
不需要一次性上齐。从 ① 开始——把工具的错误消息写好,你的 Agent 就比 90% 的实现更可靠了。
📖 下一篇:多 Agent 编排 — 让多个 Agent 协作完成复杂任务