Harness Engineering:把会写代码的模型,变成真正能交付的软件系统

引子:AI 编程的分水岭,不是会不会写代码,而是能不能持续交付

过去一年,AI 编程最迷人的一幕,通常发生在演示视频的前两分钟。

你说一句“做一个 Notion 风格的笔记应用”,模型立刻起手一个漂亮首页;你再补一句“加上登录、搜索和评论区”,它继续往前冲,像一位不知疲倦、态度极好的初级工程师。于是很多人自然得出一个判断:既然模型已经会写代码,软件工程的核心问题似乎只剩下“把需求说清楚”。

这个判断只对了一半。

模型确实越来越会写代码,但真正的软件工程从来不是“写出第一版代码”。真正困难的部分是:需求会变,代码会腐烂,系统会积累历史包袱,团队会分工,权限会分层,线上会出事故,昨天的正确会变成今天的 bug,今天的最优解会变成三个月后的技术债。

一句话做出一个 demo,不等于一句话维护一个系统。

OpenAI 在关于 Codex 的几篇工程文章里反复强调一件事:当智能体开始承担真实的软件交付工作后,人类工程师的主业就不再只是敲代码,而是设计环境、明确意图、建立反馈回路,并把应用、日志、指标、协议和文档变成智能体可以理解、操作和验证的系统。Anthropic 对长时运行智能体的研究也指向同一个结论:如果没有初始化脚手架、进度制品、会话交接、评估器和更严格的上下文工程,模型很容易在长任务中迷路、烂尾,或者更危险地,在一种看似自信的状态下,把错误带进生产环境。

这就是 Harness Engineering 的起点。

它不是一个时髦名词,也不是“给模型套个壳”。它更像一整套工程约束系统:把概率性的模型输出,转译成长期、可靠、可验证、可审计、可回滚的软件交付流程。

从 one-shot generation 到 continuous delivery 的工程断层

图 1:真正的工程难点,不在“生成第一版”,而在把第一版安全地接入长期运行的系统。


一、真正的断层:模型按会话工作,工程按系统运行

理解 Harness,最好不要从 Prompt 开始,而要先承认一个现实:大模型面对的不是“写代码”这个单点任务,而是在一个有状态世界里连续做对很多件事。

这中间至少有四道断层。

1. 时间断层:模型按窗口工作,项目按周和月生长

模型天然以会话为单位工作。哪怕上下文窗口再大,它也不等于“持续记忆”。Anthropic 在长时运行智能体的实验里观察到,模型跨越多个上下文窗口后,会出现一些典型失效模式:

  • 想一次做完太多,结果在半路耗尽上下文。
  • 留下一半实现、一半猜测的现场,让下一轮继续接锅。
  • 看到项目里已经“有些东西能跑”,就误判为任务完成。

这很像轮班交接。一个工程师下午六点下班,另一个工程师晚上九点接手,如果没有清晰的任务列表、状态记录、运行脚本和提交历史,第二个人不是在开发,而是在考古。

所以 Harness 的第一层价值,不是“让模型更聪明”,而是让它每次醒来都知道自己在哪、上一轮做了什么、这轮该推进什么、结束时要把现场收成什么样子。

2. 状态断层:模型是概率机器,生产系统是确定性机器

模型靠分布生成下一个 token,生产系统靠约束维护状态一致性。这两者并不天然兼容。

银行转账不是“差不多成功”;权限模型不是“八成没问题”;订单履约不是“页面上看起来像已经提交”。模型可以在语言上非常流畅,但只要它对真实系统状态的理解稍微偏离,输出就会从“效率工具”滑向“事故源”。

因此,Harness 必须建立边界:

  • 哪些文件能改,哪些不能改。
  • 哪些工具能用,哪些需要审批。
  • 哪些状态能写,哪些只能读。
  • 哪些结果可以直接合并,哪些必须经过验证。

换句话说,Harness 不是模型的装饰物,而是它进入真实系统时的物理边界

