Harness - 01 什么是 Harness Engineering

文章目录

什么是 Harness Engineering:一个词的诞生、分歧与边界

2026 年春天,一个英文词在开发者社区里忽然变得随处可见。二月初还只有零星几篇博客提到它,四月已经出现在各平台的技术帖、会议分论坛名称和招聘要求里。这个词是 Harness Engineering。

有意思的地方是,讨论它的人越多,它反而越难被讲清楚。有人译作"马具工程",有人译作"驾驭工程",有人说它是上下文工程的放大版,有人说它是软件工程思想在 AI 时代的回魂,还有人认定这又是一次新瓶装旧酒。顺着几篇不同作者的文章读下来,很容易越读越糊涂。更麻烦的是,同一时间还有一批相当有分量的声音在说:这件事被高估了,脚手架终究会被模型吃掉。

所以这篇文章不打算先给定义。定义是结论,来龙去脉才是理解的起点。一个术语为什么在某个时刻出现,是谁提出来的,它想解决什么问题,反对它的人在反对什么,它和已有概念的边界在哪里------这些问题搞清楚之后,"它到底是什么"反而变成一个顺带能回答的小问题。

一、词源:两个月里的四件事

讨论新术语,从时间线开始总是比较清醒的做法。

2 月 5 日:一个不太正式的命名

这个词的第一次正式亮相是 2026 年 2 月 5 日。HashiCorp 联合创始人、Terraform 作者 Mitchell Hashimoto 在个人博客发表了《My AI Adoption Journey》,记录自己这一年使用 AI 编码工具的完整过程。文章第五步里出现了这样一段话:

I don't know if there is a broad industry-accepted term for this yet, but I've grown to calling this "harness engineering." It is the idea that anytime you find an agent makes a mistake, you take the time to engineer a solution such that the agent never makes that mistake again.

值得注意的是这个命名有多不郑重。Mitchell 自己都说不确定业界有没有公认的说法,"如果已经有一个,我会跟着用"。真正被后来者反复引用的不是这个标签,而是后面那半句:每次发现 Agent 犯了一个错,就花时间设计一个解决方案,让它永远不再犯同样的错。

这个思路的出发点是效率而不是安全。Mitchell 的原话是 agents are much more efficient when they produce the right result the first time------Agent 一次做对的时候效率高得多。所以他最信任的手段不是把提示词写得更漂亮,而是"给 Agent 又快又好的工具,让它自动知道自己错了"。

文章里的例子相当朴素。一类是通过 AGENTS.md 做隐式提示:Agent 老是跑错命令、老是用错 API,就把正确的写进去。Mitchell 拿自己的终端项目 Ghostty 举例,指向 src/inspector/AGENTS.md,并加了一句很关键的说明------那个文件里的每一行都对应一次 Agent 的错误行为,而它几乎把这些行为全部消除了。另一类是真的写程序:截图脚本、带过滤的测试运行脚本,写完之后照例在 AGENTS.md 里加一行,让 Agent 知道这个工具存在。

把这两类做法放在一起看,能读出一个态度:Mitchell 花时间改的不是提示词,也不是模型权重,是工具、规则和脚手架。他不相信靠重写提示词能让模型变可靠,他相信的是补齐外围设施,让模型在犯错的路径上撞墙。

2 月 11 日:一份生产环境的实验报告

六天后,OpenAI 发表了一篇工程博客,标题直白得多:《Harness engineering: leveraging Codex in an agent-first world》,作者是技术团队成员 Ryan Lopopolo。

这篇文章的分量比个人随笔重得多,因为它报告的是一次有约束条件的真实实验:在过去五个月里,一个团队构建并交付了一个软件产品的内部 Beta 版,手写代码零行。产品有内部日活用户,有外部 alpha 测试者,会发布、会部署、会崩、会被修好。文章开篇给出的问题意识是------什么东西坏了,什么东西产生了复利,以及如何最大化团队唯一真正稀缺的资源:人的时间和注意力。

被引用最多的一句总结是 humans steer, agents execute,人来掌舵,Agent 来执行。围绕这个原则,文章列了一堆具体做法:AGENTS.md 怎么写(当作目录而不是百科全书,控制在很短的篇幅内),计划目录如何组织并纳入版本控制,工具如何暴露给 Agent,Git worktree 怎么用来做并行隔离,自定义 linter 如何在错误信息里直接嵌入修复指令,CI 如何充当 Agent 输出的质量闸门。

每一条单独看都不复杂,合起来指向同一个工程判断:让 Agent 真正干活的,不是模型有多聪明,而是模型外面那一整套架子有多结实。这篇文章也让 harness engineering 第一次走出小圈子------当人们想找一个完整案例来理解"到底什么叫 engineer the harness"时,终于有了一个可以指的东西。

3 月 24 日:把 harness 当作研究对象

一个半月后,3 月 24 日,Anthropic 发表了自己的版本,讨论长时运行 Agent 的 harness 设计(标题有《Effective harnesses for long-running agents》和《Harness design for long-running application development》两个版本)。

Anthropic 关心的是另一类问题:当你希望一个 Agent 连续工作好几个小时、跨越多个会话完成一个复杂任务,harness 要怎么设计才能让它不在中途崩掉。给出的答案是一套三代理架构,而且每个角色的边界都划得很细。

Planner 接收一句到四句话的输入,把它展开成完整的产品规格。提示词要求它野心大一点,但只停留在产品上下文和高层技术设计的层面,刻意避开细粒度的实现细节------因为早期的错误会向下游级联放大。在一次做复古游戏编辑器的运行里,它产出了一份横跨十个 sprint、包含十六个特性的规格。

