作者:Addy Osmani
编程智能体 = 模型 + Harness。 Harness 工程的核心理念,是将包围在模型外围的“脚手架”视为一种不断演进的生命体。
每当智能体出错时,我们要通过提示词、钩子(hooks)、工具、沙盒或子智能体,为其添加永久性的修复,确保它绝不再犯完全相同的错误。
一个还凑合的模型配上顶级的 Harness,能够完胜一个顶尖模型配上糟糕的 Harness。模型理论潜力与实际表现之间的鸿沟,很大程度上就是 Harness 的鸿沟。
设计 Harness 时,应从期望的行为结果倒推。每一个组件都必须能交付特定的结果,而组件的形态则是由项目过去的“失败教训”所塑造的。
随着模型的不断进步,Harness 并不会随之萎缩,而是会转移到新的约束条件和更高的视野上,逐渐演变成为类似“智能体编排编译器”的动态系统。
一个编程智能体,本质上是模型加上围绕它构建的所有配套设施的集合。Harness 工程将这套外围“脚手架”视为有生命力的产物——智能体每犯一次错,就将这套脚手架收紧一分。
简而言之:每当智能体失败时,你就要设计一个永久性的解决方案,让它再也不会犯同样的错误。
过去两年里,整个行业都在争论模型:谁最聪明、谁写的 React 代码最干净、或者谁的幻觉最少。虽然这些讨论很重要,但却忽略了系统的另一半。
模型仅仅是运行中的智能体的一个“输入源”。其余的部分全是 Harness:提示词、工具、上下文策略、钩子、沙盒、子智能体、反馈循环,以及包裹在模型外围、使其能真正完成任务的恢复路径。
优秀的 Harness 配上普通的模型,总是能击败糟糕 Harness 配上顶尖模型。越来越多最硬核、最有趣的工程工作,已不再是去挑选模型,而是去设计模型外围的这套脚手架。
这门学科现在终于有了一个名字。@Vtrivedy10 创造了**“Harness 工程(Harness Engineering)”**这个词,清晰地拆解了 Harness 到底是什么,以及其中每个部分存在的意义。行业中其他的声音也正在汇聚到大致相同的理念上:比如 @dexhorthy 在追踪行业涌现的新模式,HumanLayer 将智能体的失败归结为配置上的“技能问题(skill issues)”,Anthropic 工程团队发布了长生命周期应用的架构指南,Birgitta Böckeler 则深入探讨了用户侧体验。
这篇文章,正是为了将这些线索串联在一起。
Trivedy 的核心定义一语中的:
智能体 = 模型 + Harness。如果你不是模型,那你就是 Harness。
Harness 包含了所有非模型本身的代码、配置和执行逻辑。一个“裸模型”并不是智能体。只有当 Harness 为其提供状态管理、工具执行能力、反馈循环和强制约束时,它才真正成为一个智能体。
具体来说,Harness 包括:
CLAUDE.md、AGENTS.md、技能文件以及子智能体指令。智能体的核心本质,是一个循环运行工具以达成目标的系统。真正的技术壁垒在于如何设计这些工具,以及如何设计这个循环。
虽然这代表着一个极其庞大的接触面,但这完全是“你的”控制面,而不是模型提供商的。Claude Code、Cursor、Codex、Aider 和 Cline 本质上都是 Harness。它们跨平台的底层模型可能是一模一样的,但你所体验到的行为差异,完全是由 Harness 主导的。
当智能体做出荒谬的举动时,工程师往往习惯性地责怪模型,然后把问题束之高阁,指望着“等下个版本的模型发布”来解决。
Harness 工程的思维模式拒绝这种默认的甩锅行为。失败通常都是有迹可循且可被解析的。
AGENTS.md。正如 HumanLayer 所言:“这不是模型的问题,这是配置的问题。” 看看性能基准测试就明白了:同一个顶尖模型,在开箱即用的通用框架中运行,得分通常远低于在其深度定制、高度优化的 Harness 中的得分。将模型放入一个配备了更优代码库工具、更严谨提示词和更敏锐背压信号的环境中,能够解锁底层模型被原始环境所埋没的巨大潜能。
当今模型理论上能做到的,与你实际看到它们做到的,这二者之间的鸿沟很大程度上就是 Harness 的鸿沟。
在 Harness 工程中,最重要的习惯是把智能体的错误视为永久性的信号——而不是重试一次就抛之脑后的偶然偏差。
如果智能体提交了一个包含“被注释掉的测试用例”的 PR 并被意外合并了,这就是一个输入信号。
AGENTS.md 必须明确指出:“永远不要注释掉测试代码;要么删除,要么修复它。”pre-commit 钩子应该自动拦截代码 Diff 中的 .skip( 字符。只有当你观察到真实的失败时,才应该添加约束;也只有当更强大的模型让这些约束显得多余时,才应该移除它们。一个优秀的系统提示词中的每一行,都应该能追溯到一个具体的、曾经发生过的历史失败教训。
正因如此,Harness 工程是一门系统性的方法论,而不是一套万能模板。最适合某个特定代码库的 Harness,完全是由它独一无二的失败历史所“喂”出来的。
设计 Harness 最有效的方法,是从期望的行为出发,反向构建交付该行为的组件:期望的行为 → 实现该行为的 Harness 设计。
Harness 的每一个部分都必须有明确的职责。如果你说不清楚某个组件是为了交付什么特定行为而存在的,那就果断删掉它。
文件系统是根基。模型只能处理装得进其上下文窗口的信息。文件系统提供了一个读取数据的工作区、一个卸载中间工作成果的缓冲区,以及一个供多智能体协同交互的界面。
引入 Git 则提供了零成本的版本控制,允许智能体追踪进度、做分歧实验并在出错时回滚。
大多数智能体运行在 ReAct 循环(推理、行动、观察、重复)中。与其为每一种可以想象到的操作预先死磕出对应的工具,不如直接给智能体 Bash 权限,让它即兴动态构建自己需要的东西。
智能体通常非常擅长编写 Shell 命令,这使得 Bash 和动态代码执行成为了自主解决问题时的默认策略。
Bash 只有在安全运行的前提下才有用。沙盒为智能体提供了一个隔离环境来运行代码、检查文件并验证工作,且不会危及宿主机。
一个好的沙盒会自带强大的默认配置:预装语言运行时、测试 CLI 工具以及无头浏览器,让智能体能够观察自己的工作成果,完成“自我验证”的闭环。
除了预训练权重和当前上下文,模型本身没有额外的知识。Harness 通过“记忆文件”(如 AGENTS.md)来弥合这一短板,将知识注入到每一次会话中。
对于获取最新库版本或实时数据,网络搜索和 MCP 工具会被直接内嵌进 Harness 中以供调用。
当上下文窗口渐渐被填满时,模型的推理能力会显著退化。Harness 使用三种主要技术来管理这种稀缺资源:
全自动、长生命周期的任务经常饱受“过早停止”和“任务拆解不佳”的困扰。Harness 通过结构化设计来应对:
钩子弥合了“请求动作”和“强制执行”之间的鸿沟。它们运行在特定的生命周期节点:调用工具前、编辑文件后或提交代码前。钩子可以拦截高危的破坏性命令,强制自动格式化代码以节省 Token,以及运行测试用例。
理想状态是:成功时悄无声息,失败时信息详尽。 如果类型检查通过了,智能体什么也听不到;如果失败了,报错信息会被直接注入回循环中,触发其自我纠错。
代码仓库根目录下的那个极其简单的 Markdown 文件,依然是杠杆率最高的配置点。然而,必须把它当作飞行员起飞前的“检查单(checklist)”来对待,而不是一本长篇大论的代码风格指南。 保持简短,并确保其中的每一条规则都是靠过去的失败换来的。
同样的纪律也适用于工具。十个高度聚焦的工具,永远胜过五十个功能重叠的冗余工具。
此外,因为“工具的描述信息”也会占用提示词空间,恶意或草率的外部集成(比如未体验证的 MCP 服务器),甚至在智能体还没开始干活之前,就会向其注入一堆糟糕的提示词污染。
目前我所见过的展示成熟 Harness 全貌最清晰的公开图解,是 Fareed Khan 对 Claude Code 架构的(预估)拆解。
前文提到的几乎每一个概念,都在这张图上以具名组件的形式出现了。上下文注入构成了知识层;循环状态存储在内存库和工作树隔离器中;拦截破坏性操作的钩子藏在权限网关之后;子智能体的上下文防火墙构成了整个多智能体层;工具调度注册表则是 MCP 服务器和 Bash 的接入枢纽。
Claude Code 能取得今天的体验,至少有一半功劳要归于它底层模型外围的这套 Harness。
随着模型的不断进化,对 Harness 的需求并没有消失——而是转移了。
人们很容易想当然地认为,更聪明的模型会让这些“脚手架”变得可有可无。例如,最近模型能力的升级,确实极大地降低了我们去缓解“上下文焦虑”的需求。但是,随着能力下限的提高,上限也在随之提高。 以前遥不可及的复杂任务现在被提上了日程,这同时也带来了全新的、前所未见的失败模式。
Harness 中的每一个组件,都编码了一个关于“模型自身无法搞定什么”的底层假设。当模型进化时,过时的脚手架应该被拆除,但同时必须搭建全新的脚手架,以支撑我们攀登下一座高峰。
在 Harness 设计和模型训练之间,存在着一个活跃的反馈循环。
如今的模型在进行后训练(post-trained)时,通常会把特定的 Harness 纳入训练回路中,这甚至造成了一定程度的“过拟合”。模型会变得对其 Harness 设计者优先考虑的特定动作(比如文件系统操作、Bash 脚本编写、子智能体调度)极其擅长。
这使得 Harness 成为了一个有生命的动态系统,而非一纸静态配置文件。这也证明了,世界上“最好”的 Harness,永远是那个专门为你的独特任务和工作流深度定制优化的 Harness。
整个行业正在经历一次范式转移:从基于提供文本补全的 LLM API 进行构建,转向基于提供运行时的 Harness API(Harness 即服务)进行构建。现在的 SDK 已经开箱即用地打包了循环控制、工具链、上下文管理、钩子和沙盒。
现代的默认开发模式,不再是从零开始手写编排逻辑,而是直接选择一个 Harness 框架,配置好核心支柱,然后将全部精力纯粹地投入到领域特定的提示词和工具设计上。
正是这一点让故障排查具备了可扩展性:你是在调试一个结构清晰的配置面,而不是在重新发明整个智能体架构。
如果你观察当今最顶级的那些编程智能体,你会发现它们彼此之间的相似度,甚至远高于它们底层模型之间的相似度。 尽管底层模型百花齐放,但 Harness 的设计模式正在迅速趋同。整个行业正在快速达成共识,找出那些把“生成式文本”转化为“可交付软件”所不可或缺的承重脚手架。
最激动人心的前沿课题正在超越单一智能体的范畴:如何并行编排多智能体;如何让智能体自己分析执行轨迹,以修复 Harness 层面的失效;以及如何构建一个能根据需要进行 JIT(即时)动态组装工具的环境。
最终,在这个阶段,Harness 将不再是静态的配置文件,而是开始表现得更像是一个编译器。
如果你正在寻找一个出色的智能体 Harness 框架,@FredKSchott 编写了 Flue。它非常硬核,而且显然是受到了本文早期版本的启发!

扫码关注w3ctech微信公众号
共收到0条回复