Harness 五要素:从"能跑"到"可靠"

Agent开发入门系列第 5 篇 · 读这一篇需要 6 分钟

系列导读:这个系列不追热点,只把 Agent 架构里那些密度极高、一次读不透的概念,一个一个拆开。

先说一个几乎每个做 Agent 的人都见过的场景。

你给 Agent 下达了一个任务,它跑了几分钟,最后给你一句斩钉截铁的汇报:

「已完成。请查收配置文件 service.yaml,另外顺手优化了日志格式。」

你打开目录一看------service.yaml 根本不存在。日志一行没动。而它给你展示的那段"已修改内容",是从上下文里某个示例文件复制来的。

问题不在于它"不够聪明"。问题在于:它没有任何机制知道自己错了。

这就是从 Demo 到产品的那道坎。


一、那道坎到底有多深

模型在 Agent 场景里可能产生的失败,远不止"答错"这一种。翻一遍清单,会发现它们有个共同点:全都是过程性的,不是能力性的。

失败模式 具体表现
幻觉 编造不存在的文件、数据、接口返回
调用不存在的工具 发明一个函数名,或者拼错参数名
错误参数 路径写错、类型不对、必填项漏填
工具选择错误 手里有查询工具,凭印象直接给答案
出错后无法恢复 权限不足报了错,换个姿势再报同一个错
重复重试 同一条命令跑十几遍,每遍结果一模一样
任务未完成却结束 三个子任务做了两个,报告说"全部搞定"

这七种失败有个共同特征:模型自己察觉不到。 它不会因为幻觉而感到不对,不会因为死循环而察觉自己卡住了,不会因为漏做任务而在汇报时心虚。

早期 Agent 框架的主要关注点是把上面这些能力"跑起来"------能调工具、能循环、能自主决策。而生产系统越来越重视另一件事:可靠地做事。

于是 Harness 工程要解决的问题可以浓缩成一句话:

如何让 Agent 从"能运行"变成"可靠地完成任务"。

这张对照表值得先扫一眼:左列每一种翻车,右边都有对应的兜底机制。可靠性不是靠一句提示词喊出来的,是靠工程一层层接住的。


二、Harness 五要素

第 1 篇给过一个公式:

Harness = 上下文管理 + 工具接口 + 约束 + 验证 + 纠正

这次把它摊开成图。

五要素不是并列的五个清单,而是一个首尾相接的闭环:前两个让 Agent 能做事,后三个分别在错误发生的不同阶段把它拦住、找出来、恢复掉。

1. Context(上下文管理)------ 让它看得见

这一项的职责比"把用户那句话拼进去"要宽得多,至少要负责五件事:

  • 提供充分观察 ------ 环境的真实状态得进上下文,模型才可能基于事实决策
  • 维护任务状态 ------ 现在进行到哪一步、还剩什么,不能让模型靠回忆
  • 组织知识 ------ 该查的文档、该读的代码,先检索好再摆进去
  • 管理历史与记忆 ------ 跨轮次的偏好、之前踩过的坑
  • 支持旁路查询 ------ 怀疑某个信息过时了,能在不中断主线的前提下额外查一次

第 2 篇已经详细拆过上下文的五个组成部分,这里不重复。但有一条工程经验值得单独拎出来:目标和约束要进固定前缀,不能只躺在历史轨迹里。

一条 20 轮的任务,Agent 到第 18 轮还记着最初的约束,才叫可靠。靠"翻聊天记录"来记约束,本质上是在赌上下文窗口足够长。

2. Tools(工具接口)------ 让它动得了

工具为模型提供观察和行动的方式。设计上有三个要点:

  • 清晰的命名 ------ read_file 比 execute_io 强得多,前者自带语义,后者要靠文档解释
  • 提供参数示例 ------ schema 里带上真实可用的样例,能显著降低参数填错率
  • 明确能力边界 ------ 工具描述里要写清"什么时候该用它、什么时候不该用"

第 4 篇专门讲过工具集设计,核心结论是工具不是越多越好,30 个工具会让模型的选择准确率明显下降。这一项的重点从来不是"多挂几个",而是"让每一个都清楚、边界明确、不重叠"。

3. Constrain(约束)------ 让它不敢乱来

约束限定 Agent 能做什么,负责控制权限、采用安全默认值。

这里有一个比"限制"重要得多的原则:

默认关闭,按需开放。

工具默认不授权,文件默认只读,网络默认关闭。这跟人类工程师的权限设计是同一套逻辑------默认开放的系统,迟早会被一个意外操作打穿。

约束和验证的区别也值得说清:约束是事前 的,保证错误压根不发生;验证是事后的,保证发生了也能被抓出来。两者不能互相替代------再严的约束也挡不住模型在允许范围内做出错误决策。

