Harness Engineering:Agent 写代码不难,难的是让它别乱写
Harness Engineering:Agent 写代码不难,难的是让它别乱写
2026 年 2 月,OpenAI Codex 团队发了一篇文章,里面有个数字很扎眼:
3 个工程师,5 个月,约 100 万行生产级代码,没有一行是人手写的。
他们大约合并了 1,500 个 Pull Request,人均每天 3.5 个 PR。OpenAI 的说法是,这个内部 beta 产品只用了传统手写开发大约 1/10 的时间。
他们没有拿到一个普通人用不到的神秘模型。差别在于,他们没有把 Agent 当成“更聪明的代码补全”,而是给 Agent 搭了一套可以稳定工作的工程环境。
这个东西后来被叫作 Harness Engineering。
但我一开始对这个词没什么感觉。直到我复盘一个 Android 车机图库项目,才发现:Agent 能不能交付复杂功能,核心不在于那次 prompt 写得多漂亮,而在于它有没有被放进一个足够清楚、足够硬的工程约束里。

一、先看一个真实项目
这个项目是一个 Android 车机图库应用。
它不是 demo。它要处理 USB 设备插拔、多来源媒体、本地数据库、播放记录、图片预览、视频播放、车速安全限制、全屏交互、缩略图性能优化等一堆细节。
技术栈是 Kotlin + MVVM + Room + ExoPlayer,运行在 Android 车机系统上。最后从项目历史看,一共 38 个 commit,从骨架到完整功能基本都是 Agent 推进的。
大致演进路径是这样:
Phase 1: 搭骨架(commit 1-8)
包拆分 + Koin DI + Room 数据库 + AGENTS.md 初稿
Phase 2: 建能力(commit 9-20)
USB 扫描 + 媒体索引 + 播放记录 + DataStore 偏好设置
Phase 3: 做界面(commit 21-30)
集锦列表 + USB 文件夹浏览 + 照片预览 + 视频播放
Phase 4: 打磨(commit 31-38)
缩略图优化 + 全屏 UI + 选择态优化 + 构建验证
这个项目里最关键的文件不是某个 Activity,也不是某个 ViewModel,而是根目录里的 AGENTS.md。
它只有 97 行,但内容很密:
- 架构分层:UI Layer 到 ViewModel 到 DataSource,UI 不直接访问 DAO 和文件系统
- 命名规范:Activity、Fragment、ViewModel、数据类怎么命名
- 数据存储:Room 表结构、主键格式、DataStore Key 不能随意变更
- 交互规则:USB 拔出时显示占位,缩略图短边固定 324dp,车速超过 15km/h 限制视频播放交互
- 验证方式:通过
install.sh编译 APK 并安装到车机
这份 AGENTS.md 不是一次写完的。它在项目里改了 15 次。
这点很重要。它不是“项目说明书”,更像是错误记录和工程边界的沉淀。Agent 每踩一次坑,工程师就把对应规则固化进去。
最典型的一次是 e1db227 这个 commit。当时 Agent 在开发照片预览功能,直接在 PhotoFragment 里调用了 mediaDao.queryById()。代码能跑,但违反了项目里的 MVVM 分层:UI 层不能直接访问 DAO。
工程师 review 时发现问题,回退并让 Agent 通过 ViewModel 获取数据。之后,AGENTS.md 里“UI Layer 不直接访问 DAO”的规则被加粗,职责划分也写得更具体。
这个 commit 同时改了代码和规则。
这就是 Harness 在真实项目里的样子:不是写一句“请注意架构规范”,而是把一次错误变成以后不会再犯的边界。

