失败归因:定位首个错误
失败归因要回答什么、产出什么?
- 目标: 对每条失败轨迹标出主要错误类别、首次出现不可接受行为的步骤、对应的工具调用或模型输出,并附上可复核的证据;
- 归因对象: 轨迹中的首个导致任务偏离的错误——后续错误往往只是连锁反应,不能把最后一个报错简单当成根因;
- 三类信号来源: 用户明确纠正(“不要这么做”)、用户点踩或负面反馈、事后通过状态检查/规则验证器/LLM 评审发现 Agent 做了不该做的事;
- 依赖人的判断: 过程可以借助 LLM,但不能完全依赖 LLM,因为失败归因往往反映了产品问题,不止是技术问题;
- 规模化: 错误分类可能包含多个大类、数百种小类,这些类别与归因方式可作为归因标注 Agent 的提示词或 Skill;
- 结构化要求: 归因记录采用 JSON 或 YAML,引用具体步骤号、工具名与观察证据,区分根因与后果、判断是否可恢复并给出置信度;
- 证据留存: 除 LLM 输出的记录外,还应保存任务目标、环境状态、Agent 版本、工具集版本与完整轨迹,以便回归测试;
Coding Agent 的初始错误分类有哪些?
| 错误类别 | 典型表现 | 首个错误的定位方式 |
|---|---|---|
| 需求理解与歧义处理 | 漏掉需求里的一个条件、范围理解过宽或过窄;仓库里有两个同名配置时直接选一个,既不说明也不追问 | 用 LLM 把原始需求与 Agent 实际动作序列逐条对照,先定位第一处偏离,再回溯到造成它的工具调用或那句答复 |
| 流程与规范缺失 | 未执行单元测试就提交、未写 Plan 就开始改代码、绕过既定架构约定 | 找第一次违反流程约定的动作,如首次 git commit、首次写文件,回看它之前有没有读过约定来源 |
| 工具调用错误 | 同一文件反复编辑失败、JSON/schema 或参数格式错误、特殊字符导致抄写与转义错误 | 记录第一次失败的编辑与原始请求、错误返回;重复失败属于后续症状 |
| hack 验证环境 | 直接改断言、加 skip、mock 掉被测逻辑;声称 “测试已通过” 但根本没跑 | 取第一次改动测试或验证逻辑的消息,再把完成声明与轨迹里真实执行过的命令交叉核对 |
| 修改不完整 | 改了函数签名与三处调用方,漏了第四处动态调用、另一语言的绑定或 schema | 把声称的影响面与真实影响面做集合差,取第一个遗漏项,回看检索时用了什么关键词 |
| 对用户的信息反馈错误 | 工具调用与环境状态全对,最终告知用户的金额、状态、时间却错了 | 把答复里的每个事实断言与工具返回值逐条对齐,取第一条无法溯源或与工具返回矛盾的断言 |
| 非功能性回归 | 改了公开 API、schema 而无数据库迁移脚本;为让校验通过而删掉校验 | 取第一次做出该改动的消息,看它是否意识到自己动的是公开接口或需迁移的结构 |
| 模型执行异常 | 输出中途截断、无故停止、超时,或没有完成收尾动作就结束 | 定位第一个异常终止位置,区分模型停止、Harness 超时与工具服务故障 |
| 过早停止任务 | 多目标任务只完成一部分;未穷尽合理方案就宣布不可能 | 定位第一次遗漏目标或放弃探索的决策,并与最终验证失败分开记录 |
- 主因判定: 多个类别同时出现时,按 “最早且能解释后续失败” 的原则选主因,其余保留为次因;
- 根因与后果: 例如
edit_file返回old_string匹配失败,之后 Agent 连续三次重试仍未写入文件,主因是 “文件编辑与工具调用错误”,三次重试是后果而非三个独立根因; - 规则先筛、LLM 再定位: 至少三类可先用规则筛出嫌疑轨迹——完成声明与实际执行命令交叉核对、diff 是否触及测试断言与 skip 标记、diff 是否改动公开 API 或 schema 而无迁移文件;
- 成本与准确性: 规则先筛、LLM 再定位,比把全部轨迹喂给 LLM 更便宜也更准;
“做对了但说错了” 为什么会被整体成功率掩盖?
- 原因: 多数评估只检查环境状态;
- τ²-bench 数据: 带有信息告知要求的 704 次运行共失败 240 次,其中 162 次是信息告知出错;有 80 次(占全部失败的三分之一)环境状态正确但信息告知错误;
- AndroidWorld T3A 案例: 把图库中
expenses.jpg的开销录入记账应用,Agent 用 32 步完成授权、搜索、打开图片、逐条填写与保存,没有任何一步返回错误,最后自行宣告完成,验收却报告应写入的记录不存在; - 首错位置: 第 8 步的思考写着 “I cannot actually see the content/details of the expenses in the image”,它自己已经知道没拿到数据,却既没有停下也没有报告;
- 幻觉传播: 到第 11 步,四条开销数据凭空出现在它的记录里,此后的每一次输入和保存都基于这四条编造的数据;
- 根因归属: T3A 是纯文本 Agent,观察空间里只有元素树、根本没有图像像素,所以根因不是 “模型不会 OCR”,而是 Harness 的观察通道缺失;
- 误归因代价: 若记成模型能力问题,接下来就会去换模型或做 OCR 训练;真正该做的是补观察通道;
作用域敏感的文档格式错误应如何评估?
- 反例: 用户说 “引号格式不对” 时,不能直接把它转成全局字符替换;
- 需区分的字符: ASCII 直引号(
"、')、中文弯引号(“”、‘’)与 Markdown 反引号; - 语法角色: 同一字符在中文自然语言、英文原文、行内代码、代码块、代码注释、JSON 和路径中承担的语法角色不同;
- 作用域片段:
ZH_PROSE、EN_PROSE、QUOTED_SOURCE、INLINE_CODE、CODE_BLOCK、CODE_COMMENT、JSON_OR_SCHEMA; - 片段内容: 每个片段保存允许变换集合、必须保护的字符以及修改后的验证器结果;
- 轨迹前缀验证要求: 要求模型做最小修改,并同时检查中文文档风格、英文原文保持率、代码与 JSON 语法,以及非目标文本的编辑距离;
- 不确定时的正解: 规则无法确定作用域时,应允许模型保留原文并请求澄清,而不是把猜测性修改算作通过;
精确复制错误如何从 old_string mismatch 逐层定位?
- 反例: 不能只归因于 “模型抄错了”;
- 保存: 对同一个字符串保存原始字节哈希、Unicode code point 序列与 tokenizer token ID 序列;
- 定位链路:
文件原始字节 → 工具返回 → Harness 序列化 → 模型上下文 → 模型 token 输出 → 解码字符串 → JSON/tool-call 解析 → 工具匹配; - 探针覆盖: 直接复述、从长上下文抽取、放入工具参数、相似字符串选择,以及空格、换行、反斜杠、Unicode 组合字符和低频 token;
- 指标: byte-exact match、code-point-exact match、token-exact match、首次分歧位置与真实工具成功率;
- 分流判断: 若模型在直接探针测试中输出正确而工具调用失败,应修复 tokenizer、序列化、Harness 或工具协议;只有首个差异出现在模型输出时,才把该案例转成复制训练数据;