3. 验证断层:生成越来越便宜,证明正确仍然很贵

今天的大模型生成代码越来越便宜,但验证并没有同步变便宜。

真正昂贵的不是“写一个新功能”,而是回答下面这些问题:

  • 这个功能有没有破坏旧逻辑?
  • 页面是不是只是“长得像可用”,其实关键流程点不动?
  • 日志和指标是否暴露了性能退化?
  • 智能体是否在用一种危险但暂时没炸的方式工作?

OpenAI 在 Codex 的内部工程实践里,把应用 UI、Chrome DevTools、日志、指标和 trace 变成对智能体可读的对象;Anthropic 在应用开发 harness 中,则用生成器加评估器的方式逼迫模型接受外部批改,而不是自我陶醉式地宣布胜利。

这说明一个残酷但重要的事实:

在 AI 软件工程里,真正值钱的不是“让模型干活”,而是“让模型有资格说自己干完了”。

4. 熵增断层:代码库会学坏,智能体会复制坏习惯

只要代码库里已经存在坏模式,智能体就会继续复制它。只要文档过时、目录混乱、命名漂移、脚手架不一致,模型就会在更高吞吐下把这些问题成倍放大。

OpenAI 在 agent-first 的工程实验中提到,他们最后不得不把“黄金规则”编码进代码库和 lint,把文档维护、质量评分、结构校验和后台重构做成持续运行的清理循环。原因很简单:没有垃圾回收的智能体代码库,不会自然收敛,只会越长越乱。

Harness 在这里扮演的,就是工程领域的垃圾回收器。


二、Harness 到底是什么:不是外壳,而是控制系统

如果只用一句话来定义,我会这样说:

Harness Engineering 不是让模型多会一点,而是让模型在一个长期运行的工程系统里,知道怎么开始、如何推进、用什么边界、按什么标准结束,并在失败时可以被拉回来。

它至少包含六层。

1. 上下文层:给模型地图,而不是给它一座档案馆

OpenAI 的一个关键经验是:不要把 AGENTS.md 写成百科全书,而要把它写成目录。真正的知识应分散在结构化文档、产品规格、架构说明、执行计划、技术债记录、设计参考和自动生成的 schema 中。

这件事的本质是:

  • 模型不怕信息少,怕的是信息乱。
  • 模型不怕文档短,怕的是不知道去哪找真相。
  • 模型不怕逐步读取,怕的是一上来就被灌一千页陈旧说明书。

好的 Harness 会把“上下文工程”做成可导航系统,而不是一次性大灌输。

2. 执行层:让模型有手,但不要让它乱伸手

真正能工作的智能体,不只是会回答问题,还要能做事:读文件、跑命令、看页面、启动服务、调用工具、发起 PR、读取日志、生成补丁。

但“能做事”不等于“什么都能做”。所以执行层要同时解决两件事:

  • 给模型足够强的执行能力。
  • 给这份能力加上沙箱、协议和审批。

Anthropic 的工具设计文章里反复强调,工具要命名清晰、描述明确、返回足够上下文但不浪费 token;OpenAI 的 App Server 则更进一步,把线程、轮次、项目、审批、流式消息和工具执行都规范成协议原语。这意味着“智能体做事”不再是一团魔法,而是一条可以被 UI、IDE、CLI、桌面应用共同复用的可观察链路。

Harness 六层结构图

图 2:Harness 不是单个脚本,而是一条从意图到交付的分层工程链路。

3. 计划与交接层:让每一轮都像一位守纪律的接班工程师

Anthropic 给出的一个很有启发性的实践是:

  • 第一轮不是直接开发,而是初始化。
  • 初始化智能体先建立 init.sh、进度文件、功能列表、初始提交。
  • 之后每一轮编码智能体只做增量推进,并留下结构化状态。

这其实是在把“工程项目的组织纪律”显式写给模型:

  • 先盘点。
  • 再选择单个目标。
  • 做完留痕。
  • 交接要干净。