4. Verify(验证)------ 让它知道自己错了

验证负责判断操作是否正确:检查结构化结果、运行测试 / 类型检查 / Linter、校验工具调用结果的合法性。

这一项有一个决定成败的原则:

验证应优先检查结构化数据,而不是只看模型的自由文本。

这句话值得展开。模型说"文件已创建",这是一段自由文本,你没法从中判断真假。但如果验证层拿到的是工具返回的结构化结果------文件列表、JSON 响应、测试退出码、行号与错误列表------真伪就是可判定的。

用自由文本验证自由文本,等于让模型自己给自己打分。把"完成的判据"从模型嘴里挪到 Harness 里,可靠性才有一个不随模型心情波动的锚点。

5. Correct(纠正)------ 让它错了能爬起来

纠错的手段是一串阶梯:自动修复、重试、回滚、接续生成、熔断、转交人工。最常用的是三个:

  • 重试 + 换策略 ------ 同一个方法失败两次以上就必须换路径,否则就是烧 token 的死循环
  • 熔断 ------ 同一动作重复达到阈值就强行中断,把控制权交回上层逻辑
  • 回滚 ------ 改错了要能退回去。这条对写操作类任务是刚需,否则一次幻觉污染就可能不可逆

还有一条容易被忽略的原则:

在确认无法恢复之前,不应把半成品或中间状态暴露给用户。

Demo 里让人看着 Agent 一步步试错很有趣。但生产系统里,用户看到的应该是通过验证的结果 ,或者明确说明"卡在哪一步、为什么卡住"。把一堆未经校验的中间产物丢出去,等于把系统故障转嫁给了用户。


三、五个要素怎么合成一个闭环

单独看五要素像是五个独立模块,放到运行路径上才看得出它们是接力赛:

markdown 复制代码
Context + Tools  →  Agent 能做事
      ↓
   Constrain     →  预防错误发生
      ↓
     Verify       →  发现已发生的错误
      ↓
    Correct       →  恢复错误,必要时升级给人
      ↓
   回到 Context   →  带着修正后的状态进入下一轮

这个闭环的质量决定一件事:同一个错误能穿透几层。

写得好的 Harness 里,约束让大部分错误压根不发生;剩下的被验证抓出来;被验证抓出来的由纠正消化;纠正不了的熔断并转人工。用户看到的是一个在边界内努力工作的系统,而不是一个偶尔清醒的赌徒。


四、一个数字:模型没变,Harness 变了

这套理论最好的证据,是 Terminal Bench 2.0 上的一个真实案例。

Terminal Bench 2.0 是评估 Agent 在终端环境中完成复杂任务能力的基准测试。LangChain 在这个基准上的得分从 52.8% 提升到 66.5% ,排行榜排名从30 名开外跃升到前 5。

关键在于:这个过程中,底层模型没有换。

改变的是 Harness,具体是四件事:

  • 让 Agent 自动检查自己的执行结果
  • 检测是否陷入重复循环
  • 优化思考策略
  • 自动纠错

13.7 个百分点的提升、几十名排行榜的跃升,全部来自模型外部的工程代码。

这个案例的意义需要说得更重一点。行业里有个常见的判断习惯:分数不够就换更强的模型。但当各家旗舰模型的能力逐渐接近时,这个招数的边际收益会快速衰减------你不能再指望"等下一代模型"来补上你的工程缺陷。

当模型能力趋同,竞争优势就会转移到模型之外。

这也是为什么越来越多团队把工程重心从"选模型、调提示词"挪到"搭 Harness"。前者是采购,后者才是护城河。


五、Claude Code 给出的现实注脚

如果想知道 Harness 在真实产品里到底有多重,去看 Claude Code 的代码构成会得到一个很直接的答案。它的 Harness 里,大量代码用在这些地方:

  • 流程状态管理
  • 多层上下文压缩
  • 权限分类
  • 熔断器
  • 错误恢复
  • 重试
  • 回滚
  • 人工接管

注意这个清单的构成------里面几乎没有"让模型更聪明"的代码,全是"让模型不乱来、不出错、出错了能爬起来"的代码。

模型和基础工具只是基础。真正复杂、真正花时间、真正构成产品差异的,是围绕工具建立的那一层保障。

这也回答了第 1 篇留下的那个比喻:Model 是马,Harness 是缰绳、挽具、马车和车夫。跑得慢的时候你会觉得缰绳多余;跑起来之后才会发现,能让马不停蹄也不翻车的,只有这一整套东西。


六、什么时候这个说法会失效