Generator 按 sprint 工作,一次从规格里拿一个特性,技术栈是 React + Vite + FastAPI + SQLite(后来换成 PostgreSQL),有 git 可用,并且被强制要求在每个 sprint 结束、交给 QA 之前先自评一遍。

Evaluator 扮演 QA,通过 Playwright MCP 像真实用户一样点击运行中的应用,同时检查界面、API 端点和数据库状态,按发现的缺陷加上产品深度、功能完整性、视觉设计、代码质量几个维度打分。每个维度都有硬阈值,任何一项低于阈值就整个 sprint 不通过,并返回详细反馈。

这套架构里有几个细节比架构本身更有启发。

一是"完成"的定义要提前谈判。在写代码之前,Generator 和 Evaluator 要就"这个 sprint 做完是什么样"达成一致:Generator 提出它要构建什么、如何验证成功,Evaluator 审查是否忠于规格,双方来回迭代直到确认。仅关卡编辑器那一个 sprint 就谈出了 27 条验收标准。这一步把高层用户故事翻译成了可测试的行为。

二是缺陷报告的证据标准。要求是"不需要再做调查就能直接行动",必须带文件和行号以及具体修法。文章里给出的例子很具体:LevelEditor.tsx:892 的删除键处理同时要求 selectionselectedEntityId,而点击只设置了后者;PUT /frames/reorder 声明在 /{frame_id} 之后,导致 FastAPI 把 "reorder" 当整数解析并返回 422;一个 fillRectangle 函数存在但在 mouseUp 时从未触发。

三是验证者本身需要被调校。早期运行里出现过一种很典型的失败:QA 找到了真实缺陷,然后自己把缺陷合理化掉,最后照样批准通过。测试也停留在表面。解决办法是读 QA 日志,找出它和作者本人判断分歧的地方,然后反复改写 QA 的提示词,改了好几轮。视觉设计的评估者是另外单独校准的,用少量示例和分项打分来抑制漂移。

这篇文章里还有一句话后来被反复引用:

every component in a harness encodes an assumption about what the model can't do on its own

每一个 harness 组件都编码了一个关于"模型自己做不到什么"的假设。这句话提醒读者,harness 不是一劳永逸的架构,而是围绕模型当下能力边界搭起来的脚手架,每一根支柱都可能被下一代模型拆掉。Anthropic 自己给了一个例子:Sonnet 4.5 有"上下文焦虑",接近上下文上限时会提前收尾,所以他们加了上下文重置机制;换成 Opus 4.5 之后这个行为基本消失,重置就变成了纯粹的负担。

3 月 31 日:一次意外的教材公开

到了 3 月底,又一件事给这个词加了把火。

3 月 31 日,安全研究员 Chaofan Shou(@Fried_rice)发现 npm 上 @anthropic-ai/claude-code 的 2.1.88 版本存在构建配置失误:随包发布的 source map 文件指向了未混淆的 TypeScript 源码,而那份源码可以从 Anthropic 的 R2 存储桶直接下载。Claude Code 的完整实现就这样公开了。Ars Technica、The Register、InfoQ 等媒体当天到次日陆续跟进报道。

这件事对讨论质量的影响是决定性的。在此之前,关于 harness engineering 的交流大多停留在博客、推文和二手经验分享;在此之后,人们可以逐行阅读一个已经跑出巨大营收规模的生产级 Agent 系统内部到底长什么样:控制面在哪一层,主循环怎么运转,工具权限如何校验,上下文怎么压缩,错误如何恢复。这些问题突然有了可对照的答案。

四件事的时间密度本身就是一个变量。如果它们分散在一年里发生,每一件的影响力都会被稀释,这个词大概不会像现在这样集中爆发。

二、补考:问题意识比词早了一年

词源考古做到这里,事情似乎已经清楚了。2 月 5 日提概念,2 月 11 日用案例出圈,3 月 24 日给出进阶研究,3 月底源码公开推向高潮,一条整洁的时间线。

但只看这条线会漏掉一段更早的铺垫。

2025 年 3 月 24 日------比上面这条时间线整整早了一年------Latent.Space 发表了一篇题为《Agent Engineering》的文章,源自 swyx 在 AI Engineer Summit 上的主题演讲。文章处理的问题是"到底什么算 Agent":这件事上公开的秘密是没人达成一致,所以关于 Agent 的争论几乎无法进行,因为门槛可以被随意抬高或压低。为了让讨论有个共同底座,文章把各家定义收敛成六个要素,并用首字母凑了个缩写 IMPACT:

  • Intent(意图):怎么把用户意图编码进系统,包括多模态输入输出、目标的表达,以及在环境里跑 eval 来检验意图是否被满足。
  • Memory(记忆):长期记忆带来的连贯性和自我改进循环,可复用的工作流与技能库都算结构化记忆的一种。
  • Planning(规划):多步操作的拆解,文章把"可编辑的计划"列为当时的最佳实践。
  • Authority(授权):被委托的信任边界,文章称它是最被忽视的一项,并引了一句"如果没有信任,就没有 Agent"。
  • Control Flow(控制流):由 LLM 驱动的控制流,越 agentic 的应用,越多的控制流由模型决定。
  • Tools(工具):唯一没有争议的一项,检索、沙箱与画布、浏览器与计算机操作是三大类。