没有这一层,长任务就会退化成一连串临场发挥。短期看很热闹,长期看很难收敛。

4. 验证层:把“我觉得差不多了”变成“证据显示可以合并”

这是 Harness 最容易被低估,也最决定成败的一层。

验证不只是跑单元测试。真正有效的验证层至少包括:

  • 单元测试与集成测试
  • 端到端浏览器验证
  • 结构化评估 rubric
  • 回归检查
  • 性能或稳定性基线
  • 人类审批点

Anthropic 在前端设计与全栈应用 harness 里,明确把生成器和评估器拆开,就是因为模型对自己的产出往往过于宽容。OpenAI 则通过让 Codex 直接读取 DOM、日志、metrics 和 traces,把“验证工作”本身也纳入智能体的可操作范围。

换言之,Harness 的目标不是让错误永不发生,而是让错误更早暴露,并更便宜地被纠正。

5. 观测与治理层:让智能体在越界之前就被看见

如果系统要跑上数小时、数天,甚至多智能体并行,那么“可观察性”就不再是运维团队的额外选修课,而是智能体工程的主干。

你至少要知道:

  • 它正在做什么。
  • 为什么卡住。
  • 哪个工具调用失败。
  • 哪一步最耗时。
  • 哪段流程反复返工。
  • 哪次审批最常被拒。

同时,治理也必须同步存在:

  • 命令是否需要审批。
  • 哪些命令可自动放行。
  • 哪些仓库允许自动合并。
  • 单次运行预算是多少。
  • 什么情况下必须交给人工。

没有治理的智能体不是自主,而是失控。

6. 熵管理层:定期清理,胜过一次大修

这是很多团队最晚意识到、却最难补上的一层。

当智能体产能提升之后,代码库会以惊人的速度积累“看起来没坏、其实很脏”的东西:

  • 重复 helper
  • 风格漂移
  • 命名失真
  • 过期文档
  • 目录膨胀
  • 奇怪的粘合层

OpenAI 把这件事叫作垃圾回收。这个比喻很准确,因为技术债在智能体时代不再只是线性增长,而会被高吞吐放大。你不定期清理,它就会变成后续所有生成的训练现场。


三、什么时候需要 Harness,什么时候不要过度设计

并不是所有任务都值得上复杂 Harness。

这是一个常见误区:看到“多智能体”“长时运行”“规划器/评估器”,就觉得越复杂越先进。恰恰相反,Anthropic 和 OpenAI 的经验都指向同一个原则:先用最简单的系统解决问题,只有在失败模式稳定出现时,才增加结构。

可以把任务分成三类。

第一类:一次性生成任务

例如:

  • 生成一个落地页
  • 写一个小脚本
  • 做一个静态 demo
  • 生成邮件模板或 SQL 查询

这类任务主要追求速度,不一定需要复杂 Harness。单智能体加基本工具,再做一次验证,往往就够了。

第二类:短周期可回滚任务

例如:

  • 给现有项目加一个明确功能
  • 修一个定位清晰的 bug
  • 做一轮限定范围的重构

这时候你需要最小 Harness:

  • 读 repo
  • 写 patch
  • 跑测试
  • 看 diff
  • 留提交记录

如果团队还没有形成文档地图、目录边界和基础验证,问题会开始出现,但通常还没到灾难级别。

第三类:长时运行的产品级任务

例如:

  • 连续数天迭代一个新产品
  • 在老系统上持续引入智能体协作开发
  • 让模型自主推进前端、后端和评估
  • 多智能体并行处理不同模块

这时如果还沿用“给个 prompt 直接跑”的方式,系统几乎必然会在某个地方塌掉。因为你需要解决的已经不是生成,而是:

  • 跨会话记忆
  • 任务切片
  • 状态交接
  • 验证闭环
  • 权限治理
  • 质量清理

Harness 真正适用的,不是任何有 AI 的地方,而是任何开始出现“持续性、状态性、协作性和风险性”的地方。


