AI Coding Harness 讲义(后端开发工程师版)
一句话:Harness 是把「希望 AI 做对」变成「系统保证 AI 做对」的整套工程约束。 内容脉络:心智模型 → SDD → TDD → AGENTS.md → Lint → CI/CD → Ralph → 完整拼图
0. 心智模型:先搞懂 harness 是什么
为什么 AI 编码需要 harness
AI 编码 Agent(Codex / Claude Code / Cursor)很强:能读整个仓库、改代码、跑命令。但它有三个固有毛病:
- 会偏离:做着做着就按自己的想象发挥,不按你的需求
- 会自信地错:给出看起来很对的代码,实际有 bug
- 会自证:自己改完自己跑测试,然后说"通过了"
单靠 prompt 约束 → 看运气;靠系统约束 → 可预期。Harness 就是后者:让 Agent 在跑道内跑,越界就被护栏拦下。
Harness 的三层结构
| 层次 | 干什么 | 组件 |
|---|---|---|
| 指令层(Input) | 告诉 Agent 做什么、怎么做 | SDD 规格、AGENTS.md、instructions.md |
| 验证层(Output) | 客观检查做对没有 | TDD、Lint、CI/CD |
| 编排层(Loop) | 拆任务、循环执行、记进度 | Ralph |
两条核心原则
- 确定性机制 > 依赖 Agent 自觉:能机器验证的(lint、test、CI)不要靠 prompt 要求
- 每层只管一件事:指令层管"怎么做",验证层管"对不对",编排层管"推进到哪了"
1. SDD:规格驱动开发(先写规格,再写代码)
是什么
Spec-Driven Development:先产出规格(spec / PRD),再让 AI 基于规格生成实现。规格是单一事实来源,代码只是规格的一种实现。
解决什么问题
- 一次性 prompt 生成的代码不可审查、不可复用:需求全在对话里,换会话就丢
- 没有规格,Agent 按自己的想象实现,偏了就白干
- 规格把「做什么、不做什么、怎么验收」固化下来,人审规格而不是逐行审代码
怎么落地
- 写
spec.md:目标、范围(含"不做")、接口/数据结构、验收标准 - 让 Agent 先读规格 → 输出实现计划 → 确认后再编码
- 规格入库、版本化,像代码一样评审
- 把验收标准转成可执行测试(衔接下一节 TDD)
示例
spec.md 最小模板:
| |
对应 prompt:
“先读 spec.md,输出实现计划和接口设计,确认后再动手,不要直接写代码。”
常见坑
- 规格写太细 → Agent 变成打字员;写太粗 → 等于没写。粒度到「接口 + 验收标准」即可
- 规格和代码不同步 → 改代码必须同步改规格,否则下一轮 Agent 按旧规格重做
2. TDD:测试驱动开发(先写测试,再写实现)
是什么
红-绿-重构:先写会失败的测试 → 实现到测试通过 → 重构。测试通过 = 客观的 done。
解决什么问题
- Agent 说"做完了",你怎么知道真的做完了?测试通过是唯一客观证据
- 防回归:Agent 下一轮改代码时,旧测试自动拦住破坏
- SDD 里写的验收标准,正好翻译成测试
怎么落地
- 让 Agent 按规格的验收标准先写测试
- 运行测试,确认失败(红)——证明测试真的在测
- 实现功能,测试全绿
- 重构,保持全绿
- 让 Agent 汇报:新增哪些测试、覆盖哪些路径、验证输出
示例
“按 spec.md 的验收标准先写测试,运行确认失败;再实现到全部通过;最后重构。逐条总结每个验收标准对应的测试和结果。”
| |
常见坑
- Agent 会删测试或改断言让测试变绿:关键测试文件要么人审,要么配置为 Agent 不可改
- 只测快乐路径:验收标准必须含边界和异常(422、401)
- 覆盖率不是目的:关键路径覆盖才是
3. AGENTS.md:给 Agent 的岗位说明书(指令层)
是什么
仓库根目录的 AGENTS.md,Agent 每次启动自动读取的持久化指令:项目命令、工作规则、代码规范、禁忌。
解决什么问题
- 不用每次重复解释项目怎么跑、规范是什么
- 团队统一:任何人的新会话行为一致
- 把踩过的坑沉淀下来:Agent 每犯一次错,就加一条规则
怎么落地
- 用
/init生成骨架,再手工精简 - 内容四块:项目命令 / 工作规则 / 代码规范 / 验收标准
- 保持简短:默认上限 32 KiB,只写高频规则
- 分层:
~/.codex/AGENTS.md(个人)→ 仓库根(团队)→ 子目录(专项),越近越优先
示例
| |
常见坑
- 规则膨胀:写 50 条没人(模型也)记得住 → 只沉淀反复犯的错
- 与 lint/CI 重复:能机器执行的(格式)交给 lint,AGENTS.md 只写机器管不了的判断
4. Lint:代码规范的机器裁判(验证层)
是什么
静态检查:格式、命名、明显 bug、安全弱点的自动扫描。常见工具:ESLint / Ruff / golangci-lint / Checkstyle。
解决什么问题
- Agent 生成的代码风格必然不一致 → 机器强制统一
- 明显错误(未用变量、空 catch、硬编码密钥)提前拦下
- 比 code review 便宜:机器先扫,人只看机器看不出的
怎么落地
- 配好项目 lint 命令,写进 AGENTS.md
- 三层执行:本地 → pre-commit → CI
- Agent 改完必须跑 lint 并修到通过
示例
| |
常见坑
- 别为了"让 AI 通过"乱关规则:lint 规则是团队共识的固化
- 只 lint 不 test:lint 管风格,逻辑正确性交给测试
5. CI/CD:最后的门禁(验证层)
是什么
把 lint + test + build + 类型检查自动化进流水线,PR 合并前必须全绿。
解决什么问题
- Agent 本地可能"说谎":改完没跑、或跑的是旧代码 → CI 从仓库状态重新跑一遍,是中立裁判
- 强制验证不可跳过:门禁面前人人(agent 也)平等
- 让 Agent 的改动走和人类一样的评审通道
怎么落地
- PR 触发流水线:lint → test → build(可选加类型检查、AI 审查)
- Agent 完成改动后开 PR,CI 结果就是"验证结果"
- 失败必须修到绿,不许 bypass
- 高级:接入
codex review,PR 自动 AI 审查
示例
GitHub Actions 最小配置:
| |
常见坑
- CI 与本地环境不一致 → 锁版本(package-lock.json、go.sum)、用容器
- 测试不稳定(flaky)→ 先修 flaky 再谈门禁,否则 Agent 和人都会被带偏
- CI 只验证"没坏",不验证"符合规格":规格符合性靠测试 + 人审
6. Ralph:把上面串起来的循环引擎(编排层)
是什么
开源 CLI harness:以 PRD 为输入,循环驱动编码 Agent(Codex / Claude / Cursor)逐任务完成,自动记录进度。灵感来自 Geoffrey Huntley 的 “Ralph loop” 方法论。
解决什么问题
- 手动一轮轮 prompt 不可扩展:大项目几十个任务,人盯不过来
- Agent 会话会"忘":Ralph 把状态落到磁盘,每次新会话先读进度再继续
- 把 SDD(PRD 规格)+ Agent(实现)+ 验证(你配的命令)串成闭环
怎么落地
- 安装并初始化,选择 agent(codex)
- 维护 PRD 任务清单
ralph run循环:Agent 查进度 → 做当前任务 → 记进度 → commit → 下一个- 每轮 Agent 跑你项目里的验证命令(衔接 lint / test / CI)
- 项目级
instructions.md给 Agent 加项目规则(Ralph 版 AGENTS.md)
示例
| |
常用配置(~/.ralph/config.json):agent、maxRetries、agentTimeoutMs(单轮超时)、stuckThresholdMs(卡住判定)、webhookUrl(完成通知)。
常见坑
- Ralph 驱动的是"Agent 自行验证":验证命令必须真实存在,且 CI 兜底,否则又是自证陷阱
- 迭代次数用尽 ≠ 完成:跑完看 task list 和 CI 结果
- 长跑要配超时和通知,别半夜干等
7. 完整拼图与落地路线图
完整流程
需求 → SDD 规格 → AGENTS.md 约束 → Ralph 拆任务驱动 Agent
→ TDD 测试 → Lint → CI/CD 门禁 → 合并上线
每一层失败时的处置:
| 层 | 失败表现 | 处置 |
|---|---|---|
| SDD | 需求漂移 | 回到规格,改规格再改代码 |
| AGENTS.md | Agent 违反规范 | 加规则,沉淀 |
| TDD | 测试红 | Agent 修到绿,不许删测试 |
| Lint | 风格/低级错误 | Agent 修到通过 |
| CI/CD | 门禁红 | 阻断合并,修到绿 |
| Ralph | 卡住/超时 | 配置超时重试,人工介入 |
最小可行 Harness(一周落地)
- 第 1 天:AGENTS.md(命令 + 规则)+ lint 配好
- 第 2–3 天:CI 门禁(lint + test + build)
- 第 4 天:让 Agent 走 SDD 闭环(先规格后代码)
- 第 5 天:用 Ralph 跑一个真实小项目
- 持续:把 Agent 反复犯的错写回 AGENTS.md / 测试
8. 常见坑与原则(总结)
- 自证陷阱:Agent 改完自己跑测试不算最终验证,CI 说了算
- 规则靠人肉:能自动化的(lint / test / CI)别只靠 prompt
- 权限与沙箱:给 Agent 最小权限,危险命令(rm、push)要审批
- 密钥安全:AGENTS.md / 配置里的密钥绝不入库,用环境变量
- 人审不可省:Agent 负责快,人负责方向和最终判断
- 迭代式加固:不是一次性搭完,而是"每翻一次车,加一条规则 / 一个测试"