这六个维度和 2026 年那几篇 harness engineering 的核心议题几乎完全重合。Intent 对应指令设计,Memory 对应上下文与状态治理,Planning 对应任务拆解,Authority 对应权限判定,Control Flow 对应运行时主循环,Tools 对应工具系统。文章当时还把 OpenAI 官方 SDK 的定义缩写成 TRIM(tools、runtime、instructions、model)并批评它漏掉了记忆、规划和授权------今天回头看,被漏掉的那三项恰好是 harness 讨论最集中的地方。

这个前传说明的事情是:这个领域的问题意识早就酝酿好了,只是缺一个合适的时机、一个生动的词和一组具体案例。IMPACT 是一个准确但不上口的分类学,harness 是一个不那么准确但一看就懂的比喻,后者更容易在社区里长距离传播。Mitchell 那句 "engineer the harness" 之所以被放大,不是因为它比 IMPACT 更深刻,而是它抓住了一个好用的意象,而这个意象恰好出现在社区已经积累了足够多共识的那个节点上。

严格来说,harness engineering 不是哪个人或哪家公司的发明。它是社区在几乎同一段时间从不同方向逼近同一个问题之后形成的收敛点。Mitchell 的个人实践、swyx 的早期框架、OpenAI 的工程报告、Anthropic 的研究文章、Claude Code 源码的意外公开,共同构成了这个词的诞生环境。

这一点对理解后面的定义之争很重要。如果它是某家公司独立发明的概念,那么"正确解释"自然归这家公司所有;但它不是。它是一场群体性的命名,所以围绕它产生几种不同的理解口径,这件事本身就很自然。

三、三种解释口径

看下来,市面上关于 harness engineering 的解读大致可以归为三派。三派的差异不只是措辞,背后对"模型应该被怎样对待"这个问题有相当不同的立场。

马具派

来源很直观。harness 这个词本意就是马具、挽具,是人给马穿戴的那套装备。所以当 Mitchell 说 engineer the harness 的时候,字面上就能翻译成"好好打造你的那套马具"。马具派认为这个比喻已经足够说明问题:模型像一匹好马,力气大但不守规矩,harness 是给它穿上的装备,让骑手能够驾驭它。Opus 4.6、GPT-5、Gemini 3 这些顶级模型是赤兔马,Claude Code、Codex 这些系统是马镫和缰绳。同样的赤兔马,在会骑马的人手里是战神,在不会骑马的人手里是摔伤事故。

这个口径还有一个更中性的表述在社区里流传:harness 是"连接、保护并编排各个组件,但自己不做实际工作的那一层"。这句话的好处是它跨工程学科通用------线束、测试夹具、马具,在各自领域里都是这个意思。

马具派直观好懂,适合做比喻,适合写标题,适合向不熟悉 AI 的读者解释这件事在说什么。它的问题在隐喻本身带了一层被动意味:马是被驾驭的对象,harness 是约束它的装备。这层意味让一部分开发者不舒服,他们认为这种比喻暗示了一种压制模型潜力的态度。

工作空间派

这一派对"马具"那层被动意味有直接的反对意见。

核心主张是:harness 的目的不是限制模型能做什么,而是创造条件让模型做到原本做不到的事。一个没有合适工作环境的熟练工人做不出好活,原因不是能力不够,是没有趁手的工具、没有可靠的原材料、没有可参考的图纸、没有能反馈质量的检测工序。给他准备好这些东西是赋能,不是束缚。

这个视角下,harness engineering 的意义在于定义协作边界和协作协议,让模型能在一个稳定、可交互、可反馈的环境里持续工作。这一派通常会追溯到上下文工程的思路,认为 harness 本质上是"相关上下文"这一概念的延伸,回答的是同一个问题:怎样让模型在执行每一步的时候,都能拿到它需要的那部分上下文,既不多也不少。

好处是把关注点放回"让系统能做更多事"这个积极面上,和很多 Agent 产品构建者的直觉更贴合。风险是有时过于乐观,容易淡化一个事实------模型会犯错,而这些错误在 shell、文件系统和 Git 这些真实环境里会留下真实后果。

约束执行派

这一派在关于 Claude Code 实现的系统性研究里表达得最充分。

起点是一个冷峻的判断:模型是不稳定部件,甚至是整个系统里最不稳定的那个部件。人们喜欢把 Agent 想象成一个见习工程师,会写代码、会调工具、能在终端里独立工作,似乎只要再训练一下就能转正。但一旦它能接触 shell、Git、网络和本地文件,问题就从"它答得好不好"变成"它执行留下的后果谁来收拾"。

从这个视角出发,harness engineering 的意义很直接:一整套制度化的控制平面,用来处理一个现实问题------模型并不天然值得信任。所以 harness 的每个组件都不是装饰。system prompt 是行为协议,主循环是运行时心跳,工具 schema 是受管执行接口,上下文压缩是工作内存治理,权限是授权边界,hook 是生命周期钩子。它们合起来构成一个结构化的约束系统,把一个本质上不稳定的模型折进一套可持续运行的工程秩序里。

这一派的代表观点可以浓缩成一句话:代理系统的关键能力是约束执行。

三派的分歧其实是场合的分歧

三派并不矛盾,只是重心不同。马具派更关心"怎么描述这件事让别人听得懂";工作空间派更关心"怎么描述这件事让自己要建的系统更有野心";约束执行派更关心"怎么描述这件事让自己的系统不会在生产环境里翻车"。三种关心都合理,适用场合不一样。

