
如果你最近频繁刷到 Harness Engineering,这不是错觉。2026 年 2 月,OpenAI 先把它作为 agent-first 开发里的核心方法公开讲明白;3 月,Anthropic 又把长任务里的 reset、handoff 和生成/评估分离写成工程经验;到了 4 月,Martin Fowler 也专门跟进,把这套思路整理成更稳定的工程语言。
这个词突然变热,不是因为技术圈又发明了一个新名词,而是因为越来越多团队已经踩到同一个坑:模型现在当然会写代码,但它并不会天然稳定交付。项目一复杂,AI 很快就会暴露出老问题:同样的错误反复出现,任务一长就断片,换个会话就得重新解释背景,最后人花的大部分时间,不是在推进需求,而是在替模型补上下文、补规则、补验证。
Harness Engineering 要解决的,正是这层“会写”到“能交付”之间的落差。它关心的不是怎么把提示词再润色一轮,而是怎么把项目地图、计划、验证、交接、回滚真正放进仓库,变成可执行、可复检、可接力的工件。
所以这篇文章不准备再从抽象概念兜圈子,而是直接给你一套能落地的最小配置:仓库怎么摆、AGENTS.md 怎么写、ARCHITECTURE.md 写什么、verify.sh 怎么做、什么时候必须写计划、任务做到一半怎么交接。目标只有一个:让你今天就能把自己的 Harness Engineering 配起来。
先说结论:普通人最该先做的,不是上工具,而是把仓库变成系统记录
很多人一聊 Harness Engineering,就先去看多代理、工作流编排、会话恢复、权限系统。那些东西当然重要,但对大多数开发者来说,第一步其实没那么复杂。
最该先做的是一件更朴素的事:让仓库本身能承载任务状态。也就是把“项目怎么跑、怎么验、改到哪一步了、下一步做什么、哪些地方别乱动”这些信息,从聊天记录和脑子里,搬到版本库里。
只要这一步没做,再强的模型、再花的工作流层,最后也会变成新的混乱来源。
30 分钟先搭出最小骨架
别一上来就想把整套系统做满。先把下面这套骨架建出来,已经能解决大多数“AI 会写,但总写不稳”的问题。
repo-root/
AGENTS.md
ARCHITECTURE.md
PLANS.md
docs/
index.md
exec-plans/
active/
completed/
runbooks/
verify.md
scripts/
verify.sh
.github/workflows/
verify.yml
这一套结构最关键的不是“看起来专业”,而是职责清楚:
- AGENTS.md 负责当地图,不负责当百科全书。
- ARCHITECTURE.md 负责讲边界、分层和不变量。
- PLANS.md / exec-plans 负责承接长任务状态。
- docs/runbooks/verify.md 负责告诉人和模型:到底怎么启动、怎么验证、怎么回滚。
- scripts/verify.sh 负责把所有验证收口成一个入口。
第一份 AGENTS.md,就该长这样
很多人写 AGENTS.md 最大的问题,是总想“一次写全”。结果文档越来越长,谁都不爱看,过几天还会过时。
AGENTS.md 最好的写法,就是只写地图、入口和硬规则。下面这份可以直接拿去改:
# AGENTS.md
## 目标
本仓库采用 harness engineering 方式工作:把约束、计划、验证与交接写进仓库工件,让 Codex 在没有外部上下文的情况下也能稳定推进任务。
## 先读什么
- 架构总览:./ARCHITECTURE.md
- 计划规范:./PLANS.md
- 文档索引:./docs/index.md
- 执行计划:./docs/exec-plans/active/
- Runbook:./docs/runbooks/
## 工作流约定(PBV)
- Planner:先产出或更新 ExecPlan,把验收标准写清楚
- Builder:严格按已批准的 Plan 修改代码
- Verifier:独立运行 verify 流水线并记录结果
## 什么情况下必须写 ExecPlan
- 需要跨多个文件或模块修改
- 需要迁移、重构、引入新依赖
- 影响安全、权限、支付、发布、数据模型
- 预计超过 30 分钟,或会跨多次会话完成
## 一键验证
- 本地:./scripts/verify.sh
- CI:同样调用 verify.sh
- verify 不绿,不允许标记完成
## 受保护路径
- vendor/**, third_party/**, generated/**
- infra/prod/**, .github/workflows/**
- secrets/**, *.key, *.pem, .env*
## 输出与交接
- 每次停下前都要更新 Progress / Decision Log
- 每个长任务都要留下 Handoff
- 记录:已做、未做、如何复现、如何验证、风险与下一步
这份模板的重点,不是写得多漂亮,而是它能让模型一进仓库就知道:该先读哪里、按什么流程做、什么叫完成、哪些地方别乱碰。
ARCHITECTURE.md 不要讲理想状态,只写真实边界
很多项目的架构文档之所以没用,不是因为没人写,而是因为写得太虚。真正有用的架构文档,应该是模型和新同事都能拿来判断“这次改动有没有越界”的。
下面这份同样可以直接改:
# ARCHITECTURE.md
## 总览
- 核心业务域:
- domain-a: 负责...
- domain-b: 负责...
- 关键入口:
- API: <path>
- Web/UI: <path>
- CLI/Jobs: <path>
## 分层与依赖方向
建议层次:
- types/ → config/ → repo/ → service/ → runtime/ → ui/
规则:
- 依赖只能向前
- 横切关注点必须走统一入口
- 任何跨域调用都必须经过显式边界
## 关键不变量
- 禁止裸 console.log / print
- 类型与 schema 命名必须统一
- 单文件默认不超过 500 行
- 敏感数据不得写日志
- 外部 IO 必须做校验与限流
## 如何验证架构没有被破坏
- 结构测试命令:make structural-test
- 失败修复指引:见 docs/runbooks/verify.md
## 变更策略
- 小改动:轻量 plan + verify
- 大改动:ExecPlan + milestone + 回滚路径
这里最重要的是两句话:边界要能被验证,不变量要能被执行。 如果它只是写在文档里,最后还是会失效。真正稳定的做法,是后面再把这些规则升级成结构测试、lint 或 CI。
verify.sh 必须只有一个入口
很多团队明明有 lint、有单测、有构建命令,最后还是经常“看起来改好了,实际一跑全崩”。原因往往不是没验证,而是验证太分散。
最省事的办法,就是收口到一个命令。下面这份多栈版 verify.sh 可以直接当起点:
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$ROOT"
echo "==> verify: repo=$(basename "$ROOT") pwd=$ROOT"
run_if() {
local desc="$1"; shift
local cmd="$*"
echo "---- $desc"
bash -lc "$cmd"
}
if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
echo "==> git status (short)"
git status --porcelain || true
fi
if [[ -f package.json ]]; then
PM=""
if command -v pnpm >/dev/null 2>&1; then PM="pnpm";
elif command -v yarn >/dev/null 2>&1; then PM="yarn";
else PM="npm"; fi
run_if "node: install (best-effort)" "$PM -s install || true"
run_if "node: lint" "$PM -s run lint"
run_if "node: typecheck" "$PM -s run typecheck || $PM -s run tsc -- --noEmit"
run_if "node: unit" "$PM -s run test || true"
run_if "node: build" "$PM -s run build"
run_if "node: e2e (optional)" "$PM -s run test:e2e || true"
fi
if [[ -f pyproject.toml || -f requirements.txt ]]; then
if command -v uv >/dev/null 2>&1 && [[ -f pyproject.toml ]]; then
run_if "python: uv sync (best-effort)" "uv sync --extra dev || true"
run_if "python: ruff" "uv run ruff check . || true"
run_if "python: pytest" "uv run pytest -q || true"
else
run_if "python: ruff (if installed)" "ruff check . || true"
run_if "python: pytest (if installed)" "pytest -q || true"
fi
fi
if [[ -f go.mod ]]; then
run_if "go: test" "go test ./..."
fi
if [[ -f composer.json ]]; then
run_if "php: composer install (best-effort)" "composer install --no-interaction || true"
run_if "php: lint (optional)" "composer lint || true"
run_if "php: unit (optional)" "composer test || true"
fi
echo "==> verify: done"
这份脚本不追求一步到位,它的意义是先把“完成”定义成同一个动作。之后你再慢慢把 flaky 项、结构测试、手测 runbook、预发布检查一点点加进去。
什么时候必须写计划,不要靠感觉
Harness Engineering 最容易被忽略的一点,是“计划必须工件化”。任务一复杂,如果还靠聊天记录和临场发挥,后面一定会乱。
最简单的规则就是:满足下面任意一条,就必须写 ExecPlan。
- 需要跨多个文件或模块改动
- 涉及迁移、重构、引入新依赖
- 影响安全、权限、支付、发布、数据模型
- 预计会超过 30 分钟,或者会跨多次会话完成
ExecPlan 不需要写成论文,但必须保证一件事:换一个全新的上下文,甚至换一个人,只靠这份文件也能继续做下去。
一份能接力的 Handoff,至少要包含这些字段
很多任务之所以做着做着断掉,不是因为不会写代码,而是因为没人把“当前状态”整理成能接手的东西。下面这份 Handoff 模板,已经足够实用:
# Handoff: <任务名>
## 当前状态概览
- 目标:一句话说明要解决什么
- 当前进度:完成到哪个 milestone / 哪个 commit
- 是否可安全合并:是 / 否(原因)
## 已完成(带证据)
- 改动点:
- 关键 commit / branch:
- 通过的验证:
- lint:
- typecheck:
- unit:
- e2e:
- manual:
## 未完成与下一步
- 命令:
- 文件路径:
- 预期结果 / 验收点:
## 复现与验证 runbook
- 如何启动:
- 如何复现问题:
- 如何验证修复:
## 风险与注意事项
- 可能的回归面:
- 兼容性 / 迁移风险:
- 回滚策略:
## 需要人类判断的问题
- 可选方案:
- 推荐方案与理由:
只要这个东西写到位,你就会明显感觉到:长任务不再那么依赖“这次对话还记不记得前情提要”。
给普通人的 PBV 用法:先强制角色切换,再谈多代理
很多人一看到 Planner、Builder、Verifier,就以为非得上多代理编排。其实完全不用。单代理也能先跑起来,关键是强制角色切换。
- Planner 阶段:只允许写计划、补验收、标边界,不许直接开改。
- Builder 阶段:只按计划改代码,尽量保持改动最小、可验证、可回滚。
- Verifier 阶段:独立跑 verify,按 runbook 手测,把失败证据写回计划或 handoff。
这一步做熟之后,你再考虑把不同角色拆到不同 worktree、不同 agent,收益才会真正出来。
存量项目,照着这 7 天清单接管就够了
如果你面对的是老项目,先别急着让模型写大功能。先用一周时间,把最关键的承载层补起来。
- 第 1 天:建 AGENTS.md、ARCHITECTURE.md、docs/index.md、docs/runbooks/verify.md,顺手把最可靠的一套本地命令封进
./scripts/verify.sh。 - 第 2 天:把真实模块边界、关键入口、依赖方向补进 ARCHITECTURE.md,只写当前真实情况,不写理想蓝图。
- 第 3 天:挑一个低风险任务,第一次完整跑 PBV:计划 → 实现 → 验证 → handoff。
- 第 4 天:回头看前三天最常见的一个错误,把它升级成脚本、lint 或 CI 规则,别再只写在文档里。
- 第 5 天:让 docs/index.md 真正成为索引,至少能列出 runbooks、active ExecPlans 和关键设计文档。
- 第 6 天:试一次 git worktree,把一个小任务放到独立 worktree 里跑验证,感受并行隔离的价值。
- 第 7 天:做一次盘点,记录 verify 通过率、返工次数、任务重启是否还能继续、哪些规则最该机械化。
这一周做完,你的项目就已经不是“全靠聊天推进”的状态了。
什么时候再上 oh-my-codex 或 OpenHarness?
顺序别反。先把 repo-native harness 配起来,再考虑更重的外部能力。
- 如果你现在最大的问题还是“任务离开聊天历史就接不上”,先补 ExecPlan 和 Handoff。
- 如果你最大的问题还是“总有人没跑验证就说做完了”,先把 verify 和 runbook 收口。
- 如果你已经把这些都做稳了,瓶颈开始变成并行开发、长程恢复、权限治理、会话状态管理,这时候再看 oh-my-codex 或 OpenHarness,才是真收益。
最后给你一个最小执行清单
如果你今天只打算做 5 件事,就做这 5 件:
- 在仓库根目录建
AGENTS.md - 补一份只写真实边界的
ARCHITECTURE.md - 把本地验证收口成
./scripts/verify.sh - 给长任务建立
docs/exec-plans/active/ - 每次停下前都写一份 Handoff
你会很快发现,Harness Engineering 真正有价值的地方,不是“又学了一个新概念”,而是从这一刻开始,你的 AI 编程终于不再只靠上下文运气,而是开始靠系统推进。
参考资料
- OpenAI:Harness engineering: leveraging Codex in an agent-first world
- OpenAI Cookbook:Using PLANS.md for multi-hour problem solving
- Anthropic:Harness design for long-running application development
- Anthropic:Effective harnesses for long-running agents
- Martin Fowler:Harness engineering for coding agent users
- oh-my-codex
- OpenHarness


评论