Agent 的表现瓶颈常常不在模型,而在模型外面那层执行系统——Harness。它涵盖工具定义、上下文管理、循环控制与错误恢复。这篇讲清 Harness 的构成、它如何把同一个模型的能力放大数倍、含糊工具描述引发的典型故障,以及如何用评测驱动 Harness 迭代。

Harness:模型之外的一切

工程上有个常用等式:Agent = Model + Harness。模型负责推理与生成,其余所有东西都属于 Harness:系统提示、工具定义与执行环境、上下文组装、权限与沙箱、循环控制、状态持久化、观测与反馈回路。

一个反向思考法很有效:列出模型做不到的事,逐项补齐,就是 Harness 的组件清单。模型记不住多轮历史——补记忆与上下文管理;模型跑不了命令——补执行环境与沙箱;模型不知道自己做得对不对——补验证闭环(编译、测试、截图比对);模型在长任务里会跑偏——补状态追踪与进度文件。

有一个很有说服力的公开实验:同一场编码评测中,模型不换,仅替换文件编辑工具的设计,任务完成率从个位数跃升到六成以上。模型参数一行没动,差别全在 Harness 提供的操作粒度、结果回传方式和错误的可利用性。这类结果解释了为什么常见的 Agent 故障——重复调工具、无视约束、长任务丢状态——往往不是换模型能解决的。

一张六层检查清单

为便于排查系统缺项,可以把 Harness 分成六层自查:信息边界(Agent 该知道什么)、工具系统(怎么与外部交互)、执行编排(多步任务怎么串)、记忆与状态(中间产物怎么管)、评估与观测(怎么知道做对了没有)、约束与恢复(出错了怎么办)。它像给新员工搭工作环境:岗位说明、办公工具、操作流程、项目台账、质检、应急预案,缺哪一环都会在某天变成事故。起步阶段不必六层全建,先补信息边界与故障恢复,任务变长后再补编排、状态与观测。

好的 Harness 如何放大模型能力

工具即接口设计。工具的数量、命名、参数结构和返回值格式,直接决定模型能否稳定表达意图。经验法则:工具要正交(每个工具只做一件明确的事),返回值要面向下一步行动——报错信息里写清”该怎么改”,而不是只甩一行错误码。

上下文是稀缺资源。窗口不是越大越好:塞得越满,模型注意力越涣散,工具日志、旧决策、重复资料会挤掉关键指令。常见手段是渐进式披露——规则文件只放索引,命中场景再加载细则;上下文接近阈值时做压缩,或生成结构化交接文档后重置会话,而不是无限堆积。

错误必须可消化。测试失败只返回退出码 1,模型只能瞎猜;返回失败用例、堆栈摘要和疑似相关文件,模型下一轮就能精准修正。Harness 的反馈质量决定循环是收敛还是空转。

约束要机械化执行。只写在文档里的规范,模型迟早偏离;能让流程编译不过的才是规则。自定义 Linter、结构测试、权限钩子(拦截删除命令、内网请求、读取密钥文件)都是把”应该”变成”必须”的手段。

典型失败:含糊的工具描述

某 Agent 挂了两个工具:search_docs(query) 与 query_db(sql),描述分别是”搜索文档”和”查询数据”。用户问”上个月的工单量趋势”,模型选了 search_docs("上个月工单量趋势")——搜出一堆制度文档,然后自信地编造了数字。

问题不在模型笨,而在 Harness 给了它无法区分的选项。修复不是换更强的模型,而是把工具描述写成可判定的边界:

tools = [
{
"name": "query_metrics",
"description": (
"查询业务指标的时间序列数据。"
"适用:工单量、交易额等数值型统计。"
"不适用:查找制度、手册等文本资料(请用 search_docs)。"
),
"parameters": {
"type": "object",
"properties": {
"metric": {"type": "string", "description": "指标名,如 ticket_count"},
"start": {"type": "string", "description": "起始日期,YYYY-MM-DD"},
"end": {"type": "string", "description": "结束日期,YYYY-MM-DD"},
},
"required": ["metric", "start", "end"],
},
}
]

三个要点:说清”什么时候用”,更要说清”什么时候别用”;参数带示例与合法取值;报错时提示可替代的工具路径。改完后必须拿同一批失败用例回归,误调用率应显著下降——不动评测,这个”应该”永远无法验证。

评测驱动的迭代

Harness 的每次改动——换工具描述、调上下文策略、加重试逻辑——都是一次实验,需要评测闭环来验证:

  1. 攒失败用例集:从线上 Trace 收集真实 Badcase(误调用、超步数、丢状态),作为回归集。一个值得坚持的习惯是:每条防护规则都要能对应到一个真实发生过的失败。
  2. 逐层度量:工具选择准确率、参数正确率、单任务步数与 Token、端到端成功率。只看最终答案会掩盖过程退化——工具全挂时模型也可能输出流畅的报告。
  3. 一次只改一个变量:同时换模型和改 Harness,结果无法归因。
  4. 模型升级后反向做减法:Harness 里每个组件都编码了一条”模型自己做不到”的假设。模型变强后要重新压测这些假设,删掉已冗余的保护层——否则 Harness 越来越厚,上下文与编排成本全是浪费。

落地顺序

不必一次建完整套 Harness,优先级大致是:

  • 先补观测与权限:Trace 加工具钩子,决定系统能否上线、事故能否复盘。
  • 再补上下文管理:压缩、交接、进度文件,决定长任务的质量上限。
  • 最后才是花哨能力:多 Agent、复杂编排。生产事故极少源于”模型不会推理”,更多源于工具失控、权限过大、失败后没有现场。

面试视角

Harness 与 Prompt 工程什么关系? Prompt 工程解决”把指令说清楚”,上下文工程解决”该给模型看什么”,Harness 工程解决”系统怎么持续执行、纠偏、观测和恢复”——一层套一层,处理范围递增。

模型表现不稳,先查什么? 先查工具接口能否让模型表达意图、错误输出是否可行动、验证闭环是否存在。这些补齐之前,换模型只是在同一面墙上反复撞。

Harness 会不会过时? 会局部过时。每个组件都是对模型能力的假设,模型升级后应重新验证并删减,保留能捕获真实错误的机制。

小结

  1. Agent = Model + Harness;Harness 是工具、上下文、执行环境、循环控制与恢复机制的总和。
  2. 好 Harness 放大模型:正交工具、可消化的错误反馈、渐进式上下文、机械化约束。
  3. 含糊的工具描述是误调用高发根因;描述要写明”何时别用”,报错要提示替代路径。
  4. Harness 迭代必须评测驱动:失败用例集、分层指标、单变量实验,模型升级后还要记得做减法。