二、Harness 到底解决什么问题
用 Agent 写一个函数,大多数人都已经不惊讶了。问题出在更长的任务上。
你让它实现一个完整功能,它会遇到这些情况:
- 不知道项目里已有的约定,重新造一套写法
- 为了让功能跑通,绕过原来的架构分层
- 改了代码但没改文档,过几轮之后口径漂移
- 单元测试能过,但真实设备上跑不起来
- 反复改同一个文件,越修越偏
- 新会话接手时,不知道上一次做到哪里
这些问题不是靠“prompt 写清楚点”就能解决的。
Prompt 解决一次交互怎么表达。Context 解决一次任务中给 Agent 哪些信息。Harness 解决的是:同一类任务反复交给 Agent 时,怎么让它稳定地按项目规则执行,并且能被验证、被纠正、被接续。
研发人员可以把它拆成四件事:
| 问题 | Harness 要做的事 | 常见载体 |
|---|---|---|
| Agent 不懂项目 | 把项目约定放进代码库 | AGENTS.md / CLAUDE.md / docs |
| Agent 会绕规则 | 把关键约束变成自动检查 | Hooks / Linter / 结构测试 |
| Agent 不知道对错 | 给它持续反馈 | CI / 测试 / 构建脚本 / Reviewer Agent |
| Agent 产出越多越乱 | 定期清理漂移和重复 | lint 规则 / 清理 Agent / 重构任务 |
这四件事合起来,才是 Harness Engineering。
它听起来像一个新词,但本质上很工程:把口头提醒变成项目资产,把人工经验变成可重复执行的流程。
三、第一层:代码库本身就是真相源
Agent 最怕的不是不知道怎么写代码,而是不知道“这个项目里应该怎么写”。
在车机图库项目里,AGENTS.md 起到的作用就是把项目约定固定下来。比如:
## 架构约束
- UI Layer 只能和 ViewModel 交互,不能直接访问 DAO 或文件系统
- 数据读取通过 DataSource 封装
- Room 表字段和主键格式不得随意变更
## 验证方式
- 修改后运行 ./install.sh
- 编译失败或安装失败都不算完成
这类内容不应该写成“请写高质量代码”。那没有用。
有用的是 Agent 猜不到、但项目必须遵守的信息:目录结构、分层边界、命名约定、数据契约、构建命令、危险操作、验收标准。
OpenAI Codex 团队也踩过类似坑。他们尝试过把所有信息塞进一个巨大的 AGENTS.md,结果失败了。上下文窗口是稀缺资源,几百行说明会挤掉当前任务需要的代码和信息。
更好的做法是让 AGENTS.md 做导航:文件本身保持短,把架构、接口、业务规则拆到不同文档里。Agent 需要时再去读对应内容。
这就是第一层 Harness:代码库不是被动材料,而是 Agent 的工作说明、边界和记忆。
四、第二层:规则要能自动拦住错误
只写在 AGENTS.md 里的规则,本质上还是软约束。Agent 可能遵守,也可能在任务复杂时绕过去。
稳定的约束,要进入工具链。
Claude Code 的 Hooks 就是一个例子。按照官方文档,Hooks 由三层组成:
Hook event:触发点,比如PreToolUse、PostToolUse、UserPromptSubmit、SessionStartMatcher group:匹配范围,比如只匹配Bash,或只匹配Edit|WriteHook handler:具体处理器,可以是command、http、mcp_tool、prompt或agent
最常见的用法是:
PreToolUse:在工具执行前拦截危险命令或敏感文件修改PostToolUse:在文件修改后自动跑格式化、lint、测试或安全扫描UserPromptSubmit:在用户输入进入模型前做检查或补充上下文
官方文档里还有一个容易写错的点:command hook 收到的是标准输入里的 JSON,不是命令行参数。比如要拦截 Bash 命令,脚本应该从 JSON 里读取 .tool_input.command,再通过 JSON 输出返回决策。要拒绝工具调用,应该返回 permissionDecision: "deny" 和原因。
这和“提醒 Agent 不要做危险操作”不是一个层级。
提醒是建议,Hook 是门禁。
在车机图库项目里,机械化约束还不够完整。它有 AGENTS.md 和 install.sh,但没有自动检查“UI 层是否直接引用 DAO”。这就是下一步可以补的地方:写一个结构测试或 Hook,扫描 Fragment / Activity 中是否出现 DAO 引用,发现就阻断。
这类规则一旦写好,后面每次 Agent 改代码都会自动检查。工程师不再靠肉眼一遍遍重复发现同一个问题。
五、第三层:反馈必须足够快
Agent 很容易在错误方向上继续努力。它不是故意偷懒,而是没有及时反馈。
反馈可以分四层:
| 层级 | 什么时候触发 | 反馈什么 |
|---|---|---|
| 即时反馈 | 工具调用前后 | 格式、安全、语法、架构违规 |
| 构建反馈 | 提交或 PR 时 | 测试、lint、类型检查、编译结果 |
| 运行反馈 | 部署或真机运行后 | 日志、性能、崩溃、设备兼容 |
| 评审反馈 | 功能完成后 | 需求遗漏、体验问题、边界场景 |
车机图库项目没有完整 CI/CD,因为它要跑在车机环境里,GitHub Actions 很难直接覆盖。但它有一个轻量反馈机制:install.sh。
这个脚本会编译 APK,并通过 adb 安装到设备。编译失败、安装失败,都能马上反馈给 Agent。对这个项目来说,这比只跑单元测试更有价值,因为很多问题只有在 Android 构建和设备安装阶段才暴露。
Anthropic 在长时运行 Agent 的文章里也强调了类似问题:新会话没有旧会话记忆,如果没有外部状态记录,Agent 很容易重复劳动或接错进度。
他们的方案是两阶段:
| 阶段 | Agent | 产出 |
|---|---|---|
| Phase 1 | Initializer Agent | init.sh、功能清单、进度文件 |
| Phase 2 | Coding Agent | 增量实现、描述性 commit、端到端测试 |
每次新会话启动,都先读进度文件、看 git 历史、跑初始化脚本,再开始下一个任务。
这套机制解决的不是“模型记忆不够强”,而是把记忆从模型里拿出来,放到仓库、脚本和提交历史里。
六、第四层:Agent 产出越多,越要管理熵
AI 生成代码带来的质量问题,很多不是传统 bug。
它们更像缓慢退化:
| 类型 | 表现 |
|---|---|
| 文档漂移 | 注释和代码不一致,README 过期 |
| 架构侵蚀 | 为了快速完成任务绕过分层 |
| 风格不一致 | 同一个项目出现多种命名和实现模式 |
| 重复代码 | 已有能力不复用,又写一套相似实现 |
这些问题短期内不一定报错,但会让后续 Agent 和人类开发者越来越难理解代码库。
OpenAI Codex 团队的处理思路是,把代码质量标准尽量规则化。比如团队约定 API 响应必须用 snake_case,就不要只写在文档里,而是做成 linter 或结构测试。错误信息本身最好就是修复指南,让 Agent 看到后能直接改。
这句话很关键:
品味捕获一次,强制执行无限次。
但 Harness 也不能无限加复杂度。
Philipp Schmid 提到过一个提醒:Harness 必须设计成可删除的。今天需要复杂管线才能完成的任务,明天可能一个更强模型加一条提示就能搞定。Manus 团队 6 个月内重构了 Harness 5 次,Vercel 删除 80% 的 Agent 工具后效果反而更好,都是同一个方向:别把临时补丁做成永久负担。
所以 Harness 不是越多越好,而是越贴近真实失败模式越好。
七、外部案例说明了同一件事
回到开头的 OpenAI Codex 案例。
OpenAI 的重点不是“Agent 会写 100 万行代码”,而是他们围绕 Agent 建了完整工程环境:AGENTS.md、结构测试、CI、约束分层、定期清理。工程师的主要工作从手写代码,转向设计环境、明确意图、验证产出。
LangChain 的数据更直接。
他们在 Terminal Bench 2.0 上优化 deepagents-cli,模型保持 GPT-5.2-Codex 不变,只调整系统提示、工具和中间件 Hooks,分数从 52.8% 提升到 66.5%,排名从 30+ 到 Top 5。
| 对比维度 | 改善前 | 改善后 |
|---|---|---|
| Terminal Bench 2.0 得分 | 52.8% | 66.5% |
| 排名 | 30+ | Top 5 |
| 模型 | GPT-5.2-Codex | GPT-5.2-Codex |
| 改动 | - | 系统提示 + 工具 + 中间件 Hooks |
这说明一个现实问题:很多团队以为瓶颈是模型,其实瓶颈是运行环境。
Stripe 的 Minions 也是类似方向。公开报道里,Stripe 的自主编码 Agent 每周能产生 1,300 多个 PR,所有变更仍然需要人工 review,但代码本身不是人手写的。它背后依赖的是内部开发工具、CI、Blueprint、人工审核和大量系统约束。
这些案例规模不同,但结论一致:Agent 能不能稳定交付,不只取决于模型,还取决于你有没有把它放进一个可控的工程系统。
八、最小落地方案
如果你现在想开始,不需要先搭复杂平台。
第一步只做三件事:
- 在项目根目录写一个短的
AGENTS.md或CLAUDE.md - 写清楚 5 类信息:技术栈、常用命令、架构边界、禁止事项、验证方式
- 每次 Agent 犯错后,只补一条能防止复发的规则
一个可用的最小模板是:
# AGENTS.md
## 项目概况
- 语言/框架:Kotlin + Android + MVVM
- 构建命令:./install.sh
## 架构边界
- UI 层只和 ViewModel 交互
- UI 层禁止直接访问 DAO、文件系统和网络请求
- 数据读取统一通过 DataSource
## 数据约定
- Room 表结构变更必须同步迁移
- DataStore Key 不能重命名,除非同时处理兼容
## 禁止事项
- 禁止修改 .env、密钥、签名文件
- 禁止绕过构建脚本直接声称完成
## 完成标准
- 代码修改后必须运行 ./install.sh
- 编译、安装、关键页面启动都通过,才算完成
等这份文件稳定下来,再补第二层:Hook、linter、结构测试。
不要一开始就做大而全的平台。先抓最常见、最贵、最容易复发的错误。
比如车机图库项目里,最值得补的不是“自动优化所有代码质量”,而是一个很具体的检查:Fragment 和 Activity 不能直接引用 DAO。这个规则一旦机械化,之前 PhotoFragment 直接访问 mediaDao 的问题就不会反复出现。
九、冷一点看
Harness Engineering 解决不了所有问题。
它解决的是“Agent 在工程环境里稳定工作”的问题,不保证业务判断一定正确。
Linter 能抓格式,结构测试能抓分层,CI 能抓编译和测试,但这些东西未必能判断“用户注册流程是不是应该加邮箱验证”“车速限制的交互是不是符合真实驾驶场景”。这部分仍然需要产品判断、领域经验和人工 review。
另一个问题是遗留项目。新项目从第一天就写 AGENTS.md、加测试、设计边界,难度还可控。一个已经有几十万行历史代码、约定不统一、测试不足的项目,要给 Agent 搭 Harness,会困难很多。
所以不要把 Harness 理解成“让人退出开发”。更准确的说法是:工程师少写一部分重复代码,但要多做环境设计、约束设计和验证设计。
对大多数团队来说,模型能力越来越难形成长期差异;可积累的,是围绕自己项目沉淀下来的规则、脚本、测试、文档和执行轨迹。
前期投入 30 分钟写清楚项目规则,后面每次会话少解释 5 分钟。更重要的是,Agent 少犯一次架构错误,你省下的可能不是 5 分钟,而是一轮 review、返工和回归测试。
这才是 Harness Engineering 值得关注的原因。
参考与延伸阅读
- Harness engineering: leveraging Codex in an agent-first world - OpenAI,2026 年 2 月
- Unlocking the Codex harness: how we built the App Server - OpenAI,2026 年 2 月
- Unrolling the Codex agent loop - OpenAI,2026 年 1 月
- Effective context engineering for AI agents - Anthropic,2025 年 9 月
- Effective harnesses for long-running agents - Anthropic,2025 年 11 月
- Harness design for long-running application development - Anthropic,2026 年 3 月
- My AI Adoption Journey - Mitchell Hashimoto,2026 年 2 月
- Improving Deep Agents with harness engineering - LangChain,2026 年 3 月
- GStack - Garry Tan
- Stripe Engineers Deploy Minions, Autonomous Agents Producing Thousands of Pull Requests Weekly - InfoQ,2026 年 3 月
本文链接:Harness Engineering:Agent 写代码不难,难的是让它别乱写 - https://h89.cn/archives/610.html
版权声明:原创文章 遵循 CC 4.0 BY-SA 版权协议,转载请附上原文链接和本声明。