Harness 工程:用轨迹和评测迭代
读轨迹找失败模式,改工具、提示与环境,再用评测验证改进。
一句话理解:Harness 工程就是用固定任务集跑出轨迹,从轨迹里找到失败模式,每次只改工具、提示或环境中的一处,再用同一组任务验证有没有变好;靠证据迭代,而不是凭感觉改提示。
Agent 上线后总会出错。最常见的反应有两种:往系统提示里再加一句“请务必……”,或者直接换一个更强的模型。前者往往改好一个、坏掉一片;后者成本高,而且很多时候问题根本不在模型。前面几课拆开了 Harness 的每个零件,这一课讲怎么让这些零件越改越好:用轨迹定位问题,用评测证明改进。
为什么同一个模型,换个 Harness 差这么多
模型每一步能做的判断,取决于 Harness 给它什么:看到哪些信息、能用哪些工具、工具出错时收到什么反馈、什么时候必须停下来检查。这四样东西任何一样出问题,再强的模型也会表现失常。Anthropic 在《Demystifying evals for AI agents》中说得很直接:评估“一个 Agent”时,评估的其实是 Harness 和模型的组合。
两个一手案例:
- Anthropic 在《Building effective agents》中提到,为 SWE-bench 构建 Agent 时,他们花在优化工具上的时间比优化整体提示还多。例如模型离开根目录后经常用错相对路径,把工具改成只接受绝对路径后,这类错误就消失了。
- LangChain 在 2026 年 2 月的文章中报告,他们的编程 Agent 在 Terminal Bench 2.0 上的得分从 52.8 提升到 66.5,模型(GPT-5.2-Codex)不变,只改了 Harness:结束前强制自检、启动时注入目录结构与可用工具、检测反复修改同一文件,以及时间预算提醒。
所以 Agent 表现不好时,先把“模型不行”当作最后一个假设,而不是第一个。更多背景见 模型与 Harness。
迭代闭环:从轨迹到改动
Harness 工程是一个反复转动的闭环:
轨迹(Trajectory,也叫 Transcript 或 Trace)是一次运行的完整记录:输入、每次模型调用、工具调用的参数与结果、错误、耗时和最终输出。没有轨迹,你只能看到“答错了”;有了轨迹,你才能看到“第 3 步查了订单但没查支付,就下了结论”。怎么记录轨迹见 Tracing。
读轨迹的要领是 找第一个出错的步骤,而不是盯着最后的答案:后面的错误常常只是第一处错误的连锁反应。同时留意模型没做的事,Anthropic 在《Writing effective tools for agents》中提醒,Agent 在反馈里遗漏的内容,往往比它写出来的更重要。
找到第一处错误后,给它贴上失败模式的标签:
| 失败模式 | 轨迹里的信号 | 通常的根因 |
|---|---|---|
| 不调用或选错工具 | 直接编造,或拿 A 工具干 B 的事 | 工具描述没写清何时调用 |
| 参数反复出错 | 同一工具连续报参数错误 | Schema 缺少格式约束或示例 |
| 被工具结果淹没 | 结果很长,之后答非所问 | 返回值没有精简、没有截断 |
| 原地打转 | 相同参数的调用重复出现 | 错误信息不可行动,缺重复检测 |
| 违反业务规则 | 工具都用对了,结论却违规 | 规则不在上下文里,或只写在提示里 |
| 过早宣布完成 | 没有验证就结束 | 缺少结束前检查 |
| 环境问题 | 超时、依赖缺失、权限被拒 | 执行环境本身有问题 |
| 评分器误判 | 轨迹合理却被判失败 | 评测写错了,而不是 Agent 错了 |
最后一行常被忽略。Anthropic 的评测文章专门强调:不读轨迹,你就不知道评分器是否在正常工作。把失败逐条归类并统计频率,先修出现最多、影响最大的那一类。归因方法的细节见 错误归因。
改工具、改提示,还是改环境
同一个失败,往往可以在好几层修。原则是:在问题产生的那一层修,能用程序保证的就不要交给提示。可以按下面的顺序逐个排除:
几条经验:
- 先怀疑评测和环境。评分器误判、沙箱缺依赖、下游接口超时,都会伪装成“模型不行”。改提示修不好这类问题,只会让提示越来越臃肿。
- 硬规则交给程序。“写操作必须确认”“卡号必须脱敏”这类规则,写在提示里只是“请模型遵守”,做成 Hooks 或 权限规则 才是“程序保证执行”。
- 工具是性价比最高的改动点。改名称和描述,让模型知道何时调用;收紧参数格式,让错误的调用更难发生;精简返回值、写清错误信息,让模型读得懂结果。原则见 工具设计原则,运行时的截断与超时见 工具运行时。
- 信息问题改装配。规则没进上下文,模型当然不会遵守;工具结果太长,关键信息就会被淹没。见 上下文装配。
- 改提示时写原则,不写特例。“承诺日期已过的订单要标注已超时”是原则;“如果是 ORD1001 就说已超时”是在背答案。
用固定任务集验证改进
改完之后,用同一组任务、同一个模型和同样的配置重跑,前后对比。几个要点:
- 任务来自真实失败。Anthropic 建议从 20–50 个取自真实失败的简单任务起步,不必等到攒够几百个。构建方法见 构建评测集。
- 每个任务跑多次。Agent 的输出每次都不同,只跑一次的差异可能是噪声。Anthropic 区分了两个指标:pass@k 是 k 次里至少成功一次的概率,pass^k 是 k 次全部成功的概率。面向用户、要求稳定的 Agent,更该看后者。
- 不只看通过率。Anthropic 在工具文章中建议同时记录工具调用和任务的总耗时、工具调用次数、Token 消耗和工具报错数。一次改动可能不改变成功率,却让 Token 减半。
- 过程也要评。结果对了但多查了三次、或者差点执行了不该执行的写操作,同样是问题。见 结果评估与轨迹评估。
- 一次只改一处,并记改动日志:改了什么、基于哪条失败、预期改善什么、实际结果如何。同时改三处,你永远不知道是哪一处起了作用。
避免对评测集过拟合
在同一批任务上反复调,分数总会涨,但涨的可能只是“背题”能力。LangChain 在上面那篇文章中也提醒,针对单个任务的改动不利于泛化,可能导致其他任务回退。Anthropic 在改进工具时,则用 保留测试集(held-out test set)来确认没有对“训练用”的评测过拟合。
过拟合的信号很好认:提示里出现越来越多的具体订单号或具体文件名;开发集分数一路上涨,保留集纹丝不动;评分器被“钻了空子”,比如只检查关键词,Agent 就学会堆关键词。
应对办法:
- 分三份用:开发集用来读轨迹和调试,保留集只看分数,回归集收录每一个修好的失败。
- 定期换血:从线上新出现的失败里补充任务,淘汰已经饱和、人人都能过的题。
- 区分两类评测:Anthropic 的建议是,能力评测应从较低的通过率起步,给改进留出空间;回归评测则应接近 100% 通过,用来发现“以前能做的现在做不了”。
- 警惕漂亮的平均分:总分上涨时,逐类看失败模式有没有此消彼长。
这套闭环一旦跑通,就可以接到线上:把线上轨迹里的新失败补进评测集,每次改动后自动回归,见 持续改进闭环。
常见误区
- “表现不好就换个更强的模型。” 先读轨迹。如果失败集中在工具参数、规则缺失或环境超时,换模型只是用更高的成本掩盖问题。
- “在提示里多加几句‘务必’就行。” 提示越堆越长,规则之间会互相冲突;必须遵守的规则应该交给 Hook 和权限,而不是更大声的提示。
- “开发集分数涨了,就说明变好了。” 没有保留集的提升可能只是背题;没有回归集的提升可能伴随着旧问题复发。
产品经理检查清单
- 我们有固定的评测任务集吗?任务来自真实失败,还是凭空想象的?
- 每次运行都留下完整轨迹了吗?失败时能回放到具体哪一步?
- 失败有没有按模式归类,并统计每类的频率?
- 这次改动针对哪一类失败?改的是工具、提示、环境,还是评测本身?
- 对比时每个任务跑了几次?除了通过率,还看了步数、耗时和 Token 吗?
- 有没有保留集和回归集?上线标准写清楚了吗?
练习
用上一课的 最小 Agent 做一次完整的迭代(约 60 分钟):
- 写 10 个订单售后问题,覆盖正常诊断、订单不存在、支付记录缺失等情况,为每个问题写一条通过标准。
- 每个问题跑 3 次,保存每次的工具调用记录。
- 读失败的轨迹,按上面的表格归类,找出出现最多的失败模式。
- 按图 2 的顺序决定改哪一层,只改一处。
- 重跑全部问题 3 次,对比改动前后的通过率、工具调用次数和报错数,写三行结论:改了什么、哪里变好了、有没有变差的地方。
延伸阅读
- Demystifying evals for AI agents:任务、试验、轨迹、评分器等概念,pass@k 与 pass^k,能力评测与回归评测。
- Writing effective tools for agents — with agents:用评测驱动工具改进,以及用保留测试集防止过拟合。
- Building effective agents:附录中关于工具提示工程与 SWE-bench 的经验。
- Improving Deep Agents with harness engineering:只改 Harness 提升 Terminal Bench 2.0 得分的完整过程。
下一步
迭代多了你会发现,有些能力值得自己写,有些直接用现成的更划算。下一课「框架与 SDK 选型」帮你决定哪些 Harness 能力买现成的、哪些自己写。