写教程的作者用马具派的语言更容易开场。创业公司里从零搭 Agent 产品的工程师用工作空间派的语言更能向同事解释自己在做什么。在大厂负责一个已经跑在生产环境里的 Agent 系统的负责人,用约束执行派的语言更能说服管理层批准把时间花在那些"看起来像补丁"的基础设施上。

如果一定要选一种作为默认理解,我倾向于约束执行派。理由也很朴素:系统是给未来的自己写的,而未来的自己总会遇到今天还没看见的问题。面对未知故障的时候,一个明确的约束结构比一个漂亮的比喻管用得多。

四、反方意见:harness 会不会是一场误会

前面三派虽然吵,但有一个共同前提:harness 很重要。要把这个词理解到位,必须听一遍不同意这个前提的人在说什么。这部分讨论在中文社区里被引用得远远不够。

Latent.Space 后来专门写过一期讨论"harness engineering 是不是真的",把这场辩论概括成一个金融业的老问题:结果到底来自操作者的本事,还是来自他坐的那个位置。换到这里就是:Agent 的表现来自模型,还是来自模型外面那层脚手架?

怀疑一侧:脚手架终究会被吸收

最有意思的反对声音来自 Claude Code 团队自己。Boris Cherny 和 Cat Wu 都描述过 Claude Code 的 harness 是刻意做薄的------"所有的秘密都在模型里"、"这是最小化的做法"、"从设计上讲它就是最简单的那个东西"。Boris 还提到它随时间变得更简单,大约每三四周就被从头重写一遍,忒修斯之船式地换零件,因为模型很擅长写自己的工具。

这和"源码泄露揭示了一套复杂机器"的印象直接冲突,值得停下来想一想。我的理解是两件事都成立,只是在说不同的层:从架构意图上看,Claude Code 拒绝引入复杂的编排框架,坚持"一个主循环 + 一组工具"的朴素形态;但把可靠性所需的全部细节铺开------十种终止原因、压缩策略、权限校验、hook 生命周期------代码量自然不小。"简单"说的是结构,不是体量。

更硬的历史论证来自 Noam Brown。他的观察是:过去那些精巧的 agentic 脚手架,本来是为了从不具备推理能力的模型里硬套出推理,而推理模型出现之后,大量脚手架变得没有必要,甚至反而有害。他预期当下这批脚手架会重复同样的命运------最终被推理模型替换掉;同样的逻辑也适用于模型路由器,一旦有了统一的强模型,路由层就没有存在意义。

实证一侧的数据也不站在 harness 这边。METR 的测量发现 Claude Code 和 Codex 并没有跑赢一个基础脚手架。Scale AI 的 SWE-Atlas 显示,Opus 4.6 在 Claude Code 里相比通用 SWE-Agent 大约拿到 2.5 分的提升,而 GPT-5.2 的变化方向恰好相反------这个组合让人很难不得出"harness 的选择基本落在误差范围内"的结论。

顺带一个容易被忽略的细节:OpenAI 自己那篇 harness engineering 的文章,重点其实一直在强调上手有多简单,而不是这套东西有多深。

支持一侧:循环之外无产品

支持的一侧也有实打实的论据。

一种说法是"harness 就是产品本身":任何生产级 Agent 最终都收缩成同一个循环------执行工具、捕获结果、追加到上下文、再调用模型------而 Claude Code、Cursor 的 agent、Manus 全都活在这个循环里。有趣的是这个归约可以两头切:既能说明 harness 是全部,也能说明 harness 没什么内容。

Jerry Liu 的表述更直接:模型 harness 就是一切,从 AI 里拿到价值的最大障碍是你自己做上下文工程和工作流工程的能力,而且工具越横向通用,这一点越重要。2026 年 2 月还出现过一篇标题很有说服力的博客------《一个下午改进了 15 个 LLM 的编码能力,只改了 harness》,报告的是仅通过 harness 优化就取得的全面提升。

从产业层面看,Cursor 的估值和 AI Engineer 会议新增的 harness engineering 分论坛,也算是市场投出的票。

立场背后的利益,以及我的判断

这场辩论里双方的偏好都不难解释:做 harness 的公司卖 harness,模型实验室卖模型,而业界流行的"复合 AI 系统"框架恰好说两边都重要。文章里引了一位 AI 框架创始人在 OpenAI 活动上的私下感慨------"我甚至不确定这些人希望我存在"。

我认为这场分歧真正的分界线不在"harness 有没有用",而在讨论的是哪一类 harness。

针对模型具体弱点的临时补救,Noam Brown 是对的,它们会被吸收。让模型先列计划再执行、用少量示例压幻觉、为上下文焦虑加重置机制,这些东西的寿命都由下一代模型决定,Anthropic 自己就干净地承认过重置机制"已经变成死重"。

但另一类东西不会被吸收,因为它们要处理的不是模型的能力短板,而是模型的工作方式所决定的结构性事实。模型每次调用都是无状态启动,那么跨会话的状态就必须落在外面;模型自回归生成的本能是继续输出,那么停止判断就不该由它独占;模型只能看到环境的一个切片,那么全局一致性就得由别的东西来守;一个刚写完代码的模型对"这段代码好不好"的判断会被"这是我刚写的"强烈影响,那么验证就不该由实现者自评------Anthropic 那个"QA 找到真实缺陷又把它合理化掉"的例子,就是这条结构性事实的实验证据。

