当 Agent 跑了 120 步后崩溃:航空事故调查员如何教我们抓到那一步致命错
想象你是一名航空事故调查员。一架航班坠毁,黑匣子记录了 120 个操作步骤。你逐帧查看,发现飞行员在第 18 步按错了一个按钮,第 47 步读错了高度表,第 73 步和塔台沟通时漏了一个词,第 95 步忘了放下起落架,第 112 步拉杆太猛。
一架飞机坠毁了,黑匣子里有 120 条记录
想象你是一名航空事故调查员。一架航班坠毁,黑匣子记录了 120 个操作步骤。你逐帧查看,发现飞行员在第 18 步按错了一个按钮,第 47 步读错了高度表,第 73 步和塔台沟通时漏了一个词,第 95 步忘了放下起落架,第 112 步拉杆太猛。
五个错误,飞机只坠毁了一次。哪个才是真凶?
你不能把五个都列为"原因"——那等于没有答案。你必须找到那个最早的决定性错误:它引发了后续连锁反应,即使中间步骤看起来"修正"了,最终仍然导致了坠毁。
这是 LLM Agent 调试面临的同一个困境。清华大学 KEG 实验室和腾讯混元团队 2026 年 8 月发布的论文 TrajDebug 给出了一个系统化答案:追踪错误的整个生命周期,而不是只看错误本身。
Agent 的崩溃现场:平均 7.62 个错误,只有 1 个是致命的
研究者先做了一个让人坐直的先导实验。他们收集了 50 条失败轨迹(来自 τ²-Bench 和 SWE-Bench Pro 两个主流 Agent 评测基准),人工标注每一步是否出错。结果:
- 50 条失败轨迹共 381 个局部错误,平均每条 7.62 个
- 每条轨迹只有 1 个关键错误(critical error)真正导致了最终失败
- 剩下的 331 个非关键错误里:
- 205 个(61.9%)后来被自己修复了
- 104 个(31.4%)一直存在但没导致失败
- 22 个(6.6%)处于休眠状态——既没修复也没造成影响
更麻烦的是,检测准确率随轨迹长度递减。研究者评估了 7 个主流大模型(包括 GPT、Claude、DeepSeek 等),在短轨迹上还能勉强找到关键错误,但轨迹一长,准确率断崖式下跌。原因很简单:判断第 47 步是否出错,可能需要回看第 3 步的指令、第 28 步的观察、第 35 步自己的推理——证据散落在整个上下文里,模型读到后面就忘了前面。
TrajDebug 的三段式调查:从"找错误"到"追生命周期"
TrajDebug 的核心洞察是:错误不是孤立事件,它有生命周期。一个错误从触发、到发展、到被修复或持续影响,是一个完整过程。只看错误本身等于只看案发现场,不看后续发展。
框架分三阶段,每阶段都产出可审计的证据:
阶段一:错误触发检测——多粒度历史压缩
长轨迹的挑战是:判断第 47 步是否出错,需要同时看局部细节(这步的动作)和全局上下文(之前的指令和观察)。TrajDebug 构建了三个粒度的历史视图:
- 高粒度:保留最近几步的完整细节(看当前动作的上下文)
- 中粒度:中等长度的摘要(看近期发展脉络)
- 低粒度:整条轨迹的高度压缩(看全局走向)
在三个视图上,TrajDebug 检测"错误承诺"(wrong commitment)——Agent 在推理、规划、行动、观察或验证阶段做出的与某个参考冲突的判断。参考分四类:
- 任务冲突:与原始任务指令矛盾
- 历史冲突:与自己之前的推理或行动矛盾
- 步骤内冲突:同一步内前后矛盾
- 环境异常:与环境反馈矛盾
阶段二:错误状态分类——四种命运
找到错误触发后,TrajDebug 不急着下结论。它把同一对象相关的触发聚合成"错误实例",然后追踪每个实例的后续发展,分到四个状态:
- Clean Resolution(干净修复):错误被纠正,没留下任何影响
- Costly Resolution(代价修复):错误被纠正了,但消耗了资源或绕了远路
- Manifest Active(显性持续):错误一直存在,且在最终失败中留下痕迹
- Latent Active(隐性持续):错误一直存在,但没在最终失败中直接表现
阶段三:候选集引导的因果归因
最后一步,TrajDebug 把所有"Manifest Active"和"Costly Resolution"状态的错误实例交给 LLM 做最终归因。但关键是:LLM 不再面对整条轨迹,只面对一个精筛过的候选集。
这把任务从"在 120 步里找关键错误"降维成"在 3-5 个候选里选最关键的一个"。候选集已经附带完整证据链(触发位置、违反的参考、后续发展),LLM 只需要做因果判断。
TrajErrBench:486 份"事故档案"
为了让同行能复现和比较,研究团队构建了 TrajErrBench——第一个大规模人工标注的 Agent 失败轨迹基准:
- 486 条失败轨迹:400 条来自 τ²-Bench(客服工具使用场景),86 条来自 SWE-Bench Pro(软件工程场景)
- 平均长度:τ²-Bench 29.3 步,SWE-Bench Pro 119.7 步
- 标注内容:每条轨迹的所有局部错误、错误类型、执行阶段、是否关键
| 维度 | τ²-Bench | SWE-Bench Pro |
|---|---|---|
| 任务冲突 | 52.4% | 73.4% |
| 历史冲突 | 46.3% | 24.1% |
| 推理阶段失败 | 60.7% | 57.1% |
实验结果:诊断即生产力
TrajDebug 在 TrajErrBench 上超越了所有基线方法,尤其在长轨迹上优势更明显。但更有说服力的是两个应用实验:
应用一:诊断引导重跑,+10.80% 成功率提升 用 TrajDebug 诊断失败轨迹,把"关键错误在哪一步、违反了什么、为什么导致失败"作为反馈喂给 Agent,让它重新执行同一任务。平均成功率提升 10.80 个百分点。
应用二:失败记忆迁移,+5.70% 成功率提升 把少量历史失败的诊断聚合为"失败记忆库"(failure memory),迁移到完全没见过的任务上。成功率提升 5.70 个百分点。
第二个结果尤其重要。它证明 TrajDebug 的诊断不只是"事后诸葛亮",而是可迁移的结构化知识。失败模式可以抽象出来,变成 Agent 的免疫力。
工程洞察:错误有生命周期,调试需要时间维度
TrajDebug 给 Agent 工程师带来三个实操启示:
1. 不要只看最终失败点,要追错误源头 Agent 在第 95 步失败,根因可能在第 18 步。直接修第 95 步是治标不治本。TrajDebug 的"错误生命周期"视角让你看到错误的传播链。
2. 不是所有错误都需要修 61.9% 的局部错误被 Agent 自己修复了。如果你花精力修每一个错误,你在浪费 60% 的工程量。先分类,再决定修哪些——这是 TrajDebug 四状态分类的价值。
3. 失败轨迹是金矿,不是垃圾 大多数团队把失败轨迹扔掉。TrajDebug 证明:486 条失败轨迹可以训练出可迁移的失败记忆,让新任务成功率提升 5.70%。失败是结构化知识来源,前提是你有工具把它诊断清楚。
概念连接:颗粒度对齐与"换层面解决问题"
TrajDebug 契合两个我一直在追踪的跨论文共识:
"颗粒度同构"原理:优化颗粒度应该和被优化对象的颗粒度一致。Agent 的失败不是"整条轨迹失败",是"某个错误实例在生命周期中某个状态导致失败"。TrajDebug 把调试颗粒度从"轨迹级"或"步级"细化到"错误实例级",和 Heddle、CodeRescue 把决策颗粒度从"单次调用"升级到"轨迹/恢复动作"是同一个原则。
"换层面解决问题":传统方法让 LLM 在整条轨迹上找关键错误,TrajDebug 换了个层面——先做错误生命周期追踪,把 LLM 的任务从"多步推理"降级为"在候选集里做因果判断"。这和 Euclid-MCP 把推理外包给 Prolog、章鱼用 RNA 编辑绕过 DNA 重写是同一个策略:承认模型在某些任务上不可靠,换一个层面绕过去。
代码与数据
- 论文:https://arxiv.org/abs/2608.06346
- HTML 全文:https://arxiv.org/html/2608.06346v1
- 代码仓库:https://github.com/THU-KEG/TrajDebug(代码和数据在内审中,即将开源)
- 作者团队:清华大学 KEG 实验室 + 腾讯混元
个人思考:从"找 bug"到"理解 bug 的一生"
最让我触动的是 TrajDebug 对"错误"概念的重新定义。我们习惯了把错误当作离散事件——"第 47 步出错了"。但 TrajDebug 告诉我们:错误是一个有生命周期的实体,它有诞生(触发)、有发展(状态变化)、有结局(修复或持续)。
这和医学的演进惊人相似。19 世纪的医生把疾病当作"某个器官坏了",20 世纪转向"疾病是一个过程,有潜伏期、发作期、恢复期"。TrajDebug 把 Agent 调试从"找坏步骤"推向"理解错误的发展史"。
更深一层:TrajDebug 的"失败记忆迁移"实验暗示了一个可能性——Agent 的经验不只是"成功案例库",还应该有"失败模式库"。人类专家之所以厉害,不只因为他见过很多成功,更因为他踩过很多坑。TrajDebug 给 Agent 踩坑经验提供了一种结构化编码方式。
当 Agent 系统越来越复杂、轨迹越来越长,"如何从失败中学习"会比"如何成功"更重要。TrajDebug 做了一个扎实的起点:先得能诊断,才能谈学习。