四、从失败模式出发,反推一套真正有用的 Harness

与其从抽象概念出发,不如直接从常见失败模式出发。

失败模式 典型表现 对应 Harness 对策
智能体一次做太多 半路耗尽上下文,留下烂尾现场 任务拆分、功能列表、单轮单目标
智能体过早宣布完成 页面看起来像成了,深层功能没通 评估器、端到端测试、功能验收清单
会话切换后失忆 下一轮只能靠猜,重复劳动严重 进度文件、交接制品、提交历史、初始化脚本
看不见真实运行状态 只会读代码,不会读现象 浏览器自动化、日志、指标、trace 接入
工具调用混乱 跑了危险命令或拿不到关键上下文 明确工具描述、权限边界、审批策略
代码库越跑越脏 重复代码、文档失真、风格漂移 lint、结构测试、文档巡检、周期性清理任务

这个表很重要,因为它说明了一件事:

Harness 不是靠信仰堆出来的,而是靠失败模式倒逼出来的。

每多一层结构,都应该对应一个真实、稳定、可复现的失效来源。否则它就只是新形式的样板工程。


五、最小可用 Harness:先搭闭环,再谈平台

如果读完前面你只觉得“有道理”,但不知道怎么开始,那文章还是失败的。下面这套方案,不追求宏大,而追求今天能做、下周能跑、一个月后能收敛。

第一步:先搭“地图”,不要先搭“智能”

先别急着上多智能体。先把下面这些文件和目录补齐:

AGENTS.md
docs/
├── product/
│   ├── overview.md
│   └── feature-list.md
├── architecture/
│   ├── overview.md
│   ├── boundaries.md
│   └── invariants.md
├── plans/
│   ├── active/
│   └── completed/
└── runbooks/
    ├── local-dev.md
    └── release-checklist.md
scripts/
├── init.sh
├── dev-smoke.sh
└── verify.sh
evals/
└── acceptance/

这套结构有三个原则:

  • AGENTS.md 只写最核心的执行规则和导航入口。
  • 真正容易变化的知识,放进 docs/,让它可更新、可索引、可版本化。
  • 所有“怎么启动、怎么验证、怎么交接”的动作,都变成脚本,而不是口口相传。

第二步:给智能体一个干净的起手式

每次进入任务时,不要让它直接编码。先要求它固定执行一段开场动作:

  1. 读取当前任务说明。
  2. 读取 AGENTS.md
  3. 读取相关架构文档和 feature list。
  4. 查看最近提交和未完成计划。
  5. 运行 scripts/init.sh
  6. 跑一次最小 smoke test。
  7. 再开始改动。

这听起来有点啰嗦,但这是让模型进入“工程态”而不是“作文态”的关键。

第三步:要求它只做增量,不准豪赌

给模型的默认规则应该是:

  • 一轮只推进一个明确目标。
  • 每轮结束必须写清楚做了什么、还有什么没做。
  • 如果修改超出预期范围,必须先说明原因。
  • 没验证过,不能标记完成。

Anthropic 在长时运行 harness 里专门让智能体维护 feature list 和 progress file,这个做法非常值。因为它解决的不是记录问题,而是抑制模型的自我脑补

第四步:把“能不能合并”从主观判断改成证据集合

一个最小可用的完成标准,可以长这样:

  • 单元测试通过。
  • 关键路径 smoke test 通过。
  • 若涉及 UI,浏览器自动化验证通过。
  • 若涉及性能,至少有一条指标对比。
  • 若涉及新增能力,feature list 中有对应项被验证。
  • 变更说明能回答“改了什么、为什么这样改、还有什么风险”。

你会发现,这里面几乎没有一句“感觉差不多”。这正是目的。

第五步:让它看见运行时,不要只让它看见源码

很多团队给了模型整个仓库,却没给它任何运行态信息。这等于让一个工程师闭眼修车。

