Harness Engineering:设计让 Agent 正确写代码的环境
Harness Engineering:设计让 Agent 正确写代码的环境
程序员不写代码。设计环境,让 Agent 在安全边界内自主完成所有编程工作。
软件工程的三种模式
Prompt Engineering → Agentic Engineering → Harness Engineering
(写提示词) (设计工作流) (设计环境)
| 模式 | 程序员做什么 | 核心关注点 |
|---|---|---|
| Prompt Engineering | 写提示词,指导 AI 输出 | ”怎么说 AI 才能听懂” |
| Agentic Engineering | 设计工作流,让 Agent 自主执行 | ”让 AI 完成任务” |
| Harness Engineering | 设计环境约束,让 Agent 在安全边界内工作 | ”让 AI 正确地完成任务” |
Harness Engineering 是第三阶段的核心:程序员从”写代码”转变为”设计让 Agent 能正确写代码的环境”。
核心理念:环境设计五要素
┌─────────────────────────────────────────────────────┐
│ Harness(安全带) │
│ ┌───────────────────────────────────────────────┐ │
│ │ 强约束 可观测 可评估 可反馈 可回退 │ │
│ │ │ │ │ │ │ │ │
│ │ ▼ ▼ ▼ ▼ ▼ │ │
│ │ ┌─────────────────────────────────────┐ │ │
│ │ │ Coding Agent │ │ │
│ │ └─────────────────────────────────────┘ │ │
│ └───────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────┘
| 要素 | 含义 | 具体实现 |
|---|---|---|
| 强约束 | 限制 Agent 能做什么 | 沙箱、权限、工具白名单 |
| 可观测 | 知道 Agent 做了什么 | 日志、追踪、状态监控 |
| 可评估 | 判断做得对不对 | 测试、类型检查、Linter |
| 可反馈 | 把评估结果告诉 Agent | 错误信息、测试报告 |
| 可回退 | 出错能恢复 | Git、快照、版本控制 |
黄金法则:Agent 出错先查环境
当 Agent 写出糟糕的代码时:
┌─────────────────────────────────────────────────────────────┐
│ Agent 出错了 │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ ❌ 错误反应:指导 Agent 修改代码 │
│ ✅ 正确反应:排查环境哪一环出了问题 │
└─────────────────────────────────────────────────────────────┘
│
┌─────────────────┼─────────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ 强约束? │ │ 可评估? │ │ 可反馈? │
│ 权限太宽? │ │ 测试覆盖? │ │ 错误清晰? │
└──────────┘ └──────────┘ └──────────┘
核心洞察:大多数 Agent 错误,根源在环境设计缺陷,而非 Agent 本身。
ACI:Agent-Computer Interface
就像人类需要 HCI(人机交互界面),Agent 需要 ACI(Agent-Computer Interface)。
# ❌ 糟糕的 ACI:让 Agent 写 diff
# Agent 需要知道修改了多少行才能写 chunk header
edit_file(file="app.py", diff="@@ -10,3 +10,4 @@...")
# ✅ 好的 ACI:让 Agent 重写整个文件
# Agent 只需要关注内容本身
edit_file(file="app.py", content="...")
Anthropic 的发现:在 SWE-bench 项目中,优化工具比优化 prompt 更重要。
两个顽固问题
问题一:自我评估偏差
让 Agent 评估自己的工作?结果往往是自信满满地表扬一通,即使工作质量明显平庸。
这在设计类任务中尤其明显。“这个设计好看吗?“是主观判断,没有类似单元测试的二进制检验标准。Agent 会稳定地给自己的作品打高分。
解决方案:分离执行者和评估者。
问题二:Context Anxiety
当 context window 快满时,模型会提前收工。明明还有工作要做,但模型觉得”差不多了,该结束了”。
Compaction(压缩历史对话)并不能完全解决这个问题。真正的解药是 context reset:清空 context window,通过结构化的 handoff artifact 把状态传给下一个全新的 agent。
GAN 启发:Generator-Evaluator 模式
受 Generative Adversarial Networks (GANs) 启发,Anthropic 设计了双 agent 架构:
┌──────────────┐ ┌──────────────┐
│ Generator │ ──── 产品 ────▶ │ Evaluator │
│ (生成者) │ │ (评估者) │
└──────────────┘ └──────────────┘
▲ │
└──────────── 反馈循环 ◀────────────┘
核心思想:
- 把主观判断转化为具体可评估标准
- 调优独立的 evaluator 比让 generator 批评自己的工作更容易
- Evaluator 使用 Playwright MCP 实际操作页面进行评估
三 Agent 架构
扩展到全栈开发,构建三 agent 系统:
┌─────────────────────────────────────────────────────────────┐
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Planner │ ──▶ │ Generator │ ──▶ │ Evaluator │ │
│ │ 规划者 │ │ 执行者 │ │ 评估者 │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │ │ │
│ └─────────── Sprint Contract ───────────┘ │
└─────────────────────────────────────────────────────────────┘
| Agent | 职责 | 关键特性 |
|---|---|---|
| Planner | 把 1-4 句需求扩展为完整产品规格 | 关注产品上下文,而非细节实现 |
| Generator | 按 sprint 一个功能一个功能实现 | 每个 sprint 后自评,交给 QA |
| Evaluator | 用 Playwright 测试,按标准评分 | 每个 criterion 有硬阈值 |
Sprint Contract
在每个 sprint 之前,generator 和 evaluator 协商完成标准:
sprint_1:
feature: "用户登录页面"
acceptance_criteria:
- 用户可以输入用户名和密码
- 登录失败显示错误提示
- 登录成功跳转到首页
evaluation:
- Playwright 测试通过
- Design Quality ≥ 4/5
实战数据:20 倍成本,质的飞跃
任务:创建 2D 复古游戏制作器(关卡编辑器、精灵编辑器、实体行为系统、测试模式)
| Harness | 时长 | 成本 | 结果 |
|---|---|---|---|
| Solo(单 Agent) | 20 分钟 | $9 | 游戏核心功能坏了 |
| Full Harness | 6 小时 | $200 | 功能完整,evaluator 发现具体 bug |
| 简化 Harness | 4 小时 | $124 | Opus 4.6,去掉 per-sprint 评估 |
Solo 的失败
- 布局浪费空间,固定高度面板留下大部分 viewport 空白
- 工作流僵化,UI 不引导正确顺序
- 致命:实体出现在屏幕上但不响应输入——entity definitions 和 game runtime 连接断裂
Full Harness 的成功
Planner 将一句话 prompt 扩展为 16 个功能、10 个 sprint 的规格。
Evaluator 发现的具体 bug:
| Contract Criterion | Evaluator Finding |
|---|---|
| 矩形填充工具允许点击拖动填充 | FAIL — 只在起点/终点放置瓦片,未填充区域 |
| 用户可以删除放置的实体生成点 | FAIL — 删除键处理器设置条件不完整 |
| API 重新排序动画帧 | FAIL — FastAPI 路由顺序错误,‘reorder’ 被匹配为 frame_id |
这些是真实的、具体的、可操作的 bug。
Evaluator 的位置
Evaluator 的价值取决于任务相对于模型能力边界的位置:
任务难度 ──────────────────────────────→
│ │
│ 模型独立完成区 │ 需要 evaluator 区
│ (evaluator 是开销) │ (evaluator 有价值)
│ │
随着模型进步,边界向右移动。
Harness 简化:随着模型进步做减法
两个核心洞见
“Every component in a harness encodes an assumption about what the model can’t do on its own.”
(Harness 中的每个组件都编码了一个假设:模型独立做不到什么。)
“The space of interesting harness combinations doesn’t shrink as models improve. Instead, it moves.”
(随着模型改进,Harness 组合空间不会缩小。它只是转移了。)
简化策略(Opus 4.5 → 4.6)
- 去掉 sprint 结构 — 4.6 原生能处理复杂任务,无需人工分解
- Evaluator 改为最后一次性评估 — 不再 per-sprint 评估
- 重新审视每个约束 — “模型真的做不到吗?“
环境设计清单
强约束:
- [ ] 沙箱环境(Docker / VM / 隔离目录)
- [ ] 文件系统权限控制
- [ ] 网络访问白名单
- [ ] 工具调用白名单
可观测:
- [ ] 所有操作记录日志
- [ ] 文件变更追踪
- [ ] 工具调用链追踪
可评估:
- [ ] 单元测试必须通过
- [ ] 类型检查
- [ ] Linter 检查
- [ ] 构建必须成功
可反馈:
- [ ] 测试失败信息清晰
- [ ] 错误信息结构化
- [ ] 评估结果可被 Agent 理解
可回退:
- [ ] Git 版本控制
- [ ] 变更前自动 commit
- [ ] 支持一键回滚
核心原则总结
- 程序员不写代码 — 设计环境让 Agent 写
- Agent 出错先查环境 — 不是指导修改,而是修复约束
- 环境设计五要素 — 强约束、可观测、可评估、可反馈、可回退
- 分离执行与评估 — Generator 和 Evaluator 分离比自我评估更有效
- 每个约束都值得质疑 — Harness 编码了”模型做不到什么”的假设
- Harness 随模型演进 — 模型能力提升后,Harness 可以(也应该)简化
- 主观标准客观化 — 把”好不好”转化为可测量的具体标准
- 空间不缩水而是移动 — 模型越强,Harness 空间越大
参考资料
- Anthropic: Building Effective Agents (2025)
- Anthropic: Harness Design for Long-Running Application Development (2026)
- Lilian Weng: LLM Powered Autonomous Agents (2023)
- Simon Willison: Embracing the Parallel Coding Agent Lifestyle (2025)
- Pragmatic Engineer: Programming by Kicking Off Parallel AI Agents (2025)
- Andrew Ng: Context Hub (2025)
- ReAct: Synergizing Reasoning and Acting (2023)
- Reflexion: Autonomous Agent with Dynamic Memory (2023)
“The more complex your agent architecture, the harder it is to debug.”
— Anthropic
Harness Engineering 的本质:用简单、可调试的环境约束,替代复杂的 Agent 架构。