一个旅行预订助手收到用户指令:“帮我订一张明天从北京到上海的机票,靠窗座位,再用我的积分升舱。” Agent 解析意图后,需要依次调用航班查询、座位选择、积分查询和升舱接口。第一个 API 返回 503 Service Unavailable,第二个 API 要求 seatPreference 参数必须是枚举值“window”而非“靠窗”,第三个 API 因账户令牌过期返回 401,第四个 API 在 30 秒后超时。
直接让 LLM 看到这些原始错误码并期望它做出正确决策,风险很高。模型可能忽略错误继续执行,也可能陷入无限重试循环,或者给出一个看似合理但实际无效的恢复动作。工具调用代理的错误恢复不是简单的 try-catch,而是一套需要精心设计的决策流程。
故障模式:旅行预订中的三类典型错误
在旅行预订场景中,工具调用失败可以归纳为三类:瞬时故障、逻辑错误和策略冲突。
瞬时故障包括网络超时、服务暂时不可用(503)和限流(429)。这类错误通常可以通过重试解决,但重试策略必须考虑幂等性。航班查询是读操作,重试是安全的;但升舱接口如果因超时重试,可能导致重复扣款。
逻辑错误源于参数不合法或模型生成的调用与 API 规范不匹配。当模型输出“seatPreference: 靠窗”而 API 要求“window”时,这是一个可修复的参数错误。更隐蔽的是语义错误:模型可能调用“查询北京到上海航班”但实际需要的是“北京首都机场到上海虹桥机场”,API 返回空列表,模型却误以为没有航班。
策略冲突发生在多步骤任务中,前一步的结果使后续步骤无法执行。例如积分查询返回余额不足,升舱操作无法继续。这不是 API 调用失败,而是任务规划层面的失败,需要 Agent 重新规划或向用户确认。
ReAct 的自我修正:推理与行动的交替循环
ReAct(Yao et al., 2022)提出了一种让 LLM 交替生成推理轨迹和行动的方法。在工具调用失败时,模型不是直接重试,而是先“思考”失败原因,再决定下一步动作。
在旅行预订场景中,当航班查询返回 503 时,ReAct 风格的推理轨迹可能是:“航班服务暂时不可用,可能是瞬时故障。我应该等待 2 秒后重试一次。如果仍然失败,则尝试备用航班查询接口。”模型将这段推理作为上下文,然后生成新的 API 调用。这种显式推理使错误恢复过程可解释,也更容易调试。
但 ReAct 的自我修正能力受限于模型的推理能力和上下文窗口。如果模型在推理中错误地将 401 解释为“权限不足,需要用户重新登录”,而实际原因是令牌过期,它可能生成无效的恢复动作。更严重的是,当连续多次失败后,推理轨迹可能变得混乱,模型开始产生幻觉,比如虚构一个成功的 API 响应。
工程实现中,我们通常为 ReAct 设置最大推理-行动循环次数(例如 5 次),并监控连续失败次数。当循环内连续 2 次同一工具调用失败时,强制切换至回退策略,避免模型在错误路径上浪费资源。
Toolformer 的过滤机制:在生成时避免错误调用
Toolformer(Schick et al., 2023)采用不同的思路:模型在自监督训练中学习何时以及如何调用工具,并在生成过程中插入特殊的 API 调用标记。它的核心机制是在生成每个 token 时,评估候选 API 调用的有用性,只保留那些能降低下一个 token 预测损失的调用。
这种过滤机制天然地避免了部分错误。如果模型认为调用航班查询 API 对预测下一个 token 没有帮助(例如因为上下文已经包含足够信息),它就不会生成调用。在旅行预订中,这可以减少不必要的 API 请求,从而降低失败概率。
然而,Toolformer 的过滤是在训练时通过损失函数隐式学习的,它无法处理运行时的新错误模式。当 API 规范更新后(例如座位偏好参数从“window”改为“windowSeat”),模型可能仍然生成旧格式的调用,直到重新训练。此外,Toolformer 的过滤是针对单个 API 调用的,缺乏多步任务的整体错误恢复能力。如果航班查询成功但积分查询失败,模型不会自动回退到替代方案,因为它没有显式的重规划机制。
基于规则的恢复:确定性策略的工程价值
在实际系统中,完全依赖模型推理进行错误恢复往往不够可靠。基于规则的恢复策略提供确定性的兜底行为,尤其适合处理明确的错误码和参数校验失败。
一个典型的规则引擎可以这样设计:
- 对于 429 限流错误,使用指数退避重试,最大重试 3 次,初始间隔 1 秒。
- 对于 400 参数错误,提取 API 返回的错误详情,尝试用规则修正参数(例如将“靠窗”映射为“window”),修正后重试一次。
- 对于 401/403 认证错误,立即暂停任务,触发人工介入。
- 对于 5xx 服务端错误,重试 2 次后切换至备用服务(如果有),否则回退到人工。
规则的优势是响应时间可预测,不会出现模型推理的延迟波动。在旅行预订这种对延迟敏感的场景,快速失败并回退往往比等待模型反复推理更可取。
但规则无法处理语义模糊的错误。例如 API 返回“no flights found”,规则无法判断是日期错误、机场代码错误还是真的售罄。这时需要将上下文交给模型推理,或者升级到人工。
混合恢复架构:将推理、过滤与规则组合
工程上,我们通常组合多种策略。下图展示了一个旅行预订 Agent 的错误恢复流程,它结合了规则前置过滤、ReAct 推理循环和 Toolformer 风格的调用过滤。
flowchart TD
A[用户指令] --> B[LLM 生成初始计划]
B --> C{Toolformer 过滤}
C -->|有用| D[执行 API 调用]
C -->|无用| E[跳过调用]
D --> F{调用成功?}
F -->|是| G[记录结果]
F -->|否| H{规则引擎匹配?}
H -->|匹配| I[执行规则恢复]
H -->|不匹配| J[ReAct 推理循环]
I --> K{恢复成功?}
K -->|是| G
K -->|否| J
J --> L{循环次数 < 5?}
L -->|是| M[生成新动作]
L -->|否| N[人工介入]
M --> C
G --> O{任务完成?}
O -->|是| P[返回结果]
O -->|否| B
流程开始于 LLM 生成初始计划,然后 Toolformer 风格的过滤模块评估每个 API 调用的必要性,跳过冗余调用。执行后如果失败,规则引擎首先尝试匹配已知错误码,进行确定性恢复。规则无法处理时,进入 ReAct 循环,模型推理失败原因并生成新动作。循环有最大次数限制,防止无限重试。当所有自动恢复手段耗尽时,任务升级到人工。
重试策略的工程细节:次数、退避与幂等性
重试是最基本的恢复手段,但实现不当会加剧系统负载。在旅行预订系统中,我们为不同 API 设置差异化的重试策略:
| API 类型 | 最大重试次数 | 退避策略 | 幂等性保证 | 超时时间 |
|---|---|---|---|---|
| 航班查询 | 3 | 固定间隔 1s | 天然幂等 | 5s |
| 座位选择 | 1 | 无 | 需幂等键 | 3s |
| 积分查询 | 2 | 指数退避 1s,2s | 天然幂等 | 4s |
| 升舱操作 | 0(直接人工) | 无 | 需事务协调 | 10s |
读操作(查询)可以安全重试,写操作(升舱)必须谨慎。升舱接口如果超时,客户端不知道服务端是否已执行,重试可能导致重复升舱扣款。因此我们选择不自动重试,而是立即转人工确认。
指数退避是处理限流的常用策略,但需要设置最大退避时间,避免等待过长。工程上,我们还会在重试时添加随机抖动(jitter),防止多个客户端同时重试造成惊群效应。
回退策略:从降级到人工的平滑过渡
当重试耗尽或规则无法恢复时,系统需要回退。回退策略分为三个层次:功能降级、替代服务和人工介入。
功能降级意味着放弃非关键需求。如果座位选择 API 持续失败,Agent 可以跳过选座,仅完成订票,并告知用户:“已预订航班,但自动选座失败,请稍后手动选择。”这种降级需要任务规划器能够识别哪些步骤是可选的。
替代服务是预先配置的备用 API。例如主航班查询服务使用供应商 A,备用服务使用供应商 B。切换时需要注意数据一致性:供应商 B 的航班号、价格可能不同,Agent 需要重新确认。
人工介入是最后的保障。触发条件包括:认证失败、支付异常、连续 3 次同一工具失败、模型推理循环达到上限。人工介入不是简单地将整个对话转给客服,而是将结构化的任务状态、已执行步骤、失败上下文打包,让客服快速理解问题并决策。
可观测性与故障定位
没有足够的可观测数据,错误恢复策略的调试如同盲人摸象。我们需要记录每次工具调用的完整生命周期:请求参数、响应状态码、耗时、重试次数、模型推理轨迹和最终恢复动作。
关键指标包括:
- 工具调用成功率(按 API 和错误类型分组)
- 自动恢复成功率(规则恢复 vs. 模型恢复)
- 人工介入率
- 平均恢复延迟
当人工介入率突然上升时,可能意味着某个 API 发生了未预料的变更,或者模型推理质量下降。通过分析模型推理轨迹,可以发现模型是否在错误恢复中产生了幻觉,例如虚构了不存在的 API 参数。
未解决的问题与工程权衡
当前的错误恢复策略仍然面临几个挑战。首先,模型推理的延迟不可预测,在实时系统中,我们可能不得不缩短推理循环,牺牲恢复质量换取响应速度。其次,Toolformer 风格的过滤需要训练数据,对于频繁更新的 API,模型可能滞后。最后,人工介入的成本很高,如何利用失败数据持续微调模型,逐步降低人工介入率,是一个长期工程问题。
在旅行预订这个具体场景中,我们倾向于保守策略:写操作不自动重试,认证错误立即人工,模型推理仅用于语义模糊的错误。这种选择牺牲了部分自动化率,但避免了资金风险。每个团队都需要根据自己的业务容忍度,调整规则引擎的阈值和重试次数。
错误恢复不是要让 Agent 变得完美无缺,而是要在自动化和可靠性之间找到平衡点。记录每一次失败,分析每一次恢复决策,才能逐步构建出值得信赖的工具调用代理。