所以对同一件事可以有一个更精确的说法:会消失的是补丁,不会消失的是分工。一个例子是权限系统。它不会因为模型变强而消失,因为它编码的不是"模型判断力不够"这个假设,而是"某些后果不可逆"这个事实,而后者跟模型能力无关。

至于 METR 和 SWE-Atlas 那组数据,我倾向于把它理解成 benchmark 的可见性问题而不是结论。评测题目大多是单次、短程、有明确判据的任务,而 harness 主要在长程、跨会话、后果不可逆的场景里起作用。用一小时的题去测一套为十小时任务准备的机制,测不出差别是可以预期的。这不构成 harness 有效的证据,但它确实说明当前的评测手段还没有覆盖到 harness 声称的作用域。

五、和 prompt engineering、context engineering 是什么关系

厘清了立场,接下来该澄清边界。最容易和 harness engineering 混在一起的是两个已有词汇:prompt engineering 和 context engineering。

流传比较广的说法是把三者视为一个递进阶梯。

最早是 prompt engineering。那时候大家关心的是单次对话里怎么措辞才能让模型给出更好的输出:给模型一个角色,给它一组示例,给它一个输出格式。这些技巧在 GPT-3.5 和 GPT-4 早期确实有效,那个阶段的模型对提示词非常敏感,一个好的 prompt 能让结果从"勉强能用"变成"相当不错"。

第二个阶段是 context engineering。随着模型能力提升、任务变复杂,人们发现单纯改提示词已经不够,真正影响输出质量的是进入上下文窗口的那一堆 token 整体上是什么样:相关文档有没有,历史对话要不要压缩,工具描述怎么组织,外部知识怎么检索进来。Anthropic 在《Effective context engineering for AI agents》里给的定义比较清晰------在有限的上下文窗口里选择、组织并注入与任务高度相关的信息,让模型能在合理边界内做出最佳推理和执行。关注点从"这一句话怎么写"转向了"这一整窗内容怎么拼"。

第三个阶段是 harness engineering。关注点又往外扩了一层:不是单次对话,也不是上下文窗口本身,而是 Agent 的整个运行环境------工具、权限、状态持久化、错误恢复、多代理协作、验证机制、团队制度。它要求开发者对 Agent 能接触什么、能做什么、犯错时会怎样、跨会话如何保持一致这些问题做出显式的设计决策。

这个递进有一个朴素的直觉:模型越强,问题就越往外移。模型很弱的时候,写好一句 prompt 就能大幅改善结果;模型中等的时候,把上下文组织好才能让它发挥完整能力;模型已经很强的时候,决定成败的往往不再是模型本身,而是包裹模型的那套工程结构。

不过阶梯论也有值得保留的地方。把三者描述成"一代更比一代强",会掩盖它们之间的重叠和互补。prompt engineering 的原则没有过时,它只是变成了一个更大系统里的子模块------harness 里的每个组件都依然依赖好的 prompt 和好的上下文选择,Anthropic 花好几轮调校 QA 提示词就是最好的例子。这三件事更像同一栋建筑的三层楼板,而不是接力赛里的三棒选手。

社区里还流行一个简短的公式:

复制代码
Agent = Model + Harness

按这个公式,一个裸模型只是一个概率生成器,被 harness 包裹之后才能称作 Agent。harness 提供状态、工具执行、反馈闭环和可以被强制执行的约束,这些东西加起来,让一堆 next-token prediction 变成一个能独立完成任务的系统。

公式虽然简单,它解释了一件常被忽略的事:Agent 不是一个模型类别,而是一种系统形态。同一个模型,放在 Claude Code 里和放在一个简陋脚手架里,行为表现可以差得很远。差距不在权重,在 harness。

六、harness 的器官系统

概念关系理清之后,下一个自然的问题是:一个 harness 具体包含哪些东西?不同作者的列法略有出入,但把几篇有代表性的文章对齐看,会发现大家其实在同一套器官系统上打转。

system prompt 与指令分层

这不是传统意义上"你是一个有帮助的助手"式的人格设定,而是一套分层的运行时规章。Claude Code 的 system prompt 被拆成多段:身份与总任务一段,工具与权限说明一段,工程约束(不要越权、不要谎报验证、不要为了省事发明抽象)又一段。这些段落还要按优先级组装------默认 prompt、自定义 prompt、agent prompt、追加 prompt,每一层都有清楚的覆盖关系。

把 prompt 当作控制面的一部分而不是一段文字魔法,是 harness engineering 和传统 prompt engineering 的一条明确分界。同一句"不要跳过测试",写在人格段里和写在工程约束段里,被遵守的概率并不一样。

query loop:运行时主循环

Agent 不是请求-响应式的问答系统,而是一段持续运行的循环。Claude Code 的核心不是某一次 API 调用,是一个带状态的循环体:消息列表、工具使用上下文、压缩跟踪、轮次计数、状态转移。每一轮执行留下的状态会进入下一轮,系统要在这个循环里持续处理消息裁剪、工具结果预算、压缩、中断和恢复。

主循环最能体现 harness 的性质的地方是终止条件。一个成熟的循环不会把"什么时候停"交给模型,而是在运行时定义一组外部条件,任何一个被触发都结束循环:

复制代码
任务完成信号     模型可以参与,但不是唯一来源
token 预算耗尽   由运行时统计,不依赖模型自觉
最大轮次达到     防止在同一处打转
工具连续失败     连续 N 次失败视为路径不通
用户打断         保存状态后退出
hook 阻塞        外部检查未通过
超时熔断         挂死保护

