harness design long running apps.md
原文:Harness Design for Long-Running Application Development 作者:Prithvi Rajasekaran(Anthropic Labs 团队) 发布日期:2026 年 3 月 24 日
一、文章定位:Anthropic Agent 工程系列的第四篇
要理解这篇文章的分量,必须先把它放在 Anthropic 整个 Agent 工程系列中来看。这个系列构成了一条清晰的技术演进线:
- Effective Context Engineering for AI Agents(2025.09)——解决”Agent 的上下文应该放什么、怎么管理”这个基础问题
- Building Effective Agents(2025)——Agent 设计的总纲领,提出”找到最简单的可行方案,只在需要时增加复杂度”这个核心原则
- Effective Harnesses for Long-Running Agents(2025.11)——初版 Harness,用 Initializer Agent + Coding Agent + Context Reset 解决跨上下文窗口的长时工作
- 本文(2026.03)——在前作基础上引入 GAN 灵感的 Generator-Evaluator 结构,演进为三 Agent 架构,并展示了随模型升级(Sonnet 4.5 → Opus 4.5 → Opus 4.6)如何系统性地简化 Harness
每一篇都建立在前一篇的发现之上,而本文是目前为止最完整的一篇——它不仅提出了新架构,还回溯了整条技术路径,展示了每个设计决策的原因、权衡和演进。
二、起点:前作的成就与天花板
2.1 前作做了什么
在 2025 年 11 月的前作中,Justin Young 等人描述了一个两部分方案:
- Initializer Agent:第一个会话使用专门的 prompt,让模型搭建初始环境——
init.sh脚本、claude-progress.txt进度文件、初始 git commit。最关键的是,它会基于用户 prompt 生成一个结构化的 feature list(JSON 格式,200+ 个 feature),每个都标记为passes: false。 - Coding Agent:后续每个会话的 Agent 遵循固定流程——先
pwd确认目录 → 读 git log 和 progress 文件恢复状态 → 从 feature list 挑最高优先级的未完成 feature → 实现 → 用 Puppeteer MCP 做端到端测试 → 写 git commit 和 progress update → 交班。
前作解决了四个核心失败模式:
| 失败模式 | 解决方案 |
|---|---|
| Agent 一口气尝试做完整个项目 | Feature list 强制逐个功能实现 |
| Agent 过早宣布项目完成 | Feature list 中有明确的 passes: false 标记 |
| Agent 留下一团乱麻(bug + 无文档) | 每个会话结束时必须 git commit + 写 progress update |
| Agent 标记功能完成但没有真正测试 | 强制使用浏览器自动化工具做端到端测试 |
2.2 前作碰到的天花板
前作在结尾坦承了一个关键的未解决问题:
“是否一个通用的单 coding agent 在所有上下文中表现最好,还是多 agent 架构能通过专门化实现更好的性能?专门化的 agent——如测试 agent、QA agent、代码清理 agent——似乎可以在软件开发生命周期的子任务上做得更好。”
本文正是对这个问题的直接回答:是的,多 Agent 架构能做得更好,而且好很多。
同时,前作还有两个未显式提到但从描述中可以推断的限制:
- 需要用户提供详细的产品规格——Initializer Agent 只是将规格分解为 feature list,不能自己扩展规格的范围
- 没有解决”审美质量”问题——对于前端设计这类主观任务,即使 feature 全部 pass,视觉质量仍可能平庸
本文同时解决了这两个问题。
三、两大失败模式的深入分析
3.1 失败模式一:上下文退化与 Context Anxiety
作者在本文中对上下文管理问题进行了比前作更精确的概念化。他区分了两个不同但相关的现象:
上下文退化(Context Degradation):随着上下文窗口填满,模型对较早信息的把握逐渐模糊,输出的连贯性下降。这是一个渐进的过程,所有使用长上下文的场景都会遇到。
Context Anxiety(上下文焦虑):某些模型在”认为”自己接近上下文限制时,会主动开始收尾工作——即使实际上还有大量工作未完成。这不是因为真的没有上下文空间了,而是模型习得的一种行为模式:它在训练中学到了”上下文快用完了应该收尾”,于是在推理时过早触发这个行为。
作者对两种缓解方案的分析是文章的一个重要技术贡献:
Compaction(对话压缩):
- 做法:将对话历史的早期部分进行摘要压缩,让 Agent 在缩短的历史上继续工作
- 优点:保持连续性,同一个 Agent 继续工作,无需交接
- 缺点:不能解决 Context Anxiety。因为 Agent 虽然上下文变短了,但它”记得”自己已经工作了很久。压缩后的摘要本身就暗示了大量的历史工作,模型仍然会觉得”快到头了应该收尾”
- 本质:Compaction 解决的是信息衰减问题,但不解决行为模式问题
Context Reset(上下文重置):
- 做法:完全清空上下文窗口,启动一个全新的 Agent 实例,通过结构化的交接文件(handoff artifact)将前一个 Agent 的状态和下一步计划传递给新 Agent
- 优点:彻底消除 Context Anxiety——新 Agent 从全新的空白状态开始,没有”我已经工作很久了”的认知负担
- 缺点:增加了编排复杂度(需要编排多个 Agent 实例的生命周期)、token 开销(交接文件本身消耗 token)、延迟(每次 Reset 都有启动开销)
- 额外要求:交接文件必须包含足够的状态信息,让新 Agent 能够干净地接手工作。这本身就是一个需要精心设计的问题
实测结论:在 Sonnet 4.5 上,Context Anxiety 严重到 Compaction 单独使用不够,Context Reset 成为 Harness 的必要组件。但到了 Opus 4.5,这个行为基本消失了,所以作者完全去掉了 Context Reset,回归了单会话 + 自动 Compaction。再到 Opus 4.6,由于长上下文检索能力的进一步提升,模型可以在单个连续会话中运行超过 2 小时而不失去连贯性。
深层启示:Context Anxiety 是一个模型行为问题,不是架构问题。它是训练过程的副产物,随着训练方法的改进可以被直接消除。这意味着为解决它而引入的 Harness 复杂度是”暂时的桥梁”,而非”永久的架构需求”。作者后续”每个组件都是对模型能力边界的假设”这一原则,正是从这个具体经验中提炼出来的。
3.2 失败模式二:自我评估失效
这是本文的核心发现之一。作者观察到一个一致的现象:当 Agent 被要求评估自己刚刚完成的工作时,它会系统性地高估质量。
这不是偶发现象,而是 LLM 的一个结构性倾向。作者将其分解为两个层面:
主观任务上的表现:对于设计这类没有二元对错的任务,Agent 在评价自己的设计时会”自信地夸赞”——即使在人类观察者看来,输出明显是平庸的模板拼凑。不存在像”测试通过/失败”这样的客观检查来纠正它。
即使在有可验证结果的任务上:作者特别指出,这个问题不限于主观任务。即使在有对错标准的编码任务中,Agent 也会在执行过程中表现出”判断力不足”——比如忽略明显的 bug、对 stub 实现表示满意、看到运行不报错就认为一切正常。
为什么分离 Generator 和 Evaluator 有效?
作者的解释非常精妙:分离本身不会自动消除 LLM 对 LLM 输出的宽容倾向——评估者仍然是一个 LLM,天然倾向于对 LLM 生成的内容手下留情。但关键在于:
“调优一个独立的评估者使其变得苛刻,远比让一个生成者对自己的工作变得挑剔容易得多。”
这里的工程直觉是:让一个 Agent 既做事又批评自己做的事,是在要求它执行两个矛盾的任务——它刚刚花了大量的推理努力来产出这个结果,现在你要它否定自己的努力。这在认知上是困难的。而一个独立的评估者没有这种”沉没成本”心理,它从全新的视角看到一个成品,可以更客观地评判。
而且,一旦这种外部反馈存在,生成者就有了具体的、可操作的目标去迭代——不再是模糊的”做得更好”,而是”评估者在这三个维度给了你低分,具体原因是 X、Y、Z”。
四、前端设计实验:把主观判断工程化
4.1 问题的本质
在没有任何干预的情况下,Claude 在前端设计上的默认表现是:技术上正确、功能上可用,但视觉上乏味。它会倾向于安全的、可预测的布局——可以称之为”AI 设计泔水(AI slop)“:白色卡片 + 紫色渐变 + 无个性的排版。
这个问题的根源在于,LLM 在训练中看到了大量的”正确但平庸”的网页设计,它习得的”安全策略”就是复制这些常见模式。要让它跳出这个安全区,需要外部压力。
4.2 两个关键洞察
作者在这里提出了两个驱动整个 Harness 设计的核心洞察:
洞察一:主观判断可以被分解为可评分的标准
“这个设计美不美?“这个问题太模糊,LLM 无法一致地回答。但”这个设计是否遵循了我们定义的好设计原则?“给了 Claude 一个可以具体评分的东西。
这是一种将品味工程化的方法——你不能教会模型什么是”美”,但你可以定义一套标准,让模型按照这套标准给出一致的评判。
洞察二:将生成和评分分离,可以创建一个驱动质量提升的反馈循环
这直接借鉴了 GAN 的核心思想——生成器和判别器的对抗推动两者共同进步。但和真正的 GAN 不同,这里不涉及梯度反向传播和权重更新,而是通过 prompt 和文本反馈来实现。
4.3 四维评分标准的详细拆解
这四个标准的设计不是随意的,每个都有明确的意图和权重考量:
1. Design Quality(设计质量)
- 问的问题:设计是否感觉是一个连贯的整体,而非拼凑的零件?
- 什么算好:颜色、排版、布局、意象和其他细节组合在一起,创造出独特的氛围和身份(mood and identity)
- 关键词:“连贯整体”(coherent whole)vs “零件集合”(collection of parts)——这个区分非常精准。很多 AI 生成的页面,每个组件单独看都没问题,但放在一起缺乏统一的设计语言
- 权重:高(刻意提升)
2. Originality(原创性)
- 问的问题:是否有自主的设计决策的证据?
- 什么算差:模板布局、库默认值、AI 生成模式。未修改的库存组件。典型的 AI 生成标志——紫色渐变覆盖在白色卡片上
- 关键词:“一个人类设计师应该能认出刻意的创造性选择”——这是一个非常高的标准,它要求输出不仅要避免模板感,还要让专业人士认可其中有设计思考
- 权重:高(刻意提升)
- 注意:这个标准直接将”AI 泔水”列为扣分项,是一种对 LLM 生成内容固有弱点的精确打击
3. Craft(工艺)
- 问的问题:技术执行质量如何?
- 检查项:排版层级、间距一致性、色彩和谐、对比度
- 性质:能力检查(competence check),不是创意检查(creativity check)
- 权重:正常——因为 Claude 在这方面默认表现就不错,大多数合理的实现在此项自然达标。失败意味着基本功崩溃
- 言下之意:如果你在这里都拿不到分,说明其他维度也不用看了
4. Functionality(功能性)
- 问的问题:独立于美学的可用性
- 检查项:用户能否理解界面功能、找到主要操作、完成任务而不需要猜测
- 权重:正常——同样是 Claude 的默认强项
权重策略的哲学:作者刻意将 Design Quality 和 Originality 的权重调高。逻辑是:Claude 已经天然擅长 Craft 和 Functionality(技术能力和可用性自然而然就好),但在 Design Quality 和 Originality 上经常输出平庸的结果。通过加重这两个维度,强制推动模型承担更多美学风险。
这实际上是一种对 LLM 能力分布的精确补偿——哪里弱就在那里加权,而不是均匀地要求所有维度。
4.4 评估者的校准方法
作者使用了 few-shot examples + 详细分数分解 来校准评估者。这确保了:
- 评估者的判断与作者本人的偏好对齐
- 减少了跨迭代的分数漂移(score drift)
这个细节很关键——没有校准的评估者会随着输入的不同而漂移标准。Few-shot 锚定了评估者的基准线。
4.5 技术实现细节
底层框架:Claude Agent SDK——Anthropic 官方的 Agent 编排 SDK,保持了编排的简洁性。
评估者的工具:Playwright MCP——这让评估者不是看截图打分,而是实际操作运行中的页面。在实践中,评估者会自己导航页面、截屏、仔细研究实现,然后才产出评估。
这比静态截图分析有效得多。一个页面可能截图上看着没问题,但实际交互时会暴露布局在特定视口下的问题、hover 效果的缺失、滚动行为的异常等。
生成者的输出:HTML/CSS/JS 前端(基于用户 prompt)
迭代策略:每轮评估后,生成者要做一个战略决策——如果分数趋势向好,就沿当前方向继续精炼;如果方向不行,就彻底转向一种完全不同的美学(pivot)。
这个 pivot 机制非常重要。如果没有它,生成者可能会在一个错误方向上反复打补丁,越改越差。明确允许甚至鼓励推翻重来,是创造性突破的前提。
4.6 迭代运行的参数与观察
迭代次数:每次生成运行 5-15 轮迭代
单轮耗时:因为评估者在实际导航页面(而不是看静态截图),每轮需要真实的 wall-clock time
总运行时间:全量运行最长可达 4 小时
观察到的迭代模式:
模式一:分数总体上随迭代改善,但不是线性的。 后期实现整体上更好,但作者多次发现自己更喜欢某个中间迭代而非最终轮。这说明”质量”是多维的,某些维度的改善可能伴随其他维度的退步。
模式二:实现复杂度随迭代递增。 生成者在评估者的反馈推动下,会尝试越来越有野心的方案。这是一个双刃剑——更复杂的实现可能更令人印象深刻,但也更容易出 bug。
模式三:即使第一轮(无评估者反馈),有评分标准的输出就已明显优于完全无 prompt 的基线。 这个发现意义重大——它说明评分标准的文本本身就在 prompt 中起到了引导作用,即使还没有评估者的反馈。标准中的语言和概念塑造了生成者的”审美意识”。
模式四:标准中的措辞会以出乎意料的方式塑造输出。 作者提到,在标准中包含”最好的设计是博物馆品质的”这样的短语,推动了设计向特定的视觉收敛。这暗示了一个深层机制——评分标准不仅是评分工具,它本身就是一种隐性的 prompt engineering,直接影响了生成者的输出特征。
4.7 荷兰艺术博物馆案例
这是文章中最引人注目的单一案例。
前9轮:生成器产出了一个干净的深色主题博物馆落地页。视觉上精致,但在作者的预期范围内——你看到一个黑色背景、白色文字、漂亮图片的页面,会觉得”嗯,不错”,但不会惊讶。
第10轮:生成器彻底推翻了方案。它将网站重新构想为一个空间体验:
- 一个用 CSS 透视渲染的 3D 房间
- 格子地板
- 画作以自由位置挂在墙上
- 用门廊导航在画廊房间之间切换,取代传统的滚动或点击导航
作者评价:这是他之前从未从单轮生成中见过的创造性飞跃。
这个案例的深层含义是:评估者驱动的迭代+允许 pivot 的机制,可以让 LLM 突破”安全区”,产生真正出人意料的创意输出。第10轮的 pivot 发生,恰恰是因为前9轮的分数虽然在改善但可能遇到了瓶颈,触发了生成者选择”彻底换方向”的策略分支。如果没有这个机制,它可能只会在深色主题落地页的框框里小修小补。
五、全栈编码:三 Agent 架构的完整设计
5.1 从前作到本文的架构演进
| 维度 | 前作(2025.11) | 本文 V1(Opus 4.5) | 本文 V2(Opus 4.6) |
|---|---|---|---|
| Agent 数量 | 2(Initializer + Coder) | 3(Planner + Generator + Evaluator) | 3(但 Evaluator 简化) |
| 上下文管理 | Context Reset(必需) | 单会话 + 自动 Compaction | 单会话 + 自动 Compaction |
| 工作分解 | Feature list + 逐个实现 | Sprint 分解 + Sprint Contract | 无 Sprint,自由构建 |
| 质量保证 | Agent 自测(Puppeteer) | 独立 Evaluator 逐 Sprint 评估 | 独立 Evaluator 仅在最后 pass |
| 规格来源 | 用户提供详细规格 | Planner 自动扩展 | Planner 自动扩展 |
| 模型 | Sonnet 4.5 | Opus 4.5 | Opus 4.6 |
5.2 三个 Agent 的详细设计
Planner(规划者)
解决的问题:前作要求用户提供详细的产品规格。这在实际使用中是一个巨大的摩擦——大多数用户只有一个模糊的想法,不会写产品文档。
设计:
- 输入:1-4 句话的简单 prompt
- 输出:完整的产品规格说明书
- 被指示要”雄心勃勃”——这是一个有意的设计选择。如果 Planner 保守,生成的产品范围就会有限,最终产品也会单薄。鼓励它大胆设想可以产出更丰富的产品。
- 聚焦产品上下文和高层技术设计,而非细粒度实现细节
这最后一点的理由值得深入理解。作者的推理是:如果 Planner 试图在前期指定细粒度的技术细节,而某些细节是错误的,那么这些错误会级联到下游的实现中。更聪明的做法是约束 Agent 的可交付成果(deliverables),让它们自己在工作中找到实现路径。
类比:这就像一个好的产品经理——你告诉工程师”用户应该能做 X、Y、Z”(What),而不是”你应该用 React + Redux,在 useEffect 里调 API”(How)。
额外指令:作者还要求 Planner 在规格中寻找机会织入 AI 功能。这是一个巧妙的元级操作——让 AI 在规划产品时主动思考”这个产品的哪些地方可以用 AI 来增强”。
实例:在 RetroForge 游戏制作器的规格中,Planner 不仅规划了核心编辑器,还自主增加了 AI 辅助精灵生成器和 AI 辅助关卡设计器。这些功能在用户原始的一句话 prompt 中完全没有提到。
更细的实例:附录中展示了 Planner 为 RetroForge 生成的产品规格(部分)。它包含了完整的项目概述、目标用户画像、以及详细到 User Story 级别的功能规格。比如”项目仪表板与管理”功能就包含了 5 个 User Story 和完整的数据模型定义(项目元数据、画布设置、瓷砖大小配置、调色板选择等)。这不是一个粗略的大纲——这是一份真正可以拿去开发的产品文档。
Generator(生成者)
角色:代码实现者,按 Sprint 逐个功能实现。
技术栈:React + Vite + FastAPI + SQLite(后期升级为 PostgreSQL)
工作模式(V1,Opus 4.5):
- 从规格中按优先级挑选一个功能
- 与 Evaluator 协商 Sprint Contract
- 实现该功能
- 自评
- 交给 Evaluator QA
- 根据 Evaluator 反馈修复问题
- 进入下一个 Sprint
版本控制:有 git,这让 Generator 可以 revert 错误的代码变更,恢复到已知的良好状态
自评环节:在交给 Evaluator 之前,Generator 先自评。这不是替代外部评估,而是在外部评估之前先过滤掉明显的问题,减少 Evaluator 的负担。
Evaluator(评估者)
角色:独立的 QA Agent,用用户视角测试运行中的应用。
工具:Playwright MCP——让它可以像用户一样点击、导航、输入、截屏。
评估维度(从前端实验改编,适配全栈场景):
- Product Depth(产品深度)
- Functionality(功能性)
- Visual Design(视觉设计)
- Code Quality(代码质量)
评分机制:每个维度有硬性阈值,任何一个维度低于阈值,Sprint 就失败(FAIL),Generator 获得详细的失败反馈。
测试范围:UI 功能、API 端点、数据库状态——全方位的端到端测试。
5.3 Sprint Contract 机制详解
Sprint Contract 是本文的一个重要创新。它的完整工作流是:
- Generator 提出:我打算在这个 Sprint 中构建 X,成功标准是 Y1、Y2、Y3…
- Evaluator 审查:审查提案是否合理——Generator 是否在构建正确的东西?成功标准是否可测试?是否遗漏了重要方面?
- 两者迭代:如果 Evaluator 有异议,Generator 修改提案,直到双方达成一致
- 达成一致后:Generator 按照合同开始编码,Evaluator 将使用合同中的成功标准来测试最终输出
为什么需要这个机制?产品规格是故意写得高层次的(避免细节错误级联),但 Evaluator 需要具体的、可测试的行为来判定通过/失败。Sprint Contract 就是这个桥梁。
合同的粒度:文章提到,Sprint 3(关卡编辑器)的合同就有 27 个测试标准。这不是泛泛的”关卡编辑器应该能工作”,而是像”矩形填充工具应允许点击拖动来用选定瓷砖填充矩形区域”这样具体的行为描述。
5.4 Agent 间通信:基于文件
Agent 之间的通信通过文件系统进行——一个 Agent 写一个文件,另一个 Agent 读取并回应(要么在同一个文件中回应,要么写一个新文件让前一个 Agent 读取)。
这个看似低技术的选择有深刻的优势:
- 可审计:所有通信都以文件形式持久化,事后可以完整回溯
- 可重启:如果某个 Agent 崩溃,从文件恢复状态
- 可调试:人类可以直接打开文件阅读理解 Agent 之间的对话
- 无并发问题:Agent 是串行执行的,一个写完另一个读
- 与 git 自然集成:文件变更可以被 git track,形成通信的版本历史
- 对 LLM 友好:读写文件是 LLM Agent 最基本的操作,不需要复杂的消息传递协议
六、实测对比:Solo vs Full Harness
6.1 测试 prompt
Create a 2D retro game maker with features including a level editor,
sprite editor, entity behaviors, and a playable test mode.
6.2 数据对比
| 维度 | Solo(单 Agent) | Full Harness(三 Agent) |
|---|---|---|
| 时间 | 20 分钟 | 6 小时 |
| 成本 | $9 | $200 |
| 成本倍率 | 1x | 22x |
| 功能范围 | 基本编辑器 + 播放模式 | 16 个功能、10 个 Sprint |
6.3 Solo 的具体问题
作者逐一描述了 Solo 运行的每个问题:
- 布局浪费空间:固定高度的面板留下了大量空白视口
- 工作流僵硬:试图填充关卡时,系统提示需要先创建精灵和实体,但 UI 中没有任何引导告诉你应该按这个顺序操作
- 核心功能坏了:实体出现在屏幕上,但不响应任何输入。作者挖掘代码后发现,实体定义和游戏运行时之间的连线是断的(wiring was broken),而且表面上看不出哪里出了问题
最后这一点最致命——不是某个可见的错误,而是两个系统之间的集成断裂,只有深入代码才能发现。这正是单 Agent 自评的盲点——它写了两个系统,各自可能单独”看起来没问题”,但它没有从端到端的视角验证它们是否真正连通。
6.4 Full Harness 的表现
- Planner 的规格扩展:一句话 prompt → 16 个功能、10 个 Sprint。包含精灵动画系统、行为模板、音效音乐、AI 辅助精灵生成器和关卡设计器、游戏导出和分享链接。远远超出用户 prompt 的原始范围
- Planner 读取了 frontend design skill:它用这个 Skill 为应用创建了一套视觉设计语言(visual design language),作为规格的一部分。这确保了整个应用有一致的视觉身份
- 布局改善:Canvas 使用全视口,面板尺寸合理,界面有一致的视觉身份
- 精灵编辑器更丰富:更干净的工具调色板、更好的颜色选择器、更可用的缩放控件
- AI 功能集成:内置 Claude 集成,可以通过 prompt 生成游戏的不同部分——显著加速了工作流
- 核心功能可用:能够实际移动角色、游玩关卡
仍然存在的问题:
- 工作流仍然不够直观——仍然需要用户自己摸索出”先创建精灵和实体再填充关卡”的顺序。作者认为这是模型产品直觉的缺陷,而非 Harness 能解决的问题,但也指出这是 Harness 可以进一步优化的方向
- 物理引擎有粗糙之处——角色跳上平台会与平台重叠
- AI 生成的关卡有局限——有一堵跳不过去的大墙
6.5 Evaluator 抓到的真实 Bug 案例
文章给出了三个具体的 bug 案例,每个都值得仔细分析:
Bug 1:矩形填充工具
- 合同标准:矩形填充工具应允许点击拖动来用选定瓷砖填充矩形区域
- Evaluator 发现:工具只在拖动的起始和结束点放置瓷砖,而不是填充整个区域。
fillRectangle函数存在但在mouseUp时没有被正确触发 - 分析:这是一个经典的”函数存在但未被正确调用”的集成 bug。Generator 写了填充函数,也写了鼠标事件处理,但没有正确连接两者
Bug 2:实体删除
- 合同标准:用户可以选择并删除已放置的实体生成点
- Evaluator 发现:
LevelEditor.tsx:892行的 Delete 键处理需要同时设置selection和selectedEntityId,但点击实体只设置了selectedEntityId。条件应该是selection || (selectedEntityId && activeLayer === 'entity') - 分析:这是一个逻辑条件错误。Evaluator 不仅发现了 bug,还精确到了文件名、行号、并给出了正确的修复条件。这个级别的诊断精度意味着 Generator 可以直接去修复,不需要额外的调查
Bug 3:动画帧重排序 API
- 合同标准:用户可以通过 API 重新排列动画帧
- Evaluator 发现:
PUT /frames/reorder路由定义在/{frame_id}路由之后。FastAPI 将 ‘reorder’ 字符串匹配为frame_id的整数参数,返回 422:“unable to parse string as an integer” - 分析:这是一个 FastAPI 路由顺序问题——路径参数和具名路径的优先级冲突。这种 bug 在代码审查中很容易被人类发现,但 Agent 自测时往往不会去测试这种特定的路由组合
这三个 bug 的共同特点是:它们都不是通过看代码就能发现的,而是通过实际操作运行中的应用才暴露的。 这正是使用 Playwright MCP 进行端到端测试的价值所在。
七、调优 Evaluator 的血泪史
这个部分是全文最有实操价值的段落之一。
7.1 开箱即用的 Claude 是个糟糕的 QA Agent
作者坦承:
“Out of the box, Claude is a poor QA agent.”
具体表现:
- 识别出了合理的问题 → 然后说服自己这些问题”不是什么大问题” → 批准工作
- 倾向于表面测试(happy path),而非探测边界情况
- 更微妙的 bug 经常溜过去
7.2 调优循环
调优方法是一个经典的人在回路(human-in-the-loop)迭代过程:
- 运行 Harness
- 阅读 Evaluator 的完整日志
- 找到 Evaluator 的判断与自己判断不一致的地方
- 分析不一致的原因——是太宽容?测试不够深入?遗漏了某类问题?
- 更新 QA 的 prompt 来解决这些具体问题
- 重新运行
- 重复多轮
关键点:这不是一次性的 prompt 工程。作者说”花了好几轮这样的开发循环,Evaluator 才开始以我认为合理的方式评分。“
7.3 调优后仍然存在的局限
即使经过多轮调优,Harness 的输出仍然显示了模型 QA 能力的边界:
- 小的布局问题
- 某些交互在某些地方仍感觉不直观
- 更深层嵌套的功能中仍有未被发现的 bug——评估者没有足够深入地测试
作者的判断:仍然有更多的验证空间可以通过进一步调优来捕获。 但与 Solo 相比——核心功能根本不工作——提升已经是显而易见的了。
八、Harness 简化方法论
8.1 核心原则
“Harness 中的每个组件都编码了一个关于模型不能独立完成什么的假设,这些假设值得压力测试——既因为它们可能是错误的,也因为它们可能随着模型改进而迅速过时。”
这是本文最重要的方法论贡献之一。它将 Harness 设计从”构建一个系统”提升到了”管理一组假设”。每个组件不是”功能”,而是”假设的外化”。当假设不再成立时,对应的组件就应该被移除。
8.2 简化的方法论:逐个组件消融
作者的第一次尝试是激进地大幅削减 Harness 并尝试一些新创意,但无法复现原始版本的性能。而且变得很难判断哪些部分真正承载了性能贡献。
基于这个教训,他转向了更系统的方法:每次只移除一个组件,观察它对最终结果的影响。这本质上是一种消融实验(ablation study)——机器学习研究中常用的方法,但这里应用在了 Harness 工程中。
8.3 Opus 4.6 带来的简化动力
Opus 4.6 的发布公告中提到的改进——更仔细的规划、更持久的 agentic 任务执行、更可靠的大代码库操作、更好的代码审查和调试能力、长上下文检索的大幅提升——恰好对应了 Harness 原本试图补充的每一项能力。
这给了作者强有力的理由去测试:这些组件是否仍然必要?
8.4 移除 Sprint 分解
结果:Sprint 结构可以完全去掉。Opus 4.6 原生能够处理不分解的长任务。
保留 Planner 的原因:没有 Planner,Generator 会范围不足(under-scope)——给定原始 prompt,它会直接开始构建而不先规格化工作,最终产品的功能不如有 Planner 时丰富。
Evaluator 的调整:从逐 Sprint 评估变为仅在最后做一次 pass。
8.5 Evaluator 价值的相对性
这是一个非常微妙的分析:
在 Opus 4.5 上,构建任务处于 Generator 能力的边缘——Solo 表现不佳,Evaluator 在整个构建过程中都能捕获有意义的问题。
在 Opus 4.6 上,模型的原始能力提升了,这个边界向外移动了。以前需要 Evaluator 检查才能正确实现的任务,现在在 Generator 的能力范围内了,Evaluator 对这些任务变成了不必要的开销。但对于仍然处于 Generator 能力边缘的那些部分,Evaluator 继续提供真实的提升。
“Evaluator 不是一个固定的 yes-or-no 决策。它在任务超出当前模型能可靠独立完成的范围时,才值得花成本。”
推论:随着每个新模型的发布,你应该重新评估 Evaluator 对你的特定任务是否仍然有价值。
8.6 新增的 AI 功能构建能力
在结构简化的同时,作者还增加了 prompt 来改善 Harness 在每个应用中构建 AI 功能的方式——具体来说,让 Generator 构建一个能够通过工具驱动应用功能的完整 Agent。
这需要”真正的迭代”(real iteration),因为相关知识足够新,Claude 的训练数据覆盖稀薄。但经过足够的调优,Generator 能够正确地构建 Agent。
九、简化后的 DAW 实测
9.1 测试 prompt
Build a fully featured DAW in the browser using the Web Audio API.
9.2 详细成本分解
| Agent 与阶段 | 时间 | 成本 |
|---|---|---|
| Planner | 4.7 分钟 | $0.46 |
| Build(第1轮) | 2 小时 7 分钟 | $71.08 |
| QA(第1轮) | 8.8 分钟 | $3.24 |
| Build(第2轮) | 1 小时 2 分钟 | $36.89 |
| QA(第2轮) | 6.8 分钟 | $3.09 |
| Build(第3轮) | 10.9 分钟 | $5.88 |
| QA(第3轮) | 9.6 分钟 | $4.06 |
| 总计 | 3 小时 50 分钟 | $124.70 |
值得注意的数据:
- Planner 只花了 4.7 分钟和 $0.46——这是整个 Harness 中 ROI 最高的组件
- Build 第1轮连续运行了 2 小时 7 分钟而不失连贯——在 Opus 4.5 上不可能
- QA 每轮 ~8 分钟,成本 ~$3——相对于 Build 的成本,是非常高效的质量保障
- Build 从第1轮的 2 小时缩减到第3轮的 11 分钟——因为大部分功能已经在前两轮实现,第3轮只是修复 QA 发现的问题
9.3 QA 的具体反馈
第1轮 QA 反馈:
“这是一个强大的应用,设计保真度出色,AI Agent 扎实,后端良好。主要失败点是功能完整性——虽然应用看起来令人印象深刻且 AI 集成运作良好,但几个核心 DAW 功能只有展示没有交互深度:片段无法在时间线上被拖动/移动,没有乐器 UI 面板(合成器旋钮、鼓垫),没有视觉效果编辑器(EQ 曲线、压缩器表)。这些不是边缘情况——它们是让 DAW 可用的核心交互,而且规格中明确要求了它们。”
这段 QA 反馈展示了一个经过校准的 Evaluator 的判断力:
- 先给出正面肯定(设计好、AI 集成好、后端好)
- 然后精准定位核心失败点(功能完整性)
- 区分了”展示性功能”和”可交互功能”——这是一个很专业的产品判断
- 明确指出这些不是边缘情况而是核心需求
- 引用了规格文档作为判断依据
第2轮 QA 反馈:
“剩余缺口:
- 音频录制仍然是 stub-only(按钮切换但没有麦克风捕获)
- 片段按边缘拖动调整大小和片段分割未实现
- 效果可视化是数字滑块,不是图形化的(没有 EQ 曲线)”
到第2轮,反馈变得更具体——从”几个核心功能缺失”到精确列出哪些具体功能仍然是 stub 或未实现。
9.4 最终产品评估
最终的 DAW 应用包含:
- 工作的编曲视图(arrangement view)
- 混音器(mixer)
- 走带控制(transport)
- 全部运行在浏览器中
- 内置 AI Agent,可以通过 prompt 驱动应用功能
作者通过 prompt 让 AI Agent 从头到尾制作了一段简短的歌曲:设置速度和调号 → 铺设旋律 → 构建鼓轨 → 调整混音器电平 → 添加混响。
坦诚的局限:
- 距离专业音乐制作程序还很远
- AI Agent 的作曲能力明显需要大量改进
- Claude 不能实际”听到”声音,这使得 QA 反馈循环在音乐品味方面不够有效——这是一个有趣的模态限制
十、总结:面向未来的方法论
10.1 三条核心教训
作者在结尾提炼了三条可以带到未来工作中的教训:
教训一:始终实验、阅读 trace、调优
- 与你正在构建的模型进行实验
- 在真实问题上阅读它的 trace(运行日志)
- 调优它的表现以达到你期望的结果
- 这是一个持续的过程,不是一次性的
教训二:任务分解和专门化 Agent 有时能带来额外空间
- 对于更复杂的任务,将任务分解并为每个方面应用专门化的 Agent,有时能释放出额外的性能空间
- 注意”有时”——这不是一个普遍规则,而是取决于任务是否处于模型的能力边界
教训三:新模型到来时,重新审视 Harness
- 剥离不再承载性能贡献的组件
- 添加新组件以实现之前不可能的更大能力
- 这是一个持续的迭代循环
10.2 最深层的洞察
“随着模型改进,有趣的 Harness 组合空间不会缩小。它会移动,AI 工程师的有趣工作是不断找到下一个新组合。”
这句话是全文的精华。它意味着:
- AI 工程不会因为模型变强而变得无聊或没有必要
- 相反,每次模型升级都打开了新的 Harness 设计空间
- 你以前因为模型能力不足而做不到的事,现在可以尝试了
- 这需要持续的探索和创新,而不是一劳永逸的架构
附录:关键引用与数据索引
关键数据点
- Solo run:20 分钟、$9、核心功能坏
- Full Harness V1(Opus 4.5):6 小时、$200、16 功能 10 Sprint
- Full Harness V2(Opus 4.6):3 小时 50 分钟、$124.70、3 轮 Build+QA
- 前端实验:5-15 轮迭代、最长 4 小时
- Sprint 3 合同标准数:27 个
- Evaluator 批准率(Agent 自身的权限审批数据):用户实际批准 93% 的权限提示
关键技术选型
| 组件 | 技术 |
|---|---|
| Agent 编排 | Claude Agent SDK |
| 端到端测试 | Playwright MCP |
| 前端 | React + Vite |
| 后端 | FastAPI |
| 数据库 | SQLite → PostgreSQL |
| 版本控制 | git |
| Agent 间通信 | 文件系统 |
模型能力演进对 Harness 的影响
| 模型 | 需要 Context Reset | 需要 Sprint 分解 | 需要逐 Sprint Evaluator | 连续工作时长 |
|---|---|---|---|---|
| Sonnet 4.5 | 是(Context Anxiety 严重) | 是 | 是 | 短(受 anxiety 限制) |
| Opus 4.5 | 否(Anxiety 基本消失) | 是 | 是 | 中等 |
| Opus 4.6 | 否 | 否 | 否(仅最后一次 pass) | 2+ 小时 |