
1. 从一次线上事故说起Agent 失败为什么这么难查凌晨两点被告警叫醒某个跑在客服系统里的 Agent 连续返回空结果用户侧看到的是抱歉我暂时无法处理。翻日志模型调用成功、工具调用成功、返回码 200链路每一环看起来都绿的但最终答案就是错的。这种场景做 Agent 的人应该都不陌生——Agent 失败最麻烦的地方不是它挂了而是它没挂但结果不对。传统后端服务的失败是显式的抛异常、超时、5xx堆栈一拉就知道哪行代码出问题。但 Agent 是一个由 LLM 驱动的多步决策系统它的失败藏在语义层可能是规划阶段选错了工具可能是检索阶段召回了一堆无关文档可能是工具返回的 JSON 被模型误读也可能是多轮对话里上下文被截断导致它忘了用户前面说过什么。你拿到的只是一个错误的最终输出中间发生了什么全靠猜。这就是诊断与归因要解决的问题。所谓诊断Diagnosis是判断这次 Agent 执行到底哪里出了问题所谓归因Attribution是把最终的错误结果追溯到具体的步骤、具体的组件、甚至具体的 token 上。这两件事合起来才构成一条完整的可观测链路。我最近系统梳理了这个方向上的几篇代表性工作包括ReAG、DuoTrace、EDGE这几条思路它们各自解决链路中的一段拼起来刚好覆盖Agent 失败了怎么办的完整流程。这篇就把这条链路拆开讲清楚每一步在做什么、为什么这么设计、实际落地时怎么抄、以及我踩过的坑。先说清楚适合谁看如果你正在做 Agent 开发已经被结果不对但查不出来折磨过或者正准备给 Agent 加监控和评测体系这篇会对你有直接帮助。如果你还在纠结 Agent 和 LLM 的区别、Agent 框架怎么选建议先把基础跑通再回来看因为诊断的前提是你已经有一个能跑起来的 Agent。2. 先搞清楚 Agent 失败到底分几类在讲论文之前得先把失败这件事本身分类。不然你拿着一堆 trace 数据也不知道该看什么。根据我实际排查的经验Agent 失败大致可以归到下面几类这个分类也基本对应了后面几篇论文各自盯住的问题域。2.1 规划失败方向从一开始就错了规划失败是最致命的一类。Agent 拿到任务后第一步的推理就偏了后面所有步骤都在错误的方向上努力。典型表现是用户问帮我对比一下 A 和 B 两个方案的报价Agent 却去调了一个查询单个方案详情的工具然后基于单方案信息硬编了一个对比。这类失败的根因通常在任务分解环节。LLM 把复杂任务拆成子任务时如果拆解粒度和工具能力不匹配就会选错工具。比如工具库里只有按 ID 查订单和按用户查订单列表但任务需要的是按时间范围聚合订单金额模型很可能强行用前两个工具拼凑结果就是错的。排查这类问题核心是看第一步的推理链。我一般会把 Agent 的 planning 输出单独打日志重点看它选了哪个工具、理由是什么。如果理由本身就站不住那后面不用看了直接改 prompt 或者改工具描述。2.2 检索失败喂给模型的东西就是错的RAG 类 Agent 的失败很大一部分出在检索环节。模型本身没问题但你给它的上下文里全是无关内容它只能基于垃圾进垃圾出。这类失败有个很隐蔽的特点模型会非常自信地基于错误上下文给出答案因为它不知道检索结果本身是错的。检索失败又分几种召回为空知识库里根本没有、召回噪声大返回了一堆不相关文档、召回顺序错最相关的排在了后面被截断。这三种的处理方式完全不同所以诊断时必须区分开。2.3 工具调用失败参数错了但没报错工具调用失败不一定是接口报错。更常见的是参数语义错误模型传了一个格式正确但语义错误的参数。比如查订单模型把用户 ID填成了订单 ID接口正常返回但返回的是别人的订单或者空结果。还有一种情况是工具返回结果被误读。工具返回了一个嵌套 JSON模型在解析时把字段理解错了或者把多个结果当成一个。这类问题在工具返回结构复杂时特别常见。2.4 上下文与记忆失败它忘了多轮 Agent 里上下文管理是个大坑。对话轮次一多早期信息被挤出窗口或者摘要时丢了关键约束。表现就是 Agent 突然忘了用户前面强调过的限制条件比如预算不超过 5000。这类失败最难查因为单看某一轮的执行都是对的问题出在跨轮的信息传递上。2.5 失败分类速查表失败类型典型表现根因位置排查入口规划失败方向错、工具选错Planning 阶段第一步推理链检索失败答案基于无关内容Retrieval 阶段召回结果与 query 相关性工具调用失败参数语义错、结果误读Tool 调用阶段入参出参对照上下文失败忘记约束、前后矛盾Memory 管理跨轮信息传递把这张表记住后面看论文思路时你会更容易对上号——每篇论文其实都在强化其中某一环的诊断能力。3. ReAG把检索过程本身变成可诊断的对象ReAG 这条思路的核心是把 RAG 里最黑盒的检索环节打开让检索过程本身产生可诊断的信号。传统 RAG 你只能看到召回了哪些文档但看不到为什么召回这些检索是否真的支撑了最终答案。ReAG 要解决的就是这个。3.1 为什么检索需要单独归因先说个我实际遇到的例子。一个做技术文档问答的 Agent用户问如何配置超时重试Agent 给出的答案里混进了一段关于数据库连接池的内容。查召回结果发现检索确实返回了一篇讲连接池的文档因为那篇文档里也出现了超时重试这些词。模型看到这段内容就把它揉进答案了。问题在于检索的相关性和答案的正确性之间存在一个归因断层。你知道召回了什么但不知道召回内容对最终答案贡献了多少、哪一段是噪声。ReAG 的价值就在于它让检索结果和最终答案之间建立起可追溯的对应关系。3.2 ReAG 的核心机制拆解ReAG 的做法简单说就是在检索和生成之间插入一层显式的推理与验证。它不直接把召回文档丢给模型生成而是先让模型对召回内容做一次相关性判断和证据提取把真正支撑答案的证据片段挑出来再基于证据生成。这个设计背后有个很实在的考量LLM 在生成时对上下文里所有内容是一视同仁的它不会主动区分这段是核心证据和这段是碰巧出现的噪声。ReAG 通过显式的证据提取步骤强制模型先做一次筛选相当于给检索结果加了一道质检。从诊断角度看这一步产生的中间产物极其有价值证据片段列表。当最终答案出错时你可以直接看证据列表——如果证据本身就是错的那是检索问题如果证据对但答案错那是生成问题。归因路径一下就清晰了。3.3 实操怎么把 ReAG 思路落到自己的 Agent 里你不需要完整复现论文抓住核心思想就能改造自己的链路。我一般这么做第一步在检索之后、生成之前加一个证据提取节点。prompt 大致是让模型从召回文档中逐条列出与问题直接相关的原文片段并标注来源文档 ID。这一步的输出是结构化的方便后续追踪。第二步生成阶段只喂证据片段不喂原始召回文档。这样能大幅降低噪声干扰同时让生成阶段的输入变得可控可查。第三步把证据片段和最终答案一起存进 trace。出问题时先看证据对不对再看答案对不对两步定位。注意证据提取这一步会增加一次模型调用成本和延迟都会上升。如果 QPS 高建议只对答案置信度低或用户反馈差的请求做完整证据提取正常请求走轻量路径。3.4 我踩过的坑第一个坑是证据提取过度。一开始我让模型提取所有相关片段结果它把整篇文档都标成相关等于没筛。后来改成限制条数比如最多 5 条并强制标注为什么相关效果才好。第二个坑是证据和答案的对应关系丢失。早期我没存证据 ID出问题时只能看到答案没法回溯到具体证据。后来强制每条证据带唯一 ID答案里引用证据时带上 ID归因才真正闭环。4. DuoTrace双通道追踪把执行链路和语义链路对齐如果说 ReAG 解决的是检索环节的归因那 DuoTrace 盯的是更全局的问题Agent 的执行链路execution trace和语义链路semantic trace是两条线出问题时对不上。4.1 执行链路和语义链路为什么会脱节执行链路是你代码层面能看到的东西调了哪个函数、传了什么参数、返回了什么。语义链路是模型层面的推理过程它为什么这么想、每一步的意图是什么。这两条线在传统日志里是分开的而且粒度对不上。举个例子执行日志显示调用了 search 工具参数 query退款政策返回 3 条结果。但语义层面模型当时其实是想查退款时限只是它把意图表达成了退款政策。执行链路看起来完全正常语义链路却已经偏了。你只看执行日志永远发现不了这个问题。DuoTrace 的核心贡献就是把这两条链路在时间轴上对齐让每一步执行都能对应到当时的推理意图。4.2 双通道追踪的实现思路DuoTrace 的做法是在 Agent 每一步执行时同时记录两类信息一类是执行侧的结构化数据工具名、参数、返回值、耗时另一类是语义侧的推理数据当前步骤的意图、依据、预期结果。然后通过步骤 ID 把两者关联起来。关键在于语义侧数据的采集方式。你不能指望模型主动汇报意图得在 prompt 里显式要求它在每次工具调用前输出一段意图说明格式固定比如我准备调用 X 工具目的是 Y预期得到 Z。这段说明和执行数据一起入库就形成了对齐的双通道。从诊断角度这个设计的价值在于当某一步执行结果不符合预期时你可以立刻对照语义侧的预期结果判断是模型预期错了规划问题还是执行没达到预期工具问题。这个判断在单通道日志下是做不出来的。4.3 落地时的数据结构设计我实际落地时trace 表大概长这样字段含义来源step_id步骤唯一标识系统生成intent本步意图说明模型输出expected预期结果模型输出tool_name调用的工具执行侧params调用参数执行侧result返回结果执行侧latency耗时执行侧status成功/失败执行侧有了这张表排查时就能做很多以前做不了的分析。比如筛出所有intent 和 tool_name 明显不匹配的步骤这些就是潜在的规划失败点再比如筛出expected 和 result 语义差距大的步骤这些是工具或参数问题。4.4 实操心得与注意事项第一个心得是意图说明要短。一开始我让模型写详细意图结果它写了一大段反而拖慢速度还容易跑偏。后来限制在 30 字以内只写做什么、为什么信息密度反而更高。第二个心得是对齐要按 step_id不能按时间戳。并发场景下时间戳会乱必须用显式的步骤 ID 关联两条链路。注意双通道追踪会让每次调用的 token 消耗上升 15% 到 30%因为多了意图说明的输出。如果成本敏感可以对意图说明做采样比如只对 10% 的请求做完整双通道记录其余走轻量模式。5. EDGE从失败样本里自动挖出归因规则前面两篇更多是记录和对齐EDGE 走的是另一条路从大量失败样本里自动归纳出归因规则。这解决的是一个很现实的问题——你不可能靠人工一条条看 trace样本量一大就崩了。5.1 为什么需要自动归因假设你的 Agent 每天处理 10 万次请求失败率 3%那就是 3000 条失败样本。人工看 3000 条 trace一条 2 分钟就是 100 小时。这显然不现实。你需要的是让系统自己告诉你这 3000 条失败里60% 是检索召回为空25% 是工具参数错误15% 是上下文截断。EDGE 的思路就是做这件事把失败样本聚类然后为每一类生成可解释的归因描述。5.2 EDGE 的归因逻辑EDGE 的核心是基于失败特征的聚类 规则提取。它先从每条失败 trace 里抽取一组特征比如是否调用了工具、召回文档数、上下文长度、模型置信度、错误类型等然后对这些特征做聚类把相似的失败归到一起。对每一类再提取出区分度最高的特征组合形成一条归因规则。举个具体的聚类后发现有一类失败样本共同特征是召回文档数0 且 模型置信度0.8。这条规则翻译成人话就是检索没召回任何内容但模型还是自信地编了答案。这就是典型的检索失败导致的幻觉归因规则直接指向了检索环节。5.3 特征工程归因质量的关键EDGE 效果好不好八成取决于特征选得对不对。我实际用下来下面这些特征区分度最高检索侧召回数量、最高相似度分数、召回文档平均长度工具侧调用次数、参数类型分布、返回结果大小、是否有空返回模型侧输出置信度如果有、输出长度、是否包含无法回答类话术上下文侧当前上下文 token 数、是否触发截断、跨轮引用次数把这些特征拼成向量做聚类基本能把大部分失败模式分出来。我实测下来5 到 8 个簇就能覆盖 90% 以上的失败样本。5.4 从归因规则到修复动作归因的终点是修复。EDGE 给出的规则要能直接对应到动作否则就是纸上谈兵。我一般会建一张映射表归因规则对应修复动作召回为空 高置信度加检索兜底召回为空时强制走无法回答参数类型错误集中在工具描述里加参数示例上下文截断频繁优化摘要策略或扩大窗口单工具调用占比过高检查工具描述是否误导模型这张表是活的每次归因出新规则就往里加。跑一段时间后你会发现失败率在稳步下降因为每一条规则都对应一个被堵住的漏洞。6. 把三篇拼成一条完整链路诊断与归因的工程落地单独看每篇论文都有价值但真正有用的是把它们拼成一条能跑的链路。我现在的做法是分四层采集层、对齐层、归因层、修复层。6.1 采集层全量记录重点采样采集层负责把 Agent 每一步的执行数据和语义数据都记下来。执行数据全量记语义数据意图说明、证据提取按采样率记。采样策略我一般这么定正常请求 10%失败请求 100%用户负反馈请求 100%。这样既控制成本又保证关键样本不丢。6.2 对齐层用 step_id 串起双通道对齐层就是 DuoTrace 那套用 step_id 把执行链路和语义链路关联起来。这一层的产出是一张结构化的 trace 表后面所有分析都基于它。6.3 归因层ReAG 证据 EDGE 聚类归因层做两件事一是用 ReAG 的思路对每条失败 trace 提取证据片段判断是检索问题还是生成问题二是用 EDGE 的思路对失败样本做聚类归纳出批量归因规则。前者解决单条归因后者解决批量归因。6.4 修复层规则到动作的闭环修复层把归因规则转成具体动作落到代码或配置里。这一步必须有人参与因为有些规则需要判断是改 prompt、改工具还是改检索策略。但有了前面的归因人的判断成本大幅降低。6.5 一个完整的排查实例说个真实案例。某天发现 Agent 的订单查询类问题失败率突然从 2% 涨到 8%。走一遍链路采集层显示失败请求的 trace 都完整。对齐层一看失败步骤集中在工具调用后intent 是查询订单状态但 result 返回的是空列表。归因层用 ReAG 思路提取证据发现检索没问题问题在工具参数——模型把订单号填成了用户 ID。再用 EDGE 聚类发现这类失败集中在用户输入包含多个数字的场景模型分不清哪个是订单号。修复动作很明确在工具描述里加参数示例明确订单号是 16 位纯数字用户 ID 是 8 位。改完第二天失败率回落到 2.5%。这个案例里如果没有双通道对齐你只会看到工具返回空根本不知道是参数错了如果没有自动归因你得一条条看才能发现多个数字这个共性。链路的价值就在这。7. 常见问题与排查技巧实录这一节把我实际踩过的坑和常见问题整理一下都是文档里不会写的。7.1 常见问题速查表问题现象可能原因排查动作trace 缺失关键步骤采样率配置错误检查失败请求是否 100% 采样意图说明和实际调用不符prompt 约束不够加格式校验不符则重试归因规则太泛无法落地特征区分度低增加检索/工具侧细粒度特征修复后失败率反弹规则覆盖不全重新聚类看是否出现新簇成本超预算语义采集过多降低正常请求采样率7.2 独家避坑技巧技巧一先跑通单条归因再上批量。很多人一上来就想做自动聚类结果特征没调好聚出来的簇毫无意义。正确顺序是先手工归因几十条搞清楚失败模式长什么样再让机器去学。技巧二意图说明用固定模板。别让模型自由发挥给它一个模板我准备调用 [工具名]目的是 [一句话]预期得到 [结果类型]。固定格式解析起来才稳。技巧三证据提取限制条数。前面提过不限制条数模型会偷懒全标相关。限制 3 到 5 条并强制说明理由筛选效果最好。技巧四归因规则要定期清理。规则会过时尤其是业务变化后。我一般每月 review 一次把不再触发的规则归档避免规则库膨胀。技巧五修复动作要可回滚。改 prompt 或工具描述可能引入新问题所有修复动作都要能一键回滚并保留修改前后的失败率对比。7.3 关于成本和收益的权衡这套链路不是免费的。语义采集、证据提取、聚类分析都会增加成本和工程复杂度。我的建议是分阶段上先上采集和对齐成本最低收益最直接跑一两个月积累样本后再上自动归因。如果 Agent 请求量不大比如每天几千次甚至可以跳过自动归因人工看 trace 就够了。注意不要为了完整而过度工程化。诊断链路的目的是解决问题不是炫技。能定位问题的最小方案就是好方案。8. 后续可以怎么扩展这套链路跑通后还有几个方向可以继续挖。一是把归因结果反哺到 prompt 优化让模型在生成时就知道哪些坑不能踩二是做在线诊断不等失败发生而是在执行过程中实时检测异常信号并干预三是跨 Agent 的归因规则共享把一类 Agent 的失败模式迁移到相似场景。我自己目前在做的是第二点在线诊断的难点在于如何在不增加太多延迟的前提下做实时判断。初步想法是用轻量特征做快速筛查可疑的再走完整归因。这块还在试有结果再单独写一篇。最后分享一个我自己的体会Agent 诊断这件事工具和论文都只是辅助真正决定效果的是你对业务失败模式的理解深度。你越清楚自己的 Agent 在什么场景下容易出错归因规则就写得越准。论文给的是方法论业务理解才是那个不可替代的部分。