用追踪与回放定位 Agent 错误
文章以虚构邮件助手为例,介绍通过结构化日志、执行追踪、回放和根因分析定位 Agent 故障。由于采样、工具调用顺序和检索噪声会影响结果,重新运行同一输入未必能够复现错误。
AI 深度解读
Agent 最棘手的故障,往往是流程全部成功,答案却错了:工具没有报错,模型回复流畅,用户拿到的退款状态却是编出来的。原文围绕虚构邮件助手 Mailmind,给出一条排查路径:记录完整执行轨迹,用回放复现故障,再找到最早出错的环节。
它最有用的提醒是:重新跑一次,不等于复现;保存报错日志,也不足以解释错误答案。对正在接入工具调用、检索和多 Agent 协作的开发者,这套方法能把「模型怎么又胡说了」变成可以定位的问题。
没有异常,为什么也要算故障
Mailmind 收到问题:订单 #4521 的退款到账了吗?订单数据库返回 pending,助手却回复:退款 $47.23 已处理。查询成功、生成成功、流水线完成,但金额和完成状态都没有依据。
Agent 的运行成功率,不能代替答案正确率。
原文把故障分成四类,作用是缩小排查范围:
- 推理故障:信息正确,结论错误。例如拿到下午 3 点的邀请,却回复下午 2 点见。
- 工具故障:工具返回空数据、坏数据或格式错误。例如鉴权过期后返回空 JSON,助手误以为没有会议。
- 记忆故障:检索拿到旧退款政策,或者运行时裁剪掉了订单历史。
- 编排故障:任务分错 Agent、步骤间状态丢失,或者流水线一直等待没有返回的任务。
这些类别会叠加。工具先悄悄失败,模型再根据空结果编答案,最后看上去像纯粹的幻觉。定位时要找最先倒下的那块骨牌。
也别把模型写出的推理解释当作定案证据。原文引用 Turpin 等人在 2023 年的研究,指出思维链解释可能系统性地偏离真正影响预测的因素;同时提到 Anthropic 的 thinking 内容可能只是摘要,并非原始思维链。它能提供线索,确认原因仍需改变一个输入,再观察结果。
Trace 要记录模型当时真正看到了什么
普通日志记录一个个事件,Trace 则通过 Span 把步骤、耗时和因果关系串起来。Span 可以理解成某一步操作的记录单:谁调用了它,输入是什么,返回了什么,花了多久。
对 Mailmind,只记「订单查询成功」不够。需要保留订单 #4521 返回的 pending、检索到的退款政策 v2.3、该步组装后的 Prompt,以及最终草稿。这样才能判断:是数据先错了,还是正确数据进入模型后被错误解释。
记录范围还包括模型调用、工具输入输出、检索片段、Agent 交接,以及护栏触发和评分。检索分数也可以作为自定义属性保存。
原文建议使用 OpenTelemetry 的 GenAI Semantic Conventions,其中包含 Agent 运行的 invoke_agent 和工具调用的 execute_tool。按原文描述,截至 2026 年 10 月,这些约定仍标记为 Development,接入时要考虑后续变化。LangSmith、Langfuse、Arize Phoenix,以及 Datadog 的 Agent Observability,都是文中列出的查看轨迹的选择;后者原名为 LLM Observability。
存储策略也不能只留失败请求。退款错误可能等用户投诉才被发现,写日志时根本不知道它失败了。作者建议所有运行先保留完整轨迹,例如保留 14 天;高风险操作、护栏触发、低置信度和用户投诉对应的运行长期保存,其余再抽样。无需保存每个 token 的概率,但应保留回放所需的数据。
回放复现历史,修复验证必须重新生成
同一个输入连续运行 20 次,可以估计故障出现频率,却未必能重现昨天那次错误。采样、异步工具顺序和检索结果都可能变化。原文强调,提供方并不保证 temperature 0 或指定 seed 后输出完全一致。
回放采用另一条路:保存各步实际生成的文本、缓存的工具响应、检索结果和完整输入状态,再用记录替代现场调用。工具不重新执行,模型历史输出也不重新生成。
纯回放能复现旧错误,不能证明新修复有效。
验证修复时,要在相关步骤切回实时生成;否则只是再次播放旧答案。开发阶段的单步调试进一步允许暂停、检查状态,并修改 Prompt 或工具响应后继续运行,用来验证「如果检索拿到了正确政策,会发生什么」。
原文把排查过程整理成以下顺序,解决的是发现错答后该先检查哪里的操作问题:
graph TD
A[Reproduce using trace or replay]
B[Isolate the failing component]
C[Inspect the prompt at that step]
D[Identify root cause category]
E[Fix and verify with replay]
F["Write postmortem, add to golden set"]
A --> B --> C --> D --> E --> F
这里要特别看 E:结合正文,它要求修复组件参与实时执行。随后还要跑完整评估集,把确切输入和预期输出加入黄金测试集(golden set),并留下简短复盘。
轨迹中也有一些适合直接识别的故障特征:同一日历工具换着日期调用 15 次,是循环信号;订单回复混入另一封邮件的内容,要检查会话隔离;长线程中的信息消失,要检查运行时裁剪,原文提醒多数 API 会拒绝超长请求,裁剪通常发生在应用代码里。错误退款金额即使拿到 0.97 的置信度,也仍需独立评分验证。
多 Agent 变慢同样要看耗时,而非只看数量。文末设问中,原来的订单、日历、退款政策三个 worker 加入第四个附件分析 worker 后,耗时变成 3 倍。作者要求检查并行分发是否意外串行,以及新 worker 是否自身很慢;附件结果缺失则另查路由、执行和返回内容,并增加「有附件就必须有处理记录」的覆盖检查。
我的判断
我赞同把排查重点放在可观察的输入、输出和状态上。它比反复修改系统 Prompt 更容易收敛:工具没拿到数据,就先修工具;检索拿错版本,就先修检索。
但原文是方法说明,Mailmind 也是虚构案例,没有提供真实团队采用前后的定位耗时、存储成本或故障下降数据。因此,「回放是调试基石」是有理由的工程主张,不能当成经过对照实验验证的收益承诺。
它对完整回放的描述也有实现前提。除了缓存响应,如果异步事件顺序、路由状态或运行时代码发生变化,仅保存模型文本未必足以保证同一路径。原文强调保存完整状态,但没有给出具体实现。
另外,先出现偏差的位置,不一定就是真正根因。订单状态正确、草稿错误,确实应检查生成步骤,但还要看同一 Prompt 是否混入旧政策、冲突指令或其他线程。要求引用、增加独立评分有帮助,也不能自动保证答案正确。
能拿来做什么
- 给 Node Agent 的模型调用、工具调用和检索步骤关联同一条 Trace,保存实际组装后的 Prompt、响应和耗时,让一次用户反馈能对应到具体运行。
- 把工具的空结果与执行失败明确区分,加入返回结构校验、超时和必要重试,避免模型把鉴权失败解释成「没有数据」。
- 先围绕一条已知错答建立回放,确认能重现后,仅让修复步骤实时执行,再跑完整评估集,并将案例加入 golden set。
- 为反复调用同一工具、会话内容串线和附件处理缺失设置检查,用调用上限、上下文隔离和覆盖记录提供明确的故障信号。