至少补上这些入口:

  • 浏览器自动化
  • 开发日志
  • 错误堆栈
  • 基础指标
  • 关键流程录屏或截图能力

OpenAI 把应用 UI、日志、metrics 和 trace 都做成 Codex 可读对象,这个方向非常对。因为一旦模型能看到现象,它就不再只是在文本层面“猜系统”,而是在系统层面“读系统”。

第六步:一开始不要上太多 agent,先上“一个生成器 + 一个挑刺的人”

如果你要加第二个角色,不要先加更多执行者,先加评估者。

原因很简单:多数团队的第一性问题不是“生成太慢”,而是“生成太轻率”。

一个实用的最小组合是:

  • 生成器:负责实现。
  • 评估器:负责找漏、找假完成、找体验缺口。

等这个闭环跑顺之后,再考虑规划器、专职测试 agent、文档 agent、清理 agent。

第七步:固定做“熵管理”,不要把清理留给未来的你

每周至少做一次:

  • 扫描重复 helper。
  • 清理失效文档。
  • 更新 feature list 和 plans。
  • 回收一次性脚手架。
  • 运行结构 lint。
  • 做一轮小规模 refactor。

不要等“项目稳定了再整理”。在智能体时代,项目从来不会自然稳定,它只会在高吞吐下更快偏离。


六、如果只有两周,先把这条小闭环跑起来

很多人读到这里,最大的问题不是“我同不同意”,而是“这套东西看起来对,但团队没有那么多时间和资源,一上来根本搭不出完整版”。

这是正常的。Harness 不需要从第一天就像一家大公司的内建平台那样完整。真正有效的做法,是先搭出一条能跑的小闭环,再让系统自己长骨头。

如果你只有两周,我建议按下面这个节奏来。

第 1 - 2 天:把知识入口收紧

目标不是写更多文档,而是让智能体知道先读什么

  • AGENTS.md 压缩成 100 行以内的执行规则与导航入口。
  • 建一个最小 docs/ 结构,只保留产品概览、架构边界、运行方式。
  • 把“不要做什么”写清楚,例如禁止改哪些目录、禁止绕过哪些验证。

这两天的成果不在于内容多,而在于仓库第一次出现“结构化入口”。

第 3 - 4 天:把启动和验证脚本化

这一步的目标,是让智能体不再靠猜来操作环境。

  • scripts/init.sh,保证本地服务、依赖、环境变量能一键起。
  • scripts/dev-smoke.sh,覆盖最关键的三到五条主路径。
  • scripts/verify.sh,把测试、lint、最小验收揉成一条固定命令。

如果一支团队连“怎么启动”和“怎么验收”都还依赖口头传承,就还没到谈高阶 agent orchestration 的阶段。

第 5 - 7 天:把“完成”显式化

从这一步开始,智能体才真正有机会进入长任务。

  • 建 feature list,把需求拆成若干可验证项。
  • 建 progress log,让每轮运行结束时留下状态摘要。
  • 规定一轮只处理一个明确目标,禁止“顺手大改一片”。

做到这里,你已经拥有最小的交接系统了。它可能还不优雅,但已经能显著降低模型在多轮会话中的漂移。

第 8 - 10 天:加上一个挑刺者

先不要急着加更多执行 agent,先加评估者。

  • 如果是 UI 任务,就让评估者接浏览器自动化。
  • 如果是服务端任务,就让评估者重点看回归、日志和边界情况。
  • 如果是重构任务,就让评估者专门检查范围外变更和架构越界。

这一步的关键,不是把评估做得“绝对正确”,而是阻止生成器在自我表扬中提前收工。

第 11 - 14 天:把高风险动作纳入治理

到第二周的后半段,开始收权限。

  • 哪些命令自动放行,哪些必须审批。
  • 哪些目录允许写,哪些目录默认只读。
  • 哪些变更允许自动合并,哪些必须人工过眼。
  • 单次运行预算和超时阈值设多少。

