AI Agent 错误恢复与自我纠错 — 让 Agent 在犯错后自己修好

写 Agent 的人都会经历这个时刻: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": "检查文件权限或尝试其他路径"
        })
🎯 好错误消息的三要素:① 具体发生了什么 ② 为什么发生 ③ 建议的下一步行动。缺了哪条,Agent 的自愈能力就降一档。

第二道防线:指数退避重试

对于网络超时、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 确认文件和目录存在,再操作
- 网络操作可能超时,准备好备用方案
- 不确定参数格式时,先查文档或帮助信息"""

第四道防线:反思(Reflection)

有些错误不是工具调用层面的——是逻辑层面的。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 协作完成复杂任务