Harness 实战:让 AI Agent 可靠地写代码

模型是引擎,Harness 是车——最好的引擎没有方向盘和刹车也没用。

GitHub 仓库:harness · 中文 README


为什么做这个项目

2025 年,我们学会了让 AI 写代码。2026 年,我们发现真正的难题不是写代码,而是持续、可靠地写代码。

让 Claude Code 完成一个小任务很容易。让它连续完成 20 个任务、跨越多个会话、不偏离方向、不降低质量——这才是真正的工程挑战。

我们都见过这些失败模式:

  • Agent 给自己打高分,实际上测试根本没覆盖验收标准
  • 上下文窗口快满时,Agent 开始”草草收工”
  • 前一个会话留下的 bug,下一个会话在上面继续堆代码
  • Prompt 说了”先写测试”,Agent 微笑着跳过了这步
  • 占位符 TODO 藏在接口后面,表面上代码”能跑”

这些不是 Agent 的”偶尔失误”。这是系统性的失败模式,需要系统性的解决方案。

Harness 就是这个解决方案。它不是一个库,不是一个框架——它是一套你放进任何项目的文件,让 AI Agent 像靠谱的工程师一样工作,而不是像实习生一样需要盯着。


核心洞察:从 GAN 到 Agent 工程

让写代码的和审代码的互相不认识

Harness 的核心思想借鉴自 GAN(生成对抗网络)

在 GAN 中,Generator 生成,Discriminator 判别,两者对抗产生高质量输出。我们把同样的思路用到了 Agent 开发上——如果让同一个 Agent 既写代码又评估代码,它永远觉得自己写得不错。这不是 Agent 的缺陷,这是人类也有的认知偏差:沉没成本效应

所以 Harness 把”写”和”评”拆到两个完全独立的上下文窗口中:

                    ┌──────────────┐
                    │   Planner    │  把模糊需求变成结构化计划
                    └──────┬───────┘

                    ┌──────▼───────┐
              ┌────►│  Generator   │  一次一个任务,TDD 实现
              │     └──────┬───────┘
              │            │
              │     ┌──────▼───────┐
    FAIL      │     │  Evaluator   │  独立会话,怀疑论审查
    (max 2x)  │     └──────┬───────┘
              │            │
              │       PASS │ FAIL
              │            │
              └────────────┘

Generator(生成器)负责写代码,遵循 TDD,跑测试。它有完整的编辑权限,可以创建文件、运行命令。

Evaluator(评估器)在全新的 Claude Code 会话中启动,没有看过 Generator 的实现过程。它只能读代码、跑验证、看结果。它的默认心态是”大概是有问题的”——5 个维度全部通过,才给 PASS。

任何一项 FAIL,整体 FAIL。Generator 收到反馈后修复,再由全新的 Evaluator 重新审查。最多 2 次重试,防止无限循环。

一个真实的例子

我们在自己的项目上测试了这个流程。任务是给首页加一个”回到顶部”按钮,我们故意在代码里埋了一个 bug——把滚动检测条件写反了(scrollY < 200 应该是 scrollY > 200)。

结果:

  1. Generator 完成了实现,代码能跑,npm run build 通过
  2. Evaluator 在全新会话中审查代码,发现条件反转——FAIL
  3. Generator 收到反馈,修复条件为 scrollY > 200
  4. 新的 Evaluator 重新审查——PASS
  5. 计划自动标记为完成,进度笔记记录了整个过程

人工介入:零。整个 FAIL → Fix → Re-evaluate → PASS 循环自动完成。


两层防护:概率 + 确定

为什么一层不够?

光有 Agent 层面的对抗还不够。Prompt 是概率性的——你告诉 Agent “提交前跑 lint”,它 90% 的时候会照做,但那 10% 的偏移就是 bug 的来源。

所以 Harness 加了第二层:Hook 确定性护栏

┌─────────────────────────────────────────────────────┐
│          概率层(Skill / Prompt)                      │
│  "请遵循 TDD"  "请先验证基线"  "请不要跳过测试"          │
├─────────────────────────────────────────────────────┤
│          确定层(Hook / 机械执行)                      │
│  pre-commit: 代码文件? → lint + typecheck             │
│  pre-push:   → 完整验证套件                            │
│  post-edit:  → 即时语法检查                            │
└─────────────────────────────────────────────────────┘

Skill 告诉 Agent 应该做什么——这是概率性的,有时候会被忽略。

Hook 确保关键步骤不被跳过——这是确定性的,不管 Agent 怎么想,代码提交前 lint 一定会跑。

这不是二选一,而是两层叠加。就像飞机有自动驾驶(概率)也有机械备份(确定)——两者共存才安全。

