你可能最近见过这个词:Harness Engineering。
它频繁出现在在各种技术博客、技术群、甚至一些 AI 工程师的简历里。
但如果你去问Harness 到底是什么?大概率会得到各种不一样的回答:
- 有人说是开发规范
- 有人说是“驾驭 AI 的系统”
- 有人说是 AGENTS.md
- 还有人说是 CI/CD,甚至测试框架
今天我把这件事彻底讲清楚。
先看一组让所有人沉默的数据
Anthropic 做过一个对照实验。
同一个 prompt,同一个模型——Opus 4.5,旗舰级 AI,够强了。任务只有一个:做一个 2D 复古游戏编辑器。
第一次,让它裸跑,没有任何工程基础设施。20 分钟,烧了 9 美元,游戏核心功能根本跑不起来。
第二次,给它配上完整的 Harness——Planner 扩展需求、Generator 逐功能实现、Evaluator 用 Playwright 实际点击测试。6 小时,烧了 200 美元,游戏可以正常游玩。
模型没换。prompt 没换。差距是 8 倍。
OpenAI 紧接着在 2025 年发布了一篇文章,他们用 Codex 从空仓库起步,五个月后生成了 100 万行代码。三个工程师驱动,开了 1500 个 PR,平均每人每天 3.5 个。
他们的结论是:同一个模型,在空白环境里和在一个有完整 Harness 的环境里,产出有本质差异。不是好一点,是质变。
模型不是瓶颈。Harness 才是。
Harness 到底是什么
打个比方。
你请了一个顶级厨师,给他一间只有食材的厨房——没有灶台、没有菜谱、没有出菜流程。让他做一桌菜。他能力再强,能做出来吗?
AI 编程 Agent 的困境一模一样。能力在那里,但没有配套的工程环境,就发挥不出来。
Harness 就是这套工程基础设施的总称,分五个子系统:
1. 指令系统(Instructions)
Agent 需要知道做什么、按什么顺序做、做到什么程度才算完。
很多人以为扔一份超长的 README 就够了。实际上,Agent 更需要的是一份路线图,告诉它去哪找信息,而不是把所有信息全部塞给它。一份 50 行的 AGENTS.md 文件,可能比一个 500 行的 README 更有效。
2. 状态系统(State)
一个任务跑一半停了,下次 Agent 怎么知道从哪继续?
人的项目有产品文档、有 git log、有进度记录。但这些对 Agent 来说大部分是盲区。Harness 要求把状态信息显式地写进文件,让 Agent 下次启动时能无缝接着干。
3. 验证系统(Verification)
这是投入产出比最高的子系统,也是最容易被忽略的。
Agent 说"写完了",不等于真的写完了。你有没有告诉它具体怎么验证?单元测试有没有跑?端到端流程有没有走一遍?
没有验证环节,Agent 就会过早宣布胜利,然后留下一堆半成品。
4. 范围系统(Scope)
Agent 有一个经典毛病:要么做得太少,要么做得太多。
让它加个功能,它能顺手重构半个代码库,然后留下一堆新 bug。Harness 通过 Feature List 这种东西,明确告诉 Agent:这次只做这一件事,做完就停。
5. 会话生命周期(Session Lifecycle)
每次开始之前做什么检查,每次结束之后留什么记录。
很多团队发现 Agent 第一次跑还行,第二次就跑飞了。问题往往出在这里——会话和会话之间没有交接,第二次从头开始,状态全丢了。
第一个问题:任务说不清楚,Agent 只能瞎猜
你让 Agent "加个搜索功能"。它理解的跟你完全不一样。
搜什么?全文本还是结构化?要不要分页?要不要高亮?你没说清楚,Agent 就自己猜。猜对了是运气,猜错了再改,改的成本比一开始说清楚还高。
这就像去饭馆跟师傅说"来个鱼",端上来是红烧还是清蒸还是酸菜,全看运气。
更隐蔽的是:项目里隐含的架构约定 Agent 根本看不到。你们团队统一用 SQLAlchemy 2.0 新语法,但 Agent 默认写了 1.x 的代码。所有 API 必须走 OAuth 2.0,但这个规则只存在你脑子里。Agent 不知道——它不是不想遵守,是压根不知道有这回事。
解决方案:仓库即规范。
所有必要的信息必须放在仓库里,通过结构化的指令文件来呈现。OpenAI 把这个原则叫做"仓库即规范"——仓库就是最高权威的规范文档。Slack 里的架构决定、Confluence 里的设计文档、工程师脑子里的隐性知识,对 Agent 来说全等于不存在。
具体做法是:在仓库根目录放一个 AGENTS.md 文件,50 到 100 行,只放最关键的东西——项目概览、技术栈版本、硬约束、指向专题文档的链接。专题文档按模块放,Agent 需要的时候再去读。
就像图书馆的书架标签——你想找历史类书籍,直接去标着"历史"的书架,不用把整个图书馆翻一遍。
第二个问题:Agent 总是一次做太多事
你让 Claude Code "给这个项目加上用户认证功能"。
结果它同时开始改数据库 schema、写路由、改前端组件、还顺手重构了错误处理中间件。两个小时后你一看——12 个文件被修改,800 行新代码,但没有一个功能是端到端跑通的。
这不是模型能力问题,是你没有给它划边界。
Agent 天生就有"多做一点"的冲动。看到相关的事情就顺手一起做了,就像在超市本来只打算买瓶酱油,结果推着满满一车出来。
Anthropic 的实验数据很残酷:使用 WIP=1 策略(做完一件再做下一件)的 Agent,任务完成率比使用宽泛提示的 Agent 高 37%。而且,Agent 生成的代码行数和实际完成的功能数量呈负相关——写得越多,完成得越少。
解决方案:强制 WIP=1。
在 Harness 里明确告诉 Agent:任何时刻只允许一个任务处于"进行中"状态。每个功能项必须有明确的验收标准——不是"代码写完了",而是"curl 返回 201 才算完成"。
用 Feature List 把所有任务的状态外部化:哪个在做、哪个做完了、哪个被阻塞。新会话读取这个文件,三分钟就能接上,不用猜。
第三个问题:Agent 总说"做完了",然后留下一堆 bug
Agent 改完代码,跑了单元测试,全部通过,然后告诉你"做完了"。
你实际一跑——端到端流程根本没走通,数据库迁移半途失败,某个配置在目标环境里缺失。
这不是小概率事件。Guo 等人 2017 年的论文已经证明了:现代神经网络系统性地过度自信——模型自报的置信度显著高于实际准确率。
Agent 也是这样。它"觉得"做完了,但实际上差得远。你的 Harness 必须用外部化的、基于执行的验证来替代 Agent 的"感觉"。
更严重的是:Anthropic 2026 年的研究发现,当 Agent 被要求评估自己的工作时,它系统性地过度正面评价——即使质量明显不达标。就像让学生自己给自己判卷,对自己的答案总是特别宽容。
解决方案不是让 Agent "更客观"。解决方案是把"干活的人"和"检查的人"分开。
Anthropic 的三 Agent 架构实验给出了最直接的证据:
架构 | 时长 | 成本 | 结果 |
单 Agent 裸跑 | 20 分钟 | $9 | 否(游戏无法正常响应输入) |
三 Agent(Planner + Generator + Evaluator) | 6 小时 | $200 | 是(游戏可以正常游玩) |
同一个模型,同一段提示词。区别只在 Harness——裸奔 vs 有人验收。
Evaluator 的核心职责是用 Playwright 实际点击测试,而不是等 Agent 自己说"我觉得可以了"。
第四个问题:单元测试全绿,上线就崩
你让 Agent 加一个文件导出功能。它写了渲染进程组件、预加载脚本、服务层逻辑,每个组件的单元测试都通过了。Agent 说"做完了"。
你实际一点击导出按钮——文件路径格式不对,进度条没反应,大文件导出时内存泄漏。5 个组件边界缺陷,单元测试一个都没发现。
这就像一个合唱团排练,每个声部单独唱的时候都完美,但合在一起的时候女高音比男低音快了半拍,伴奏的调子差了半个音。每个部分都"对"了,但整体跑调了。
单元测试的设计哲学是隔离——模拟依赖,专注被测单元。这个哲学使单元测试快速且精确,但也制造了系统性的盲区:接口不匹配、状态传播错误、资源生命周期问题、环境依赖差异——单元测试一个都抓不到。
解决方案:三层验证缺一不可。
第一层:语法与静态分析。成本最低,信息量最小,但必须通过。
第二层:运行时行为验证。跑测试、执行应用启动检查、验证关键路径。不只要写了,还要能跑。
第三层:系统级确认。跑端到端测试,走完完整用户流程。不只要能跑,还要跑对。
单元测试通过 ≠ 任务完成。端到端测试跑通才算真正的完成信号。
第五个问题:跨会话任务总是丢上下文
你让 Agent 实现一个完整的功能,它跑了 30 分钟,上下文快满了。你开个新会话继续,然后发现——它不记得上次做了什么决策、哪些文件改过了、测试跑到什么状态了。它得花 15 分钟重新探索一遍项目。
这就是上下文窗口的局限。上下文窗口是有限的,不管模型吹多大的窗口(128K、200K、1M),长任务总会用完。
更深层的问题:Agent 产生的信息不是均匀重要的。中间推理步骤包含决策的"为什么"——为什么选了方案 A 而不是方案 B,为什么用了这个库而不是那个库。压缩策略通常保留代码但丢了"为什么"。下一个会话看到代码但不知道为什么这么写,可能会把一个有意为之的设计决策给"优化"掉。
Anthropic 还发现了一个更隐蔽的现象:当 Agent 感觉上下文快满了,它们会表现出"过早收敛"的行为——匆忙结束当前工作,跳过验证步骤,或者选一个简单的方案而不是最优方案。就像考试时发现时间快到了,赶紧随便选几个选择题。
解决方案:把 Agent 当成一个会失忆的超级工程师来管理。
每次会话结束前,它必须把关键信息写进文件:做了什么、为什么这样做、下一步是什么。进度文件、决策日志、git 提交作为检查点——这就是那个工匠的日记本。
一份 PROGRESS.md 记录好之后,下一个会话三分钟就能接上。没有这份文件,得花 15 分钟重新猜——上次改了啥、为什么那么改、现在卡在哪。
第六个问题:每次会话开头 Agent 总要先摸半小时环境
你开了个新的 Agent 会话,让它"帮我加个搜索功能"。它上来就开始改代码,改了 20 分钟发现测试框架没配好,又花 10 分钟搞测试框架,然后发现数据库迁移脚本格式不对,最后折腾了半天。
搜索功能是加了,但整个会话效率很低,大部分时间花在了"搞清楚这个项目怎么运作"上,而不是写搜索功能。
解决方案:初始化必须是独立的阶段。
第一个会话只做初始化,不写任何业务功能代码。初始化的产出是:可运行的环境、可验证的测试框架、自举契约文档、任务分解、git 检查点。
这就像盖房子——不能边打地基边砌墙,不然墙砌到一半地基还没干,整栋楼都得推倒重来。先打地基,地基干了,再砌墙。
实验数据:使用独立初始化阶段的项目,多会话场景中的功能完成率比混合方式高 31%。初始化投入的时间在后续 3 到 4 个会话中就能完全收回。地基打得越扎实,上面的楼盖得越快。
第七个问题:Agent 写的代码越来越乱
你的 Agent 跑了一下午,改了 20 个文件,提交了代码,会话结束。
下一个会话开始,一上来就发现:构建失败了,测试红了,临时调试文件到处都是,功能清单没更新,进度完全不清楚。新会话的前 30 分钟全花在搞清楚上一个会话到底干了什么上。
这就像大学宿舍——你不倒垃圾,下一个室友进来就得替你收拾。他本来是来复习考试的,结果先花半小时收拾烂摊子。
Lehman 的软件演化定律告诉我们:持续变更的系统,除非主动管理,否则复杂性必然增加。对 AI 编码 Agent 尤其成立——Agent 每次会话都会引入变更,如果不在退出时清理,技术债务会指数级累积。
一个真实项目的数据,没有清洁策略的情况下:
周数 | 构建通过率 | 测试通过率 | 新会话启动时间 |
第 1 周 | 100% | 100% | 5 分钟 |
第 4 周 | 95% | 92% | 15 分钟 |
第 8 周 | 82% | 78% | 35 分钟 |
第 12 周 | 68% | 61% | 60+ 分钟 |
同样的项目,有清洁策略的情况下,第 12 周:构建通过率 97%,测试通过率 95%,新会话启动时间 9 分钟。
12 周后,两者差距是灾难性的。
解决方案:清洁状态是会话完成的必要条件。
在 Harness 里明确定义:会话完成 = 任务通过验证 AND 清洁状态检查通过。
会话退出检查清单:
- 构建通过
- 所有测试通过
- 功能清单已更新
- 无调试代码残留
- 标准启动路径可用
每个会话结束前走一遍这份清单。每天多花 5 分钟打扫卫生,12 周后省下几十个小时的混乱时间。
一个真实团队的完整转变
用 GPT-4o 开发一个 TypeScript + React 前端应用(约 20,000 行代码)的团队,经历了四个阶段:
阶段一:只有 README。5 次运行成功 1 次(20%)。主要失败:选错包管理器、没遵循组件命名约定、跑不了测试。
阶段二:加了 AGENTS.md,写明技术栈版本、命名约定、关键架构决策。成功率升到 60%。
阶段三:在 AGENTS.md 里加了验证命令。成功率升到 80%。
阶段四:加上进度追踪文件。成功率稳定在 80% 到 100%。
四次迭代,模型一个字没改。成功率从 20% 到接近 100%。
这就是 Harness 工程的力量。你没有换更贵的食材,你只是把厨房收拾利索了。
说到底
Harness 要解决的问题就一个:让 AI Agent 的能力真正能被用出来。
模型强不强是一回事,能不能稳定地产出可靠的代码是另一回事。这两者之间的差距,就是 Harness 要填的坑。
它不是某个单一的工具或文件,而是五件事的集合:指令、状态、验证、范围、生命周期。每件都有具体做法。
两条核心原则:
仓库即规范。所有 Agent 需要知道的信息都必须放在仓库里。不在仓库里的,Agent 看不到。
完成必须有证据。Agent 说"做完了"不算,只有验证命令实际跑通了才算。单元测试全绿不等于端到端流程跑通。
做到了这两条,再配合状态持久化、范围控制、清洁交接,一个 Agent 才能真正成为可靠的开发搭档,而不是一个时而超神时而超鬼的抽卡机器。
怎么落地
说清楚了,来点实际的。以下是一套最小可用的 Harness 模板,拿过来改改就能用。
第一步:在仓库根目录放一个 AGENTS.md
这个文件是整个 Harness 的入口,参考原始模板格式:
# 订单服务 这个仓库面向长时运行的 coding agent 工作流。目标不是尽可能快地产出代码,而是让每一轮会话结束后,下一个会话仍然能无猜测地继续工作。 ## 这是什么 一个 Spring Boot 微服务,处理订单创建、查询和取消。 ## 技术栈 - Java 17 + Spring Boot 3.x - 数据库:PostgreSQL 15 - ORM:Spring Data JPA + Hibernate 6.x - 迁移工具:Flyway - 构建工具:Maven ## 开工流程 写代码前先做这些事: 1. 用 `pwd` 确认当前目录 2. 读取 `PROGRESS.md`,了解最新状态和下一步 3. 运行 `git log --oneline -5` 看最近提交 4. 运行 `./init.sh` 5. 在开始新功能前,先跑必需的 smoke test 如果基础验证一开始就失败,先修基础状态,不要在坏的起点上继续叠新功能。 ## 工作规则 - 一次只做一个功能 - 不要因为"代码已经写了"就觉得做完了,必须实际验证过才算 - 除非为了消除当前 blocker 的窄范围修复,否则不要扩大到其他功能 - 实现过程中不要悄悄改弱验证规则 - 优先依赖仓库里的持久化文件,而不是聊天记录 ## 必需文件 - `PROGRESS.md`:会话进度和当前已验证状态 - `init.sh`:统一的启动与验证入口 - `docs/`:各模块的架构规范文档 ## 完成定义 一个功能只有在以下条件都满足时才算完成: - 目标行为已经实现 - 要求的验证真的跑过 - 仓库仍然能按标准启动路径重新开始工作 ## 收尾 结束会话前: 1. 更新 `PROGRESS.md` 2. 记录仍未解决的风险或 blocker 3. 在工作处于安全状态后,用清晰的提交信息提交 4. 保证下一轮会话可以直接运行 `./init.sh`就这些,不要超过 150 行。AGENTS.md 是导航仪,不是手册。
第二步:用结构化的 README 和 docs/ 目录描述项目结构
docs/ 这套东西是给大规模、长周期项目准备的。如果你手上的项目复杂度没那么高,用结构化的 docs/ 目录就够了,效果一样好。
项目结构成这样:
order-service/ ├── AGENTS.md # 入口:开工流程、工作规则、收尾清单 ├── README.md # 给人类看:项目介绍、快速开始 ├── docs/ │ ├── api-patterns.md # API 规范 │ ├── db-conventions.md # 数据库规范 │ ├── transactional.md # 事务使用规范 │ └── testing.md # 测试标准 ├── src/test/java/.../ # 测试代码 └── ...docs/里的每个文件按模块放,Agent 改到哪个模块,自然会看到对应的规范。不用把所有规则塞进一个文件。
这套结构和原始文档 lecture-03 里的建议完全一致:知识靠近代码、最小但完备、跟代码一起更新。AGENTS.md 充当目录页,docs/ 充当详细内容。Agent 需要什么去读什么,不会被信息淹没。
第三步:写一个 init.sh
#!/usr/bin/env bash set -euo pipefail echo "[init] 检查 Java 环境" if ! java -version 2>&1 | grep -q 'version "17'; then echo "[init] 错误:需要 Java 17" exit 1 fi echo "[init] 安装依赖" mvn dependency:resolve -q echo "[init] 运行数据库迁移" mvn flyway:migrate -q echo "[init] 编译" mvn compile -q echo "[init] 运行基础验证" mvn test -Dtest='OrderApplicationTest' -q echo "[init] 完成,环境就绪"注意set -euo pipefail——脚本任何一步失败立即退出,不会让 Agent 在坏掉的环境里继续干活。
第四步:会话退出前更新 PROGRESS.md
每次会话结束前,把关键信息写进一个文件,让下一个会话能直接接上:
# 订单服务进度 ## 当前状态 - 最新 commit: abc5678 (feat: add order query endpoint) - 测试状态: 42/43 通过(InventoryReleaseTest 失败) - 编译: 通过 - 迁移: 通过 ## 已知问题 - InventoryReleaseTest: 并发取消场景下库存未释放,怀疑 @Transactional 传播问题 - 订单号生成策略待确认(UUID vs 雪花算法) ## Blocker - 需要确认库存服务是否需要引入消息队列(依赖订单取消功能的评审结果) ## 下一步 1. 补充 GET /api/orders/{id} 的 404 边界测试 2. 修复 InventoryReleaseTest 并发问题 3. 更新 OpenAPI 文档这个文件是每次会话交接的核心。新会话读取它,就知道从哪接。
第五步:制定会话退出检查清单
每个会话结束前,Agent 必须确认这五件事:
会话退出检查清单: - [ ] mvn compile 成功 - [ ] mvn test 全部通过(至少无新增失败) - [ ] PROGRESS.md 已更新 - [ ] 无 System.out.println、debugger、硬编码密码残留 - [ ] git commit 已创建,message 说清楚做了什么这五条放进 AGENTS.md 的收尾部分,Agent 每次收尾前自己读一遍。
从哪开始
别一上来就想搞个大新闻,分步走反而更快。按这个顺序来:
第一步:AGENTS.md。开工流程、工作规则、收尾清单,先把这三个写清楚。50 行以内够了,不用完美,后面边用边改。
第二步:init.sh。一个脚本,检查 Java 版本、数据库连不连得上、跑一遍基础测试。环境有问题,后面全是白干。
第三步:docs/ 目录。API 规范、数据库规范、事务规范,按模块放文档。Agent 改哪块,就往哪块的文档里塞规则。
第四步:PROGRESS.md。加上交接文件,让下一个会话能直接接上,不用从头猜。
关于反复测试。
这个环节很多人会忽略,觉得写完规则就完事了。真实情况是:规则写得再好,不测就不知道哪有问题。
建议每次改完规则后,刻意制造一些小任务让 Agent 跑一遍,记录它哪里卡住、哪里理解错了。把这些反馈补充进文档。
比如:让 Agent 修复一个已知的 Bug,或者加一个小功能。看它的步骤对不对,收尾干不干净,commit 写得清不清楚。
跑上三四次,你就能摸清 Agent 的脾性,知道哪些规则它爱忽略,哪些地方需要写得更细。这个反复打磨的过程,比第一次写多详细都管用。
学习资源推荐
如果你想更深入地学习大模型,以下是一些非常有价值的学习资源,这些资源将帮助你从不同角度学习大模型,提升你的实践能力。
一、全套AGI大模型学习路线
AI大模型时代的学习之旅:从基础到前沿,掌握人工智能的核心技能!
因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获取
二、640套AI大模型报告合集
这套包含640份报告的合集,涵盖了AI大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示
因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获取
三、AI大模型经典PDF籍
随着人工智能技术的飞速发展,AI大模型已经成为了当今科技领域的一大热点。这些大型预训练模型,如GPT-3、BERT、XLNet等,以其强大的语言理解和生成能力,正在改变我们对人工智能的认识。 那以下这些PDF籍就是非常不错的学习资源。
因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获取
四、AI大模型商业化落地方案
作为普通人,入局大模型时代需要持续学习和实践,不断提高自己的技能和认知水平,同时也需要有责任感和伦理意识,为人工智能的健康发展贡献力量。