没有这个循环,所谓 Agent 就只是一个带工具的 chatbot。

工具系统

工具包括本地函数调用、Skills、MCP server、外部 API。在 harness 的视角下,工具不是模型能力的自然延伸,而是需要被调度、被授权、被限制并发、被审计的受管执行单元。

Claude Code 会根据工具的 schema 判断它能否并发执行,会对高风险工具(比如 Bash)施加高密度的行为规约,会把执行前的权限询问做成一个独立阶段,而不是一次随手的检查。工具描述本身也是 harness 的一部分------描述写得含糊,模型就会在错误的时机调用它,这类问题改提示词往往没用,改工具描述立刻见效。

上下文治理

包括工作记忆、长期记忆、压缩策略、会话状态的跨轮维护。对话变长、工具输出变多、子任务变复杂的时候,上下文一定会膨胀,系统必须有明确策略决定什么该留下、什么该压缩、什么该丢弃,以及压缩时如何保住继续工作所需的语义底座。

Anthropic 把这件事叫 context compact。它不是可选优化,而是长时运行 Agent 能不能活下去的关键器官。值得一提的是他们发现压缩并不总能替代重置:压缩不提供干净的起点,所以在模型有上下文焦虑的那个阶段,他们宁可清空窗口、用一份结构化的交接文档带着状态重新开始。

权限与沙箱

这一层决定模型犯错时会留下多大的后果。是让它直接在宿主机上跑,还是在容器里跑;是让它自动执行所有 shell 命令,还是对高危命令弹确认;是允许它访问任意路径,还是把它限制在项目目录内。

Codex 在这一点上走得更远,把审批和执行限制做成了一个独立的 crate,里面有 Policy、Rule、Evaluation、Decision 等概念,已经接近一门小型的策略语言。而在使用侧,这一层通常表现为一份很朴素的配置:

json 复制代码
{
  "permissions": {
    "allow": ["Bash(git:*)", "Bash(npm:*)"],
    "deny": ["Bash(rm -rf:*)", "Bash(sudo:*)", "Edit(.env)", "Edit(.env.*)"]
  }
}

这几行和写在指令文件里的"请不要修改 .env"有本质区别:后者是劝告,模型可能记得也可能漂移;前者是机制,模型连调用那个工具的机会都没有。

错误恢复

这个器官最常被忽略。很多传统软件把失败当异常处理,Agent 系统不能这样做。对 Agent 来说,失败是日常天气:模型会超 token,会触发 prompt too long,会撞上输出上限,会遇到工具拒绝、用户打断、hook 阻塞、API 重试。

一个成熟的 harness 必须把这些失败路径当主路径来设计,预先定义好截断后如何续写、压缩失败时如何让系统恢复呼吸、死循环出现时如何熔断。判断一个系统成熟度的一个快捷方式,就是看它对"失败"的定义有多清楚:失败在这里是一种意外,还是一个被命名和分类的正常阶段?

多代理编排与验证

一个任务如果需要拆解、研究、实现、验证四个阶段,系统该怎么组织?是让同一个 Agent 跑完全部,还是让不同角色各司其职?

多代理不等于更好,Anthropic 自己也引用了"先找最简单的方案,只在需要时增加复杂度"这条原则,并且在第二版里砍掉了 sprint 划分,让构建者连续跑了两个多小时。但验证环节是个例外。一个实现者天然倾向于相信自己的改动"差不多行了",模型更是如此,所以比较稳妥的做法是让验证成为独立阶段,最好由独立角色承担,并且给它可执行的证据标准------带文件行号、带具体修法、不需要再调查就能行动。

本地规则与 hook

这包括 CLAUDE.mdAGENTS.md 这类项目级配置文件,也包括 pre-commit、session-start、subagent-context 这类生命周期钩子。它们的作用是让组织习惯能够被写进系统:新来的开发者不用重新学一遍这个项目的规矩,每次对话都能自动带上项目的上下文约束。

Mitchell 那句关于 Ghostty 的说明是这一层最好的注解------文件里的每一行都对应一次真实的错误行为。反过来说,一份没有任何错误行为作为来源的规则文件,通常也没什么约束力。

它们是一个循环,不是一张清单

这八个器官不是彼此独立的模块。prompt 定义行为协议,主循环负责执行,工具系统决定能触碰什么,上下文治理决定记忆如何流动,权限决定错误后果的范围,恢复机制处理错误本身,多代理把不确定性分区,本地规则把经验沉淀下来。少了任何一个,系统在某个方向上就会漏风。

比较常见的失衡是只做前三个:写一份很长的指令文件,接好一堆工具,然后指望模型自己撑住长程任务。这样的系统通常能演示得很漂亮,撑不过第一次真实的长跑。

七、三层划分:通用、项目、任务

列出八个器官还不足以让这个概念落地。因为同样是"工具系统"这一个器官,它到底该由使用者自己构建还是由 Agent runtime 提供,答案取决于你站在哪一层看。

社区里有一个相当实用的划分,按与具体项目的关联程度把 harness 分成三层。

层次 与项目的关系 典型内容 谁在做
通用 harness 弱相关 终端交互、主循环、权限系统、记忆、会话持久化、上下文压缩、hook 机制、任务调度 Anthropic、OpenAI、OpenCode 等
项目 harness 强相关,但不是业务功能 指令文件、仓库知识布局、架构边界、lint 规则、质量标准、依赖选择原则、文档索引 开发者自己
任务 harness 与当前这次工作相关 三代理架构、跨会话交接文档、针对特定任务的 QA 提示词、Playwright 检查脚本 开发者临时搭建

