Harness 设计解读:Anthropic 如何让 Agent 自主完成六小时全栈开发

15 分钟

本文基于 Anthropic 工程博客 Harness Design for Long-Running Application Development(作者 Prithvi Rajasekaran,发布于 2026-03-24)整理,在原文基础上补充了底层概念的解释。

作者 Prithvi Rajasekaran 在 Anthropic 实验室同时推进两个方向:提升 Claude 生成前端设计的质量,以及让 Claude 在无人干预的情况下完成完整的应用开发。两个方向都取得了一定进展,但随后都遇到了瓶颈。这篇文章记录了他如何用多 Agent 协作架构突破这个瓶颈。

什么是 harness?在软件工程里,"测试框架(test harness)" 指的是包裹被测程序、控制其运行并捕获输出的外层结构。借用这个词,"Agent harness"指的是包裹 AI Agent、控制其调用顺序、传递上下文、协调多个 Agent 协作的编排层。

两个根本性难题

当你给 Agent 分配一个真实的长期任务 —— 比如 "帮我做一个完整的复古游戏制作工具",会遇到两个在短任务里看不到的问题。

上下文焦虑

首先理解 "上下文窗口"(Context Window)是什么。模型每次处理请求时,能看到的文字是有限的,这个限制叫做上下文窗口,可以理解为模型的工作台大小。工作台满了,早期放上去的内容就会被推出去,模型看不见了。

对于长时间运行的任务,随着代码文件、错误日志、对话历史不断堆积,上下文窗口会越来越满。作者观察到一个有趣的行为:"上下文焦虑"(context anxiety) —— 模型在感知到上下文快满时,会过早地收尾工作,即使任务还远没有完成。就像一个手头资料快放不下了的研究员,开始草草写结论,而不是继续做实验。

应对上下文满的策略有两种:重置(reset) 是把上下文完全清空、重新开始,代价是之前的工作记录全部丢失;压缩(compaction) 是在原地对现有上下文做摘要,保留关键信息再继续。两种策略各有取舍,作者发现对 Sonnet 4.5 来说,重置的效果优于压缩 —— 完全清空反而比 "聪明地保留" 更可靠。

自我评估偏差

第二个问题更隐蔽:让 Agent 评估自己的产出,它几乎总是给出过于乐观的评价。作者把这叫做 "自我评估偏差"(self-evaluation bias)。

这并不是 AI 特有的问题。审查自己写的代码,比审查别人的代码更难发现问题 —— 因为大脑已经知道 "想要表达什么",会自动填补逻辑漏洞,而不会真正执行每一步。Agent 也一样:它知道自己 "想要做什么",所以在检查时会倾向于确认自己已经做到了,而不是真正验证。

对于设计质量这类主观任务,这个问题尤为严重,因为没有明确的对错标准,Agent 说 "看起来不错",你也找不到一个硬指标来反驳它。


这两个问题共同指向了同一个解法:把生成和评估交给不同的 Agent 来做。这个思路,来自机器学习中的一个经典架构。

从 GAN 获得的灵感:生成与评估分离

GAN(Generative Adversarial Network,生成对抗网络)是深度学习中的一种训练范式。它的核心思想是:同时训练两个模型,生成器(Generator)负责生成内容(比如图片),判别器(Discriminator)负责判断内容是真实的还是生成的。两者相互对抗 —— 生成器努力骗过判别器,判别器努力识破生成器 —— 在这个博弈过程中,两者的能力都螺旋式提升。

用一个直观类比:生成器像是学生在大考前大量做模拟题,老师则负责批改和指出问题。对抗让学生的解题能力越来越强,老师的判断也越来越准。

作者借鉴的是这个思路里最核心的一条原则:生成和评估要由相互独立的主体来完成。在 Agent 系统里,两个 Agent 不需要相互对抗训练,只需要角色分离 —— 一个 Agent 专注生成,另一个 Agent 专注批判。

前端设计的实践

作者首先在前端设计生成任务上验证了这个思路。系统里有两个 Agent:

  • 生成 Agent:根据需求生成前端页面
  • 评估 Agent:用 Playwright(一个浏览器自动化测试框架,能像真实用户一样打开网页、点击按钮、截图)与生成的页面交互,然后按四个维度打分并给出修改意见

