一个编程智能体,是“模型”加上围绕它构建的一切。Harness 工程把这套脚手架视为一个持续演化的产物,每次智能体犯错,都会再收紧一层。
简单说:每当一个智能体失败,你就为它设计一个永久性的解决方案,让它以后不再犯完全相同的错误。
过去两年,整个行业一直在争论模型本身:谁最聪明、谁写 React 最干净、谁幻觉最少。这样的讨论当然重要,但它忽略了系统的另一半。
模型只是一个正在运行的智能体的输入之一。剩下的部分,就是 Harness:围绕模型包裹起来、让它真正能完成任务的提示词、工具、上下文策略、钩子、沙箱、子智能体、反馈回路和恢复路径。
一个普通模型配上优秀 Harness,往往能稳定胜过一个优秀模型配上糟糕 Harness。 越来越多真正有意思的工程工作,已经不再是选哪个模型,而是设计模型周围这套脚手架。
这套方法论现在已经有了名字。@Vtrivedy10 提出了 harness engineering 这个术语,并对 Harness 到底是什么、每个组成部分为什么存在,给出了一种非常清晰的拆解。行业里的其他声音也在往相似方向汇聚,比如 @dexhorthy 持续追踪这些正在浮现的模式,HumanLayer 把智能体失败理解为配置层面的“能力问题”,Anthropic 的工程团队不断发布关于长时运行应用设计的指南,而 Birgitta Böckeler 则在探索用户侧的实际体验。
这篇文章就是把这些线索整理到一起。
Harness 到底是什么?
Trivedy 的核心定义已经解释了大部分问题:
智能体 = 模型 + Harness。只要你不是模型本身,你就是 Harness。
Harness 包含所有不属于模型本体的代码、配置和执行逻辑。一个裸模型不是智能体。只有当 Harness 为它提供状态、工具执行、反馈回路和可执行的约束时,它才真正成为智能体。
具体来说,一个 Harness 通常包括:
系统提示词、
CLAUDE.md、AGENTS.md、技能文件,以及subagent指令。工具、Skills、MCP 服务,以及它们的技术描述。
配套基础设施,例如文件系统、沙箱和无头浏览器。
用于拉起子智能体、处理交接和路由模型的编排逻辑。
用于确定性执行的钩子和中间层,比如 lint 检查或上下文压缩。
用于日志、追踪、成本与延迟计量的可观测性工具。
从本质上说,智能体是一个通过工具循环去达成目标的系统。真正的能力,在于你如何设计这些工具,以及如何设计那条循环。
虽然这看起来是一个巨大的系统表面,但它是 你的 表面,而不是模型提供方的表面。Claude Code、Cursor、Codex、Aider 和 Cline,本质上都是 Harness。底层模型甚至可能完全一样,但你最终体验到的行为,大多数时候是由 Harness 决定的。
重新审视“skill Issue”
当智能体做出一些非常离谱的事时,工程师很容易第一反应就是怪模型,最后把问题归档成“等下一个版本模型出来再解决”。
Harness 工程的思路,恰恰反对这种默认反应。大多数失败其实都具有相当高的可解释性。如果智能体无视了某个约定,就把它写进 AGENTS.md。 如果它执行了破坏性命令,就写一个钩子把它拦住。如果它在一个 40 步任务中途迷路了,就把架构拆成规划器和执行器。如果它总是在收尾时交出一份坏掉的代码,就把类型检查的回压信号接进那条循环里。
正如 HumanLayer 所说:“这不是模型问题,而是配置问题。” 看看性能基准就知道:同一个领先模型,跑在一个现成框架里时,分数往往会比它跑在一个定制化、高度调优的 Harness 里低得多。只要把模型放进一个拥有更好代码库工具、更紧提示词和更强回压的环境,它就能展现出原始配置根本没激活出来的能力。
今天模型“理论上能做到什么”和你“实际看到它做到什么”之间的差距,在很大程度上就是 Harness 的差距。
棘轮效应:每一次错误都要变成一条规则
Harness 工程里最重要的习惯,就是把智能体的错误视为永久性信号,而不是那种重试一下就忘掉的一次性偶发问题。
如果一个智能体提交了一个 PR,里面居然把测试注释掉了,结果还被误合并了,这就是一个输入信号。下一版 AGENTS.md 里就必须明确写上:“绝不能注释掉测试;要么删除,要么修好。” 下一版 pre-commit 钩子应该自动检查 diff 里是否出现 .skip(。审查子智能体也必须更新成:一旦发现被注释掉的测试,就直接拦截。
约束只应该在你观察到真实失败之后才被加入,只有在模型确实足够强、已经不再需要时才移除。一个优秀系统提示词里的每一条规则,都应该能追溯到一次具体、历史上真的发生过的失败。
也正因为如此,Harness 工程是一种方法论,而不是一个一键套用的框架。针对某个特定代码库的正确 Harness,完全是由它独有的失败历史塑造出来的。
从目标行为反推设计
设计 Harness 最有效的方式,是先从你想要的行为出发,再去构建那个能交付这种行为的组件:我们想要什么行为 → 为了实现它,应该怎样设计 Harness。
Harness 里的每一个组件,都必须承担一个明确的职责。如果你说不清某个组件具体是为了交付哪种行为而存在,它就应该被删掉

基础。模型只能处理能塞进上下文窗口的内容。文件系统给智能体提供了一个可读写的数据工作区、一个可以卸载中间结果的地方,以及一个让多个智能体协作的共享表面。
再加上 Git,就等于自动获得了版本控制能力。智能体可以追踪进度、为实验开分支、回滚错误。
Bash 与代码执行:通用工具能力
大多数智能体运行在 ReAct 循环上:推理、通过工具调用采取行动、观察结果、然后重复。
与其为每一个可能动作都预先造好一个工具,不如直接给智能体 Bash 权限,让它在需要时自己搭出所需工具。
智能体通常非常擅长 shell 命令,所以 Bash 和代码执行天然就会成为默认的问题求解策略。
沙箱与默认工具集
只有在 Bash 能安全运行时,它才真正有用。沙箱为智能体提供了一个隔离环境,让它能运行代码、检查文件、验证结果,同时不影响宿主机。
一个好的沙箱还应该带有强默认配置:预装语言运行时、测试 CLI 和无头浏览器,让智能体能看到自己做出来的结果,并闭合“自我验证”这条循环。
记忆与搜索:持续学习
模型除了训练权重和当前上下文之外,并没有其他知识。Harness 会用记忆文件(例如 AGENTS.md)来弥补这个缺口,把相关知识注入到每一次会话中。
至于像库版本变更、实时数据这样的动态信息,网页搜索和 MCP 工具则会被直接内建进 Harness。
对抗上下文衰减
随着上下文窗口被不断填满,模型的推理质量会持续下降。Harness 通常通过三种主要手段来管理这种稀缺性:
上下文压缩: 智能总结并卸载较旧上下文,防止 API 报错。
工具调用卸载: 把巨大的工具输出(例如 2,000 行日志)存进文件系统,只把必要的开头和结尾留在上下文里。
渐进式披露: 只有当任务确实需要时,才暴露相应指令和工具,而不是一上来就把所有东西全塞进去。
长时任务执行
长时自主工作最容易出现的两个问题,是过早停止,以及糟糕的任务拆解。Harness 会通过结构设计来对抗这些问题:
循环守卫: 当模型试图退出时拦截它,并在新的上下文窗口里强制它继续围绕完成目标推进。
规划机制: 强制模型先把目标拆成逐步执行的计划文件,并在每一步之后通过自验证钩子检查结果。
职责拆分: 把“生成”和“评估”分配给不同智能体,避免模型在给自己打分时天然带有的正向偏置。
钩子是你的强制执行层
钩子负责弥补“请求一个动作”和“真正强制它发生”之间的距离。它们会在特定生命周期触发:工具调用前、文件编辑后,或者提交前。钩子可以阻止破坏性命令、自动格式化代码以节省 token,以及运行测试套件。
理想状态是:成功时保持安静,失败时提供足够详细的反馈。 如果类型检查通过了,智能体什么都不用听到;如果失败了,错误就要被直接注入回循环里,让它自己继续修正。
规则手册与工具选择
仓库根目录下那份朴素的 Markdown 文件,依然是杠杆最高的配置点。但它必须被当成 飞行员检查清单,而不是风格指南。 保持简短,并确保每一条规则都是被历史错误“挣”出来的。
同样的纪律也适用于工具。十个高度聚焦的工具,一定会胜过五十个功能重叠的工具。
更进一步说,由于工具描述本身会进入提示词,那些恶意或粗糙的外部集成(比如未经验证的 MCP 服务)甚至可以在智能体开始工作前,就把坏提示词注入进去。
生产环境里真正长什么样
我目前见过的、最清楚展示成熟 Harness 的公开案例,是 Fareed Khan 对 Claude Code 架构 的一份拆解(估计

的几乎每个概念,都能在这张图里找到对应的命名组件。图中的 Context injection 是知识层。Loop state 存在 memory store 和 worktree isolator 里。破坏性操作的钩子则被挂在 permission gate 后面。Subagent context firewalls 构成了整个多智能体层。Tool dispatch registry 是 MCP 服务和 Bash 接入的地方。Claude Code 的演进,至少有一半是在演进 Harness,而不仅仅是在演进底层模型。
Harness 不会消失,只会转移位置
随着模型能力提升,对 Harness 的需求并不会消失,只会发生迁移。
人们很容易以为模型变强之后,脚手架就会过时。例如,最近一轮模型升级,大幅降低了人们对“上下文焦虑”类缓解机制的需求。但地板抬高的同时,天花板也会抬高。以前根本做不到的任务,现在进入了可达范围,而这又会带来全新的失败模式。
Harness 里的每一个组件,本质上都编码了一个假设:模型凭自己还做不到这件事。当模型能力变强之后,过时的脚手架应该被拆掉,而新的脚手架则必须被造出来,用来抵达下一层任务边界。
那训练闭环呢?
Harness 设计与模型训练之间,其实存在一条活跃的反馈循环。
今天很多模型在后训练时,已经把特定 Harness 放进训练闭环中了,这会带来一定程度的过拟合。模型会在 Harness 设计者重点优化的那批动作上,变得特别强,比如文件系统操作、Bash 和子智能体调度。
这也说明,Harness 是一个活系统,而不是一个静态配置文件;同时也证