通用层对绝大多数开发者来说不需要自己动手,选一个合适的工具就行。在这一层做贡献的是基础设施公司和开源项目。

项目层是开发者真正要操心的地方,也是"我的项目要不要做 harness engineering"这个问题的主战场。OpenAI 那篇 Codex 工程报告里最有参考价值的经验大部分集中在这一层:指令文件当作目录而不是百科全书、架构不变量通过自定义 linter 强制执行并把修复指令写进错误信息、执行计划视为一流工件并把活跃计划和已完成计划都纳入版本控制。

任务层往往是临时搭起来的,完成之后可能就拆了。它的意义在于为一次特别重要或特别复杂的工作提供额外支架,而不是作为长期基础设施存在。Anthropic 那套三代理架构就是典型的任务层产物------他们自己也说,评估者不是永久设施,只有当任务超出模型独立可靠处理的范围时它才值那份成本,而这条边界会随每一代模型向外移动。

这个划分的实用价值在于帮开发者快速定位自己该操心什么:通用层已经由工具提供,任务层是一次性的,长期值得投入的是项目层。它还能防止一种常见误解------以为写了一份 CLAUDE.md 就等于做了 harness engineering。那只是项目层的入口,它解决不了通用层的运行时问题(那是工具的职责),也替代不了任务层的具体编排(那是具体活儿的职责)。

八、为什么是 2026 年初

到这里,来龙去脉基本讲完了。还剩一个值得讨论的问题:为什么是 2026 年初?为什么不是 2024 年,也不是 2027 年?

偶然的部分前面说过了,是四个标志性事件的时间密度。必然的部分更值得说:AI coding 领域的主要矛盾变了。

2023 年到 2024 年初,模型能力还没到让人放心的水平。写代码经常写错,上下文理解经常跑偏,工具调用经常失败。那个阶段开发者关心的是"模型到底能不能用",讨论集中在模型本身和提示词技巧上:怎么让 GPT-3.5 给出更靠谱的答案,怎么让 GPT-4 理解一个大文件,怎么用少样本示例降低幻觉。prompt engineering 是主要话题,因为模型本身是瓶颈。

2024 年下半年到 2025 年,情况开始变化。Claude 3.5 Sonnet 这类模型在多文件编辑、代码理解、长上下文方向上明显跨过了一道坎,AI IDE 开始实用化,Vibe Coding 这个词开始流行。关键问题变成了"怎么把合适的信息喂给模型",讨论集中在上下文管理:怎么做检索,怎么建知识库,怎么组织大型仓库的索引。context engineering 成为主要话题,因为上下文拼装是瓶颈。

2025 年底到 2026 年初,又一道坎被跨过。这一代模型的能力已经足够强,强到单次推理的质量不再是主要瓶颈。开始出问题的地方变成了长期运行中的系统性失败:Agent 能写出很好的代码,但会修一个 bug 引入另一个;它能写很长的代码,但会在半路把上下文耗光;它能执行复杂任务,但会在两次会话之间丢掉所有状态;它能给出漂亮的验证报告,但会把自己的实现判为通过。这些问题不是提示词能解决的,也不是靠堆上下文能解决的。它们需要运行时纪律、制度化的约束、外部验证和跨会话的状态管理。

主要矛盾从"模型够不够聪明"变成了"系统能不能让聪明的模型稳定地做事"。harness engineering 在这个时间点爆发,是因为社区终于有了一个共识:瓶颈已经不在模型一侧。

这里还有一层不太直观但很重要的推论。能力弱的模型造成的破坏是局部的、容易被察觉的------代码通不过编译,回答明显离题,工具调用报错。能力强的模型造成的破坏是系统的、难以察觉的------写出看起来没问题的代码但引入了隐蔽的竞态条件,做出看起来很合理的架构决策但违反了项目里一条它不知道的约束,在一个小任务里顺手重构了整个模块而每一行改动单看都是改进。弱模型让你在第一分钟就发现它不行,强模型让你在一周后才发现它做了什么。

所以从 Sonnet 3.5 时代到 Opus 4.6 时代,围绕主流 Agent 工具的 harness 没有变薄,反而变厚了:主循环更复杂,权限策略更细,压缩机制更成熟,hook 系统更丰富。如果 harness 只是能力补丁,模型变强本该让补丁变少。实际情况正好相反,因为这辆车跑得比以前快得多,刹车反而更重要。

九、harness 自己也开始被抽象

如果把观察窗口从春天往后延一点,会看到一个新趋势,它对理解这个词的未来形态很关键。

2026 年 4 月 8 日,Anthropic 发表了《Decoupling the brain from the hands》。文章的出发点还是那句老话------harness 编码了关于模型做不到什么的假设,而这些假设会随能力提升而过时。上下文重置那个例子被再次拿出来复盘:换到 Opus 4.5 之后,"这些重置已经变成了死重"。

但结论不是"所以别搭 harness",而是别把赌注押在某一个具体 harness 上。他们的做法是把长时任务托管化,暴露一组"意在比任何具体实现活得更久"的接口,并把系统切成三个可替换的部件:

  • Session :一份存在于 harness 之外的追加式事件日志,通过 getEvents() 查询。它让持久上下文和模型的上下文窗口分离,于是压缩和裁剪的决策不再是不可逆的。
  • Harness(大脑) :无状态,可通过 wake(sessionId) 重启,通过 emitEvent 写入。
  • Sandbox(双手) :只作为一次工具调用被触达,execute(name, input) → string,于是容器从需要精心照料的宠物变成可丢弃的资源。