四个评分维度是:

  1. 设计质量(Design Quality):设计是否呈现一个完整的整体感?颜色、字体、布局、图像是否共同营造出一种特定的风格和气质?
  2. 原创性(Originality):是否有定制化的设计决策,还是充斥着模板布局和 AI 默认风格?一个人类设计师是否能看出刻意的创意选择?
  3. 工艺(Craft):技术执行层面 —— 字体排版层级、间距一致性、色彩和谐度、对比度。这是能力检查,而不是创意检查。
  4. 功能性(Functionality):与美观无关的可用性。用户能否理解界面的作用,找到主要操作入口,不靠猜测完成任务?

作者特别提到一个有趣的观察:评分标准的措辞会影响生成结果。加入 "最好的设计是博物馆级别的" 这样的描述,会推动生成器朝某一种特定的视觉风格收敛。评估标准的语言,不只是在描述好坏,也在塑造生成方向。 更进一步,即使没有 Evaluator 给出任何反馈,仅仅把这四个评分维度写进生成 Agent 的 prompt,第一轮输出的质量就已经超过了没有这些标准时的基线 —— 评分语言本身就在引导生成器远离通用模板。

评估 Agent 使用 Playwright 实际操作生成的页面,截图后再打分,而不是只看源码。这一点很关键:源码层面看起来正确的东西,在真实浏览器里渲染出来可能完全不同。每一轮生成通常经过 5-15 次迭代,完整跑一遍需要四个小时。

迭代过程并非线性递进。生成器在每轮都会策略性地判断:是在现有方案上微调,还是推翻重来、换一个完全不同的风格方向。作者记录了一个博物馆网站的案例:生成器在第 10 次迭代时放弃了暗色主题,重新构想为 "用 CSS 透视渲染的带棋盘格地板的 3D 房间"。有时候,中间某次迭代的结果反而比最终版更好;而随着迭代推进,Generator 往往会追求越来越有野心的方案,实现复杂度也在递增。

全栈应用的三 Agent 架构

把这套思路扩展到全栈应用开发时,单一的生成-评估二元结构不够用了。作者设计了三个角色。

Planner(规划者)

用户通常只给一个简短的需求(1-4 句话)。Planner 的工作是把这个模糊需求扩展成详细的产品规格:明确功能边界、用户故事、高层设计方向。

有一个关键约束:Planner 要刻意避免过早做技术决策。不要在规格里写 "用 PostgreSQL 存用户数据",因为一旦写进规格,后面的 Generator 就会把这个当成约束来遵守,即使实际情况下用 SQLite 更合适。规划阶段的技术细节过多,反而会限制实现阶段的灵活性。

Planner 还负责把前端设计工作纳入产品规格,生成视觉设计语言说明 —— 颜色、字体、组件风格,让 Generator 在实现阶段有设计层面的依据可以遵循。

Generator(实现者)

Generator 按顺序实现功能,技术栈是 React + Vite(前端)、FastAPI(后端)、SQLite/PostgreSQL(数据库),并用 git 做版本控制。

在把工作交给 Evaluator 之前,Generator 会先做一轮自评估。这听起来与前面说的 "自我评估偏差"矛盾 —— 既然 Generator 评不好自己的工作,为什么还要它自评?原因是:自评的价值在于过滤掉明显的低级错误(比如服务没有启动、端口写错),让 Evaluator 能聚焦在更有价值的问题上。

Evaluator(验证者)

Evaluator 同样使用 Playwright 像真实用户一样操作应用 —— 点击 UI、调用 API、检查数据库状态,来验证功能是否真正可用。这类测试能发现很多静态代码审查发现不了的问题。原文列举了几个具体例子:

  • 矩形填充工具只在拖拽的起点和终点各放一个图块,没有填满中间的区域
  • Delete 键的处理逻辑要求两个条件同时满足,但实际上只需满足其中一个
  • FastAPI 路由把字符串 reorder 错误地匹配为整数参数,导致请求直接返回 422 错误

这些 bug 在代码层面不一定显眼,但用 Playwright 像真实用户一样操作一遍,就会立刻暴露出来。

整个系统使用 Claude Agent SDK 做编排,Agent 之间通过文件系统传递上下文和中间产物。

Sprint Contract:协商式任务分解

在早期的架构里,Generator 和 Evaluator 之间有一个 "冲刺合同"(Sprint Contract)的机制 —— 借鉴自敏捷软件开发。每次冲刺开始前,两个 Agent 先协商这一轮要完成什么、完成的标准是什么,形成一份双方都认可的 "交付清单",然后再开始写代码。

这个机制解决了一个常见问题:如果没有明确的完成标准,Evaluator 发现一堆问题,Generator 对 "完成了多少"的理解可能完全不同,导致无效争论。Sprint Contract 把抽象的用户故事转化成可验证的具体条目,双方对齐之后再动手。