写到这里该说边界了。上面这套东西不是无条件的真理,下面几条限制是实打实的。

第一,简单任务不需要全套五要素。 一个"把这段话翻译成英文"的 Agent 只需要上下文和工具,约束、验证、纠正全是纯开销。Harness 五要素是按任务风险和复杂度逐级启用的,不是一上来就全开。

第二,Verify 本身可能成为瓶颈。 验证器也是代码,也会有 bug。而且验证越严格,Agent 越容易陷入"反复修补以求通过验证"的死循环。如果验证逻辑写错了,得到的结论是彻底错误的------比没有验证更糟。所以 Verify 必须有明确的判据来源,不能靠猜。

第三,Correct 的自动修复可能掩盖真问题。 自动重试让系统看起来很稳,但也把真实故障的信号给吞掉了。线上出问题时,监控上看到的可能只是一串"重试成功",根本不知道底下压着多少个不可恢复的错误。能自动修复的不该报警,但必须留痕。

第四,熔断和转人工的阈值很难定。 阈值太低,系统动辄中断,正常任务被误杀;阈值太高,熔断形同虚设。更麻烦的是不同任务的合理阈值差几个数量级,一个"重试 3 次"的全局配置几乎必然在某些场景下是错的。这个数值得花时间调,但别指望一次调对。

第五,Harness 自己有 bug 时,谁来验证 Harness? 这是个无解的递归困境。上下文压缩逻辑写坏了,你只能从"Agent 突然变得很笨"这个现象倒推回去。实践中的办法是给 Harness 本身写测试和轨迹回放工具,但那意味着要为保障层再写一层保障。

第六,代码量会膨胀,而且膨胀本身有代价。 五要素每个展开都是子系统:权限管理、状态机、验证器、重试策略、压缩算法、监控。几百上千行 Harness 代码会带来理解成本、测试成本和调试难度。一个只有三个步骤的流程配上完整 Harness,很可能不如一个写死的工作流。

说到底,Harness 是一笔投资。判断它值不值得的标准很朴素:这个任务失败的代价,是否大于把这套保障层维护起来的代价。


小结

这一篇讲的是 Agent 从"能跑"到"可靠"的那道坎,以及跨过它的五个环节。

ini 复制代码
Harness = Context + Tools + Constrain + Verify + Correct

一句话记住每一条:

  1. Context ------ 让它看得见,目标与约束进固定前缀
  2. Tools ------ 让它动得了,命名清晰、示例充分、边界明确
  3. Constrain ------ 让它不敢乱来,默认关闭、按需开放
  4. Verify ------ 让它知道自己错了,优先查结构化结果,不读模型自述
  5. Correct ------ 让它错了能爬起来,熔断在手,半成品不外露

而 Terminal Bench 2.0 上 52.8% → 66.5% 、排行榜 30 名开外 → 前 5 这个案例说明了一件事:模型没变,Harness 变了。当模型能力逐渐接近,竞争优势会转移到模型外部。

第 1 篇在这里埋了一个问题:如果 Harness 这么重要,那模型自己变强之后呢?

下一篇就回答这个。会出现一个反直觉的事实------有些今天必须靠 Harness 写的逻辑,正在被内化进模型。 但同样反直觉的是,内化并不等于可以删掉。


下一篇:《模型即 Agent?那 Harness 还有用吗》

关注这个系列,我会持续更新。觉得有用的话,欢迎点个赞------它会让我更有动力把下一篇写好。

相关推荐
孟健1 小时前
LLM API 安全防线:从 OpenCode 盗刷事件到 LiteLLM 多模型容灾实操
人工智能·后端·架构
GoGeekBaird1 小时前
云沙箱活跃时,文件怎么进出云沙箱
agent
程序员cxuan2 小时前
我用 WorkBuddy + ima 把公众号文章做成了知识库。
人工智能·后端·程序员
Code_Artist2 小时前
AI 终于学会写正确的汉字了?GPT Image 2.0 到底做对了什么?
人工智能·chatgpt·openai
程序员cxuan2 小时前
玩了一天 REA,我号快没了
人工智能·后端·程序员
阿里云大数据AI技术2 小时前
聚数成湖,以智驭行:卓驭如何构建移动物理 AI 的数据底座
人工智能·spark
沛东的认知和实践3 小时前
Agentic RAG检索侧设计:从模式选型到工具、循环与提示词
agent
武子康3 小时前
150毫秒和2400毫秒:同一 Agent 任务的两种延迟
人工智能·后端·agent
Behavior3 小时前
某餐饮品牌开放 MCP 接口被玩成消费级 Agent:WorkBuddy 搭出会算营养、比价格、能下单的减脂私教
aigc·agent·mcp