Harness Engineering:把 AI 编码从“能写代码”推进到“能交付系统”
- 明确任务定义:将自然语言需求转换为包含目标、范围、约束、验收条件和验证命令的具体契约,确保任务闭合且可执行。
- 构建最小可闭环Harness:从简单任务开始,确保环境初始化、相关检查运行、必要文档获取及失败信息反馈的自动化,实现无人干预下的稳定复现与验证。
- 优化仓库结构与知识管理:采用“短入口、深链接、就近说明”的策略组织文档,使关键规则最终进入可执行系统,并通过CI工具化代码审查中的常见反馈。
- 增强Agent对系统的感知能力:提供脚本化启动服务、固定测试数据、浏览器自动化等功能,以支持端到端验证,生成统一证据目录,提高问题定位效率。
- 逐步扩大自治权限并持续治理:根据任务风险和Harness成熟度分级授权给Agent,并定期维护Harness,包括更新文档、减少冗余工具、处理过期信息等,确保长期可持续性。
Harness Engineering:把 AI 编码从“能写代码”推进到“能交付系统”
本文受 OpenAI《Harness engineering: leveraging Codex in an agent-first world》启发,尝试回答一个更具体的问题:团队如何从零开始,把 Harness 一步步落到真实软件工程中?
过去一年,很多团队已经验证了 AI 能写代码。可一旦任务从“补一个函数”扩大到“完成一个需求”,成功率就会迅速下降:Agent 找不到真正入口,不知道哪些约束不能破坏,改完无法自证正确,遇到失败也得不到足够信息。
问题通常不只在模型,而在模型工作的环境。
这正是 Harness Engineering 要解决的事。这里的 Harness 不是某个框架,也不是一份超长提示词,而是包围编码 Agent 的整套工程控制面:上下文、工具、环境、约束、反馈、观测和权限。它的目标,是让 Agent 可以独立完成“理解—修改—验证—纠错—交付”的闭环。
可以把一次 Agent 交付的可靠性粗略理解为:
可靠交付 = 清晰任务 × 可发现上下文 × 可执行环境 × 快速反馈 × 安全边界
这是乘法,不是加法。任何一项接近零,单纯换更强模型或增加提示词都很难补救。
一、先定义目标:Harness 交付的不是代码,而是证据
传统研发中,工程师可以依靠长期记忆、组织默契和人工判断补足信息。Agent 没有这些默认背景。一个适合 Agent 的任务必须是“闭合”的:输入清楚、边界清楚、完成条件可以执行。
建议用以下任务契约取代一句自然语言需求:
## 目标
用户可以撤销尚未发货的订单。
## 范围
- 修改订单 API 和用户端订单详情页
- 不修改已发货订单的状态机
## 约束
- 复用现有鉴权与审计日志
- 不新增生产依赖
- 数据库变更必须向后兼容
## 验收条件
- 待支付、已支付订单可以撤销
- 已发货订单返回 409
- 重复请求保持幂等
- 单元、集成和端到端测试通过
## 验证命令
make check
make test-order
make e2e-order-cancel
这里最重要的变化是:完成不再等于“Agent 说已经完成”,而等于“仓库能够产出可检查的证据”。
二、第一阶段:建立最小可闭环 Harness
不要一开始追求全自治。先选一个边界清楚、风险低、10~30 分钟可验证的任务,例如新增校验规则、修复局部缺陷或补一个 API 字段。
最小 Harness 只需具备四个条件:
- 一条命令完成环境初始化;
- 一条命令运行与改动相关的检查;
- Agent 能在仓库内找到必要文档;
- 失败信息足以指导下一次修改。
仓库入口可以统一为:
.PHONY: setup check test-agent
setup:
./scripts/bootstrap.sh
check:
./scripts/lint.sh
./scripts/typecheck.sh
./scripts/test-changed.sh
test-agent:
./scripts/test-agent-smoke.sh
脚本要满足三个要求:非交互、幂等、失败即非零退出。不要让 Agent 猜测先启动哪个服务、去哪里复制环境变量,或如何判断测试究竟有没有完成。
这一步的验收指标不是生成了多少代码,而是:同一个任务在全新工作区中能否稳定复现,Agent 是否能在无人补充命令的情况下完成一次修改和验证。
三、第二阶段:把仓库变成可导航的知识库
Agent 最容易获得、也最不容易过期的上下文,应该在代码仓库里。聊天记录、口头约定和散落在内部系统里的说明,都不适合作为唯一事实来源。
但这不意味着把所有知识塞进根目录的 AGENTS.md。超长总说明会稀释关键约束,也更容易过期。更好的做法是“短入口、深链接、就近说明”。
repo/
├── AGENTS.md # 全局地图、通用命令、硬约束
├── docs/
│ ├── architecture.md # 模块边界与依赖方向
│ ├── domain/
│ │ └── orders.md # 订单领域语义与状态机
│ ├── decisions/ # ADR:为什么这样设计
│ └── runbooks/ # 调试、回滚、故障处理
├── services/
│ └── order/
│ └── AGENTS.md # 订单服务局部命令与陷阱
└── scripts/
└── agent/ # 面向 Agent 的稳定工具入口
根 AGENTS.md 应像地图,而不是百科全书:
# Repository Guide
## 快速开始
- 安装:`make setup`
- 全量检查:`make check`
- 仅检查改动:`make check-changed`
## 架构硬约束
- domain 不得依赖 transport 或 persistence
- 跨服务调用必须通过公开 client
- 所有写接口必须包含鉴权、审计和幂等策略
## 按任务阅读
- 修改订单:`docs/domain/orders.md`
- 数据库迁移:`docs/runbooks/migrations.md`
- 新增服务:`docs/architecture.md`
文档中的每条关键规则最好最终进入可执行系统。比如“domain 不得依赖 web”不应只是一句话,还应由依赖检查器验证。文档负责解释意图,工具负责阻止违规。
四、第三阶段:把架构意图编译成机械约束
代码审查中的大量反馈其实是可机械化的:目录依赖、命名、接口兼容性、迁移规则、安全基线。这类判断应尽量从 Reviewer 的记忆迁入 CI。
可以按以下顺序推进:
- 格式化、静态检查和类型检查;
- 禁止依赖和模块边界;
- API Schema 与数据库迁移兼容性;
- 安全、隐私和许可证扫描;
- 针对本仓库约定的自定义检查。
例如,用伪配置表达依赖方向:
layers:
- domain
- application
- infrastructure
- transport
rules:
domain: []
application: [domain]
infrastructure: [domain, application]
transport: [application]
CI 则提供由快到慢的反馈阶梯:
jobs:
fast-checks:
steps:
- run: make format-check lint typecheck test-changed
contract-checks:
needs: fast-checks
steps:
- run: make dependency-check api-compat migration-check
integration:
needs: contract-checks
steps:
- run: make test-integration
e2e:
needs: integration
steps:
- run: make test-e2e
把最便宜、最确定的检查放在前面。Agent 若要等待 20 分钟才发现一个类型错误,自治循环必然昂贵且缓慢。
五、第四阶段:让 Agent 看见系统,而不只是源代码
真实功能经常跨越 UI、API、队列和数据库。只给代码与单元测试,Agent 无法判断实际行为是否正确。Harness 需要给它与人类工程师类似的感知能力。
对于 Web 系统,至少提供:
- 可脚本化地启动整套本地服务;
- 固定的测试账号和种子数据;
- 浏览器自动化与截图;
- 可检索的结构化日志;
- Trace ID 串联前端请求、API、任务和数据库操作;
- 必要时可查询本地指标或事件。
一个端到端验证脚本可以输出统一证据目录:
artifacts/run-20260722-103000/
├── summary.json
├── browser/
│ ├── before.png
│ ├── after.png
│ └── console.log
├── api/
│ └── responses.jsonl
└── traces/
└── order-cancel.json
summary.json 不仅写成功或失败,还应包含失败阶段、关键日志位置、复现命令和 Trace ID。好的反馈不是信息越多越好,而是下一步行动越明确越好。
六、第五阶段:设计自校正循环
成熟 Harness 中,Agent 的主循环应当非常朴素:
读取任务契约
→ 定位相关代码与文档
→ 制定小步修改计划
→ 实施最小改动
→ 运行最快的相关检查
→ 根据失败信息修复
→ 运行更高层验证
→ 输出变更摘要、证据和剩余风险
关键是控制每次循环的范围。一次改几十个文件后再统一验证,会让错误归因变得困难。可以在 Harness 中明确限制:先搜索后修改;优先局部检查;连续两次同类失败后重新读取约束;涉及数据库、权限或外部接口时提高验证等级。
建议把最终交付格式也固定下来:
## 变更
- 实现了什么
- 修改了哪些边界
## 验证
- `make check`:通过
- `make test-order`:通过,38 tests
- `make e2e-order-cancel`:通过
## 证据
- 截图、日志或 Trace 路径
## 风险
- 尚未覆盖的情况
- 是否需要迁移、灰度或监控
七、第六阶段:分级扩大自治,而不是一次放权
权限应该随任务风险和 Harness 成熟度增长。
| 等级 | Agent 能力 | 典型任务 | 必要门禁 |
|---|---|---|---|
| L0 辅助 | 解释、建议,不写入 | 调研、代码问答 | 无写权限 |
| L1 修改 | 在分支中改代码 | 测试、局部修复 | 人工逐项审查 |
| L2 自证 | 修改并运行验证 | 常规功能 | CI 全绿、证据齐全 |
| L3 提交 | 创建提交或 PR | 标准化需求 | 所有权规则、自动审查 |
| L4 合并 | 低风险变更自动合并 | 依赖升级、机械重构 | 风险分类、自动回滚 |
| L5 运行 | 处理受控生产操作 | 特定运维任务 | 最小权限、审批、审计、熔断 |
不要按“模型有多聪明”授权,而要按“系统多可验证、失败多可逆”授权。支付、权限、数据删除、不可逆迁移等高风险区域,即使 Agent 表现很好,也应保留明确的人类审批点。
八、持续治理:控制仓库熵增
Agent 提高吞吐后,新的瓶颈会从“代码写得慢”转为“仓库是否还能被理解”。重复工具、过期文档、例外架构和不一致测试会快速积累,并反过来降低后续 Agent 的成功率。
因此需要把维护 Harness 当作产品工作:
- 记录 Agent 经常问错或找不到的内容,补导航而不是补聊天提示;
- 统计最常见 CI 失败,将高频模糊错误变成明确诊断;
- 删除重复脚本,为常用动作保留一个标准入口;
- 定期验证文档中的命令、链接和所有者;
- 把反复出现的代码审查意见升级为 lint、测试或生成器;
- 为遗留代码设立“允许存在但不得新增”的基线。
这是一个很实用的治理原则:规则第一次出现时写进评审意见,第二次写进文档,第三次就应该考虑写成机器检查。
九、衡量 Harness 是否真的有效
不要用生成代码行数衡量成功。它鼓励更大的改动,却不能代表更高的交付质量。建议观察四类指标:
1. 自治能力
- 无人工追问完成率;
- 首次验证通过率;
- 每个任务需要人工干预的次数;
- Agent 可独立完成的任务等级分布。
2. 反馈效率
- 首次有效反馈时间;
- 局部检查与完整 CI 时长;
- 失败信息可直接定位问题的比例;
- 从失败到修复的平均循环次数。
3. 交付质量
- 合并后缺陷率和回滚率;
- 架构违规数量;
- 测试逃逸率;
- 安全与兼容性问题数量。
4. 人类负担
- 每个 Agent 任务的审查时间;
- Reviewer 重复反馈比例;
- 环境与工具问题导致的阻塞时间;
- 从需求提出到可验证 PR 的周期。
初期最值得优化的通常不是“完全无人干预率”,而是首次有效反馈时间和重复人工指导次数。它们能直接暴露 Harness 的断点。
十、一套可执行的 30 天落地路线
第 1 周:跑通一个最小闭环
- 选择 10 个历史小任务作为基准集;
- 统一
setup、check、test-changed命令; - 建立短小的根
AGENTS.md; - 记录每次人工介入的原因。
交付标准:全新工作区里,Agent 可以独立完成至少一类低风险任务。
第 2 周:消除知识与架构黑箱
- 补模块地图、领域说明和关键 ADR;
- 给高频目录增加就近指引;
- 将三条最高频架构规则变成自动检查;
- 为失败输出增加可操作提示。
交付标准:Agent 不依赖口头补充即可找到入口,并能在数分钟内获得首轮反馈。
第 3 周:补齐真实行为验证
- 提供一键启动的本地集成环境;
- 建立固定账号和种子数据;
- 接入浏览器自动化、截图、日志和 Trace;
- 统一保存验证证据。
交付标准:至少一个跨 UI/API/数据层的任务能由 Agent 自行观察并验证。
第 4 周:建立分级自治与度量
- 按目录和变更类型定义风险等级;
- 明确哪些步骤自动、哪些必须审批;
- 建立任务成功率、人工介入和反馈耗时看板;
- 每周从失败案例反推一个 Harness 改进项。
交付标准:低风险任务可稳定达到 L2;团队能用数据回答下一项 Harness 投资应该放在哪里。
结语
Harness Engineering 的核心,不是教 Agent 写出更多代码,而是重构软件工程,使正确行为更容易被发现、执行和验证。
当上下文只存在于人的脑中,Agent 就会反复追问;当架构只存在于文档中,它就会反复越界;当测试无法复现真实行为,它就只能宣称成功;当失败没有清晰证据,人类就必须接管调试。
真正可扩展的做法,是把隐性知识迁入仓库,把团队约定编译成约束,把运行状态转化为可观察证据,再用逐级授权扩大自治范围。最终得到的不只是一个更好用的 AI 编码工具,而是一套对人和 Agent 都更清晰、更可靠的软件生产系统。
参考:OpenAI,Harness engineering: leveraging Codex in an agent-first world。本文是基于其理念整理的独立工程实践方案,并非原文翻译。