他们给的类比是操作系统把硬件虚拟化成进程和文件这两个足够通用的抽象------"抽象活得比硬件更久"。立场也说得很清楚:对这些接口的形状有主见,对接口背后跑什么不持立场。

这套改造带来的收益是可量化的:把 harness 从容器里拿出来之后,"所有资源都在它旁边"这个假设消失了,客户自有网络环境的场景被解锁;容器按需惰性创建,首 token 时间的 p50 下降约 60%,p95 下降超过 90%。凭据也移出了生成代码的可达范围------Git token 在初始化时接到远端配置里,MCP 的 OAuth token 放在代理背后的保险库里,于是提示注入拿不到它们。

这件事对"什么是 harness engineering"这个问题的意义在于:这个词指的对象正在分层。手工搭建的那部分会持续被平台吸收,就像当年每个程序自己管内存的做法被操作系统吸收一样。但被吸收不等于消失------职责还在那里,只是从每个开发者的项目里搬到了平台的接口后面。你不再需要自己写会话持久化,但你仍然需要决定什么进 Session、什么算完成、哪些命令允许在 Sandbox 里执行。

十、一个克制的定义,和三个常见误解

回到开头那个问题:harness engineering 到底是什么?

铺垫到这里,可以给一个比较克制的回答。它是一个在 2026 年初由 Mitchell Hashimoto、OpenAI、Anthropic 和社区共同催生的工程术语,问题意识至少可以追溯到 2025 年 3 月 swyx 的 agent engineering / IMPACT 框架。它关心的是模型外围那一整套运行结构:system prompt 与指令分层、运行时主循环、工具系统、上下文治理、权限与沙箱、错误恢复、多代理编排与验证、本地规则与 hook。这些东西合起来决定了一个 Agent 系统能不能从"可以演示"走到"可以交付"。

如果要用一句话概括它在做什么:harness engineering 不是在补模型的能力短板,而是在承担模型的工作方式决定了它不该承担的那部分职责。前半句会随模型进步而失效,后半句不会。

最后说三个在传播中反复出现的误解。

误解一:harness 等于一堆配置文件。 判断一个系统有没有 harness,不能靠数配置文件、数 MCP server、数指令文件的行数。一个项目可以有一份写得漂漂亮亮的指令文件而完全没有 harness,另一个项目可能没有指令文件但有扎实的 harness。真正能判断的是三个问题:这个系统对"失败"的定义是什么;它的停止条件写在哪里;它的状态持久化在哪里。三个问题都能给出清楚答案的系统,是一个承认了职责划分的系统;有任何一个答不上来的,是一个还在依赖模型自觉的系统。

误解二:模型变强,harness 就会消失。 会消失的是补丁,不会消失的是分工。上下文重置机制这种针对具体行为缺陷的补救会被下一代模型抹掉,Anthropic 自己就干脆地承认过;但权限边界、状态持久化、独立验证不会,因为它们编码的不是"模型判断力不够",而是"后果不可逆"、"调用是无状态的"、"实现者不能自评"这类跟能力无关的事实。没有人会说等 CPU 变强就不需要操作系统了,那件事不会发生,因为它从一开始就不是那个问题。

误解三:harness 越厚越好。 这是被前两个误解带出来的过度修正。每一个组件都编码了一个假设,而假设会过时,所以 harness 需要定期审计而不是只增不减:跑了半年之后回头看,有多少条规则还记得为什么存在?Claude Code 团队每三四周重写一遍 harness、Anthropic 在第二版里砍掉 sprint 划分、"先找最简单的方案再增加复杂度",说的都是同一件事。一套没人敢删东西的 harness,已经从助力变成了负担。

理解到这一步,"它到底是什么"就不再是关键问题了。更值得问的是那个更具体的问题:在你自己的项目里,哪些职责现在还压在模型身上,而它其实不该承担?这个问题的答案,才是你的 harness 该长什么样。

参考资料

相关推荐
一个处女座的程序猿13 小时前
Agent之Harness:deepseek-harness的简介、安装和使用方法、案例应用之详细攻略
deepseek·harness
aimmon14 小时前
DeepSeek Harness 初探:1、一切皆插件的 Agent 框架
二次开发·ai大模型·deepseek·harness
小马过河R15 小时前
Graph Engineering 深度解析:模型越强,越需要给它画好“地图”
人工智能·langchain·graph·ai工程化·harness·驾驭工程
墨心@15 小时前
阶段 4:事件总线
人工智能·语言模型·大语言模型·agent·codex·harness
skywalk816316 小时前
硬核移植实录:在 FreeBSD 15.1 上从零跑起 DeepSeek 智能体 harness(附完整踩坑手册)
人工智能·freebsd·deepseek·harness
小小工匠17 小时前
Harness - 03 怎么做 Harness Engineering
harness
也非非也18 小时前
DeepSeek 又开源了一个新东西——DeepSeek Harness
人工智能·开源·agi·deepseek·harness·dsh
特立独行的猫a1 天前
一切皆插件:DeepSeek Harness 的架构哲学,以及与主流 Agent 的对比
人工智能·架构·agent·deepseek·harness
兮动人1 天前
DeepSeek 把模型的“马具“开源了:拆解 Harness
gpt·deepseek·harness·dsh