三种 Hook 护栏

Hook触发时机做什么为什么
pre-commitgit commit检测暂存文件类型,仅对代码文件跑 lint/typecheck文档提交不需要跑 lint,节省时间
pre-pushgit push完整验证套件代码离开本地前的最后一道关
post-editWrite/Edit即时语法检查不等到验证阶段才发现语法错误

所有 Hook 从 config.json 读取设置,可以逐项启用/禁用。没有黑盒,一切可控。


七条设计哲学

这些不是我们凭空想出来的——它们提炼自 Anthropic(两篇)、OpenAI、Geoffrey Huntley 的四篇研究论文,加上我们自己的实践验证。

1. 不信任,要验证

Agent 的自我评估永远过于乐观。Evaluator 在独立的上下文窗口中运行,没有 Generator 的沉没成本压力,默认假设”大概是有问题的”。

它按 5 个维度打分:

维度检查什么
验证通过npm testmake check 等项目验证命令是否通过
验收标准计划中列出的每一条标准是否都满足
测试覆盖新增功能是否有对应的测试
无占位符代码中没有 TODOFIXMENotImplementedError...
TDD 合规是否先写了测试再实现(后端任务)

任何一项 FAIL,整体 FAIL。

2. 概率 + 确定 = 完整防护

Skill 告诉 Agent 该做什么,Hook 确保关键步骤不被跳过。这是 Harness 最核心的创新——业界首次将 Claude Code Hook 系统性地用于 Agent 质量保障

3. 上下文是稀缺资源

每个会话只做一件事。状态通过 JSON 计划和 Markdown 笔记在会话间传递,而不是塞进上下文窗口。

Anthropic 发现了一个叫 Context Anxiety(上下文焦虑)的现象:当上下文快满时,Agent 会开始”草草收工”。解决方案不是给更大的窗口,而是管理好你已有的窗口。

4. 仓库即真相

Agent 访问不到的信息等于不存在。所有决策、架构、需求都推入仓库。CLAUDE.md 是地图而非百科——30 行以内,指向更深的文档。

这来自 OpenAI 的实践:在 Codex 百万行生产代码的经验中,他们发现 AGENTS.md 越短越好,因为 Agent 不需要记住所有信息,只需要知道去哪里找。

5. 验证即反压(Backpressure)

lint、typecheck、测试套件构成快速反馈回路。回路必须快——慢验证 = 少迭代。Agent 在有限时间内能尝试的修复就更少。

Geoffrey Huntley 用一个极端例子证明了这点:他用 $297 完成了一个 $50,000 的合同,关键就在于把验证回路压缩到秒级。

6. Git 是安全网,不是仪式

每个任务完成后提交。不是因为”应该提交”,而是因为恢复只需要 git reset --hard。当 Agent 搞砸时(它会的),你需要一个可靠的回退点。

7. 简化,再简化

每个 Harness 组件都编码了一个假设:“模型不能自己做到这个”。模型在进步,假设在过时。定期检查:这个组件还有必要吗?

三行重复代码好过一个过早抽象。今天需要 Hook 保障的东西,明年可能模型原生就支持了。


架构全景

harness/
├── .claude/
│   ├── settings.json              Hook 配置(确定性护栏)
│   └── skills/harness/            交互式工作流技能
│       ├── SKILL.md               入口:分类 → 澄清 → 计划 → 执行 → 评估
│       └── references/            计划格式、会话协议、评估指南
├── .harness/
│   ├── config.json                唯一需要编辑的文件
│   ├── runner.py                  无头执行器(CI / 批量处理)
│   ├── evaluator.py               怀疑论评估器(独立会话)
│   ├── hooks/                     Hook 脚本
│   │   ├── pre-commit-check.sh    仅代码文件触发 lint/typecheck
│   │   ├── pre-push-verify.sh     推送前完整验证
│   │   └── post-edit-check.sh     编辑后即时语法检查
│   ├── plans/                     任务计划(JSON)
│   ├── eval_feedback/             评估判定结果
│   └── progress.md                跨会话记忆
├── docs/
│   ├── best-practices.md          设计原则
│   └── research/                  四篇原始研究论文
└── CLAUDE.md                      Agent 入口(地图,非百科)

关键组件

config.json — 唯一需要编辑的文件

{
  "verify_cmd": ["npm", "test"],
  "source_dirs": ["src/"],
  "test_dirs": ["src/__tests__/"],
  "hooks": {
    "pre_commit_lint": true,
    "pre_commit_typecheck": true,
    "pre_push_verify": true
  }
}

不管是 Go 后端、Node.js 前端、Rust CLI 还是 Python 数据管道——改 config.json 就行,不需要重写 Harness。