走到这一步时,你已经有了一套不是特别华丽、但足够可靠的最小 Harness。它可能还不“聪明”,却已经开始像工程系统,而不是一个热闹的提示词秀场。


七、工程师接下来真正该练的,不再只是编码速度

如果 Harness 成立,那么工程师的价值也会随之重排。

我不认为“程序员会消失”这种说法严肃,但我非常认同一件事:只会把模糊需求翻译成代码的人,会越来越不值钱;能把复杂现实翻译成系统边界、评估标准和交付节奏的人,会越来越值钱。

未来更稀缺的,不是“写得快”,而是下面四种能力。

1. 定义完成

你能不能把“做出来”写成一组可验证条件,而不是一句模糊评价?

2. 设计边界

你能不能把一个系统拆成哪些地方允许智能体自由发挥、哪些地方必须被严管?

3. 理解业务里的脏现实

很多真正重要的规则,根本不在代码里,而在流程、习惯、灰度策略、审批链、风控逻辑和组织默契里。谁能把这些东西结构化,谁就掌握了智能体时代的高分辨率上下文。

4. 持续校准系统

Harness 不是一次性交付物,而是活的基础设施。它要随着模型能力、团队习惯、任务类型和事故经验持续更新。你不是在写一个完美框架,而是在维护一套会自我进化的编排系统。

Human + Agent delivery loop

图 3:未来更像“人类负责约束与校准,智能体负责执行与反馈”的闭环,而不是简单的人力替代。


八、最后的判断:Harness 不会消失,它会下沉成新的工程底座

很多人把 Harness 想成一个过渡概念,仿佛模型再强一点,它就会被吞掉。

我恰恰持相反看法。

模型越强,Harness 不是越不重要,而是越基础、越隐形、越像操作系统。

因为模型变强之后,问题不会停留在“能不能生成”,而会迅速升级为:

  • 能不能连续几小时推进复杂任务。
  • 能不能在多次交接里保持状态一致。
  • 能不能在改动中不破坏旧世界。
  • 能不能自己验证,而不是自我表扬。
  • 能不能在被授权时真正可靠,在不该越界时真正收手。

当这些问题出现时,答案都不会来自“再写一个更好的 prompt”。答案来自系统:来自目录、协议、脚本、测试、评估、观测、审批、清理和文档。

换句话说,未来的软件工程并不会因为模型变强而变得更虚。恰恰相反,它会变得更像工程。

只是工程师手里调的,不再只是代码本身,而是模型与现实之间那层决定成败的编排结构

如果你今天就想开始,请不要先问:

“我该怎么让 AI 一次写完整个项目?”

先问这个问题:

“如果这个智能体要在我的系统里连续工作七天,我准备让它凭什么不把现场搞乱?”

这个问题的答案,就是你的 Harness。


九、一份可以立刻执行的简版清单

如果你想把本文压缩成一个行动列表,就做这 10 件事:

  1. AGENTS.md 改成导航入口,不要写成百科全书。
  2. 建立 docs/productdocs/architecturedocs/plans 三层知识目录。
  3. 写一个 init.sh,让智能体每次都能用同一种方式启动环境。
  4. 写一个 verify.sh,把最小验证路径脚本化。
  5. 维护一份 feature list,让“完成”变成显式状态而不是主观印象。
  6. 让每轮任务只推进一个明确目标,并要求留下进度记录。
  7. 接入浏览器自动化或运行时观测,不要让模型只盯着源码。
  8. 至少引入一个“评估者”角色,专门负责挑刺。
  9. 把高风险命令、写操作和合并动作纳入审批策略。
  10. 固定做文档与代码清理,把熵管理制度化。

如果一支团队真的把这 10 件事做完,哪怕模型本身没有再升级一个大版本,你也会明显感觉到:它不只是“更能写”,而是“更像一个能一起交付的人”。


十、延伸阅读

作者:pprp · 发布于:2026年04月15日 00:00 · 修订于:2026年04月27日 00:00