效果对比:单 Agent 与 Harness

用同一个任务 "制作一个复古风格的游戏制作工具",作者对比了两种方案(均使用 Opus 4.5 模型):

方案时长费用结果
单 Agent20 分钟$9界面看起来能用,但核心实体之间没有正确连通
完整 Harness6 小时$200界面精良,游戏机制真正可运行,并实现了 AI 精灵生成和关卡生成

20 倍的成本换来了什么?在这个案例里,差距不是 "差一点"与 "好一点",而是 "外表像个产品但核心坏掉的"与 "真正可以用的产品"之间的差距。单 Agent 版本通过了表面检查,但 Harness 里的 Evaluator 发现了实体连通问题并推动修复了它。

这个数字也提示了一个现实判断:对于探索性原型来说,$9 可能完全够用;对于真正需要可靠运行的产品,$200 的投入才能买到质量保障。使用 Harness 之前,值得先想清楚任务的质量要求是什么。

Harness 的演化:模型变强后怎么做

当作者换用 Opus 4.6 模型来运行同样的 Harness 时,发现很多早期设计的组件变得多余了。Opus 4.6 在规划、持续执行和调试上有了显著提升,很多以前需要结构化流程来弥补的能力空缺,现在模型自身已经具备了。

作者做了两处简化:

  1. 移除 Sprint 分解结构:早期设计 Sprint Contract 是为了帮助模型分解长任务、避免目标漂移。Opus 4.6 在持续执行长任务上更稳定,Sprint 结构的必要性降低了,去掉之后反而减少了流程开销。

  2. Evaluator 从多轮变为单次:原来 Evaluator 参与每一轮迭代。改成只在全部实现完成后做一次 QA,减少了 Evaluator 的调用次数。但作者保留了 Evaluator,即使在 Opus 4.6 之下,它仍然发现了 Generator 遗漏的显著问题。

用数字音乐制作工作站(DAW)作为测试任务,更新后的 Harness 跑出了这样的结果:

阶段时长费用
Planner4.7 分钟$0.46
第一轮实现2 小时 7 分钟$71.08
第一轮 QA8.8 分钟$3.24
第二轮实现1 小时 2 分钟$36.89
第二轮 QA6.8 分钟$3.09
第三轮实现10.9 分钟$5.88
第三轮 QA9.6 分钟$4.06
合计3 小时 50 分钟$124.70

QA 轮次发现了多处功能空壳:音频录制没有实际捕获输入、音频片段缺少拖拽和缩放操作、图形效果编辑器缺失。Generator 在后续轮次逐一修复了这些问题,并额外接入了 Claude Agent,实现了由 AI 自主驱动的作曲功能。与早期 Harness 相比,总时长和费用都有所下降,同时质量依然可靠。

启示

作者在文末提炼了四条洞察,值得仔细对待。

1. Harness 的每个组件都在编码对模型能力的假设

Sprint Contract 的存在,意味着作者认为 "模型无法在没有明确分解的情况下持续完成长任务"。Evaluator 的存在,意味着 "模型无法可靠地自我验证"。每当你设计一个 Harness 组件时,都在为模型的某个弱点打补丁。这些假设值得被明确写出来,因为它们会随模型能力的变化而失效。

2. 任务分解与专项 Agent 的叠加效应

把任务分解(规划→实现→验证)和专项 Agent(各自专注自己的角色)结合起来,产生的收益远大于两者之和。这两种手段在更强的模型上依然有效,甚至会变得更有效 —— 因为更强的基础能力能把每个角色发挥到更高水准。

3. 随着模型进步,要主动审视 Harness

如果三个月前设计了一套 Harness,模型更新后,不应该假设 Harness 仍然最优。当初为了弥补模型弱点而设计的结构,现在可能只是在增加延迟和成本。定期重新审视、做消融实验(把某个组件移除,看效果是否下降),是维护一套有效 Harness 的必要工作。

4. 更强的模型让有效组合的空间变得更大

能力更强的基础模型意味着每个 Agent 角色都能发挥得更好,多个角色的协同效果也更显著。随着模型进步,多 Agent 架构的价值上限在提高,而不是因为"模型太强"而被压缩。


这篇文章带给我们的启示是:Harness 设计是一个持续的工程实践,而不是一次性的架构决策。 模型在变,任务在变,组件的假设也需要跟着变。保持追踪实际运行表现、定期做对照实验,才能让 Harness 在模型能力的每一次跃升中都能真正发挥作用。

目录