runner.py — 无头执行器

用于 CI 流水线或批量处理,不需要人工介入:

# 执行计划中的下一个任务
python3 .harness/runner.py --plan .harness/plans/fix-login.json

# 循环执行所有任务
python3 .harness/runner.py --plan .harness/plans/fix-login.json --loop

# 只看状态,不执行
python3 .harness/runner.py --status

SKILL.md — 交互式工作流

在 Claude Code 中直接使用,适合日常开发。贴入一段 bug 报告或功能需求,Skill 自动引导完整流程:

你贴入反馈


分类 → 归类为 bug / feature / improvement / chore


澄清 → 提出针对性问题(最多 2 轮)


计划 → 创建 .harness/plans/{slug}.json


执行 → 验证基线 → TDD 实现 → 验证 → 评估
    │            ↑                         │
    │            └── FAIL (最多 2 次) ──────┘

完成 → 提交,更新进度笔记

通用性:一套 Harness,所有项目

Harness 不绑定任何语言或框架。项目类型的差异全部通过 config.json 吸收:

项目类型verify_cmdsource_dirs说明
Astro 前端["npm", "run", "build"]["src/"]本站使用的配置
Go 后端["make", "check"]["cmd/", "internal/"]lint + test + build
Rust CLI["cargo", "test"]["src/"]Cargo 原生测试
Python 数据["pytest"]["src/"]pytest 驱动
Node.js API["npm", "test"]["src/", "lib/"]Jest / Vitest

Hook 脚本自动检测项目类型(Makefile / package.json / pyproject.toml / Cargo.toml),无需手动配置。


研究基础

Harness 站在巨人的肩膀上。我们从四篇文献中提炼出了共同的设计原则,并在此基础上加入了 Hook 确定性护栏——这是我们的原创贡献。

文献核心贡献来源
Harness Design for Long-Running AppsGenerator + Evaluator 对抗模式Anthropic, 2026.3
Effective Harnesses for Long-Running Agents两阶段 Agent 架构;Context AnxietyAnthropic, 2025.11
Harness Engineering for Codex仓库即真相;AGENTS.md 是地图OpenAI, 2026.2
The Ralph Wiggum Technique一次一个任务;验证即反压Geoffrey Huntley, 2025.7

更深入的文献交叉解读,请参阅 Harness Engineering 学习指南


十大共识原则

从 Anthropic、OpenAI 和社区的实践中,我们提炼出十条跨团队共识的设计原则:

  1. 上下文管理 — 窗口是稀缺资源,不是垃圾桶。每次会话聚焦一件事。
  2. 结构化交接 — 会话间通过 JSON 计划 + Markdown 笔记传递状态,不靠上下文窗口记忆。
  3. 反馈回路 — 验证必须快。慢反馈 = 少迭代 = 低质量。
  4. 任务分解 — 大需求拆成小任务,每个任务有明确的验收标准。
  5. 生成与评估分离 — 写代码的和审代码的必须互相不认识(独立上下文)。
  6. Harness 随模型进化 — 定期审视每个组件的必要性。
  7. 仓库即真相 — Agent 访问不到的等于不存在。
  8. 渐进式披露 — 不要一次性把所有信息塞给 Agent。
  9. 确定性护栏 — Hook 保障 Prompt 覆盖不到的场景。
  10. Git 是安全网 — 每个任务提交一次,回退永远有保障。

快速上手

前置条件

安装

Harness 不是 npm 包——它是一组你放入项目的文件:

# 克隆并复制到你的项目
git clone https://github.com/anxiong2025/harness.git /tmp/harness
cp -r /tmp/harness/.claude /tmp/harness/.harness /tmp/harness/CLAUDE.md your-project/

# 编辑配置
vim your-project/.harness/config.json

30 秒开始使用

cd your-project

# 1. 配置你的项目验证命令
# 编辑 .harness/config.json 中的 verify_cmd

# 2. 交互模式:打开 Claude Code,贴入需求
# Claude 自动进入 harness 工作流

# 3. 无头模式:批量处理
python3 .harness/runner.py --plan .harness/plans/your-plan.json --loop

这不是银弹

Harness 不会让 AI Agent 变得完美。它让 Agent 的失败变得可预测、可检测、可恢复

  • 可预测 — 知道 Agent 会在哪里出错(自我评估过高、上下文焦虑、跳过步骤)
  • 可检测 — Evaluator 在独立上下文中审查,Hook 在确定性层面拦截
  • 可恢复 — 每个任务一个 commit,回退成本几乎为零

这就够了。完美不是目标,可靠才是。


GitHub 仓库:harness — 记得 Star

完整中文 README:README.zh-CN.md