长任务 agent 的 harness 设计:模型往往不是瓶颈
当我们想让 Claude 仅凭一句 prompt 就造出能跑的完整应用时,发现模型本身很少是瓶颈。真正的杠杆在 harness——围绕模型的那一圈脚手架:prompt、工具、控制流、反馈环。
这篇讲我们为「长任务应用开发 agent」设计 harness 时学到的东西。这类 agent 一跑就是几个小时、写出几千行代码,还得全程把质量稳住。
核心难题:长跑会让质量衰减
一个能写出漂亮 200 行小应用的模型,写到 2000 行时常常变成一团乱麻。失败会累积放大:agent 忘了早先的决定、把已经写过的东西重新实现一遍、自相矛盾地推翻自己的架构——最阴险的是,它给自己的活打分太宽松。
我们反复见到三个问题:
| 问题 | 表现 |
|---|---|
| 上下文耗尽(context exhaustion) | 工作上下文被代码、工具输出、过往推理塞满,模型对任何单个细节的注意力都在下降 |
| 自评偏差(self-evaluation bias) | 同一个 agent 又写又判,往往会自信地夸自己平庸的产出 |
| 目标漂移(goal drift) | 跑久了慢慢忘掉原始规格,转而为「局部进展」做优化 |
把记忆当工具,而不是往上下文里倒
我们的第一反应是给 agent 更多 上下文。结果适得其反——把完整历史塞进 context window,衰减反而更严重。
真正有用的做法是:把记忆当成一个显式、可查询的工具。agent 不再把所有东西一路背着走,而是把耐久的笔记(规格、架构决策、一份动态任务清单)写进外部存储,到了某一步只读回当前相关的那部分。
这其实就是人类工程师的工作方式:你不会把整个代码库装在脑子里,你做笔记,需要时再查。
⭐ 杠杆最大的一招:生成与评估分离
我们做过的单个收益最高的改动,就是把「产出工作的 agent」和「评估工作的 agent」拆开。
一个 agent 又写又评时,它是在「按自己的曲线打分」。一个独立的评估者——给它写明白的标准——能抓到生成者完全看不见的问题。这个直觉借自 GAN(生成对抗网络):一个生成器和一个判别器互相较劲,产出比任何一方单干都好。
针对前端工作,我们给评估者四条明确的打分维度:
| 维度 | 看什么 |
|---|---|
| 设计质量 | 布局、排版、配色、视觉层次 |
| 原创性 | 有没有避开那种千篇一律的模板感 |
| 工艺 | 间距、对齐,那些小细节 |
| 功能性 | 每个功能是不是真的能用 |
把标准写明确,就把一句空泛的「做好看点」变成了评估者能度量、生成者能据此动手的东西。
三 agent 架构
做全栈应用开发时,我们收敛到三个角色:
- Planner(规划者):把用户的一句短 prompt 扩展成详细的产品规格——功能、数据模型、用户流程。
- Generator(生成者):按规格逐个功能实现。我们的技术栈是 React、Vite、FastAPI、SQLite。
- Evaluator(评估者):用 Playwright 把应用跑起来,像真实用户那样把每个功能都点一遍,再把具体的 bug 报告回传给生成者。
循环这样转:规划 → 生成 → 评估 → 修复 → 再评估,直到评估者点头,或者预算用光。
上下文重置与「上下文焦虑」
我们发现,把长跑拆成一段段离散的 sprint——每段开一个干净的上下文,只用耐久记忆库做种子——能大幅提升「持续输出的质量」。
有意思的是,需不需要这么做,高度取决于模型:
| 模型 | 表现 |
|---|---|
| Sonnet 4.5 | 出现我们叫做「上下文焦虑」(context anxiety)的现象:上下文一满,它就开始赶工、偷工减料、过早宣布「干完了」。重置上下文能缓解 |
| Opus 4.6 | 能撑住长得多的连续会话而不出现同样的衰减,能把一个连贯的计划带着走过多得多的工作量,才需要重置 |
由此得到一条关键直觉:模型越强,harness 可以越简单。我们今天搭的大量脚手架,本质是在弥补当前模型的局限。
这对未来意味着什么
harness 不是一个永久的固定件——它是个移动靶,应该跟着模型能力一起走。今天的最佳实践是「重脚手架」:显式记忆、独立评估者、频繁重置上下文。随着模型越来越擅长在长跨度上维持自身的连贯性,这些脚手架应该逐步消解。
我们认为真正耐久的几条经验是:
- 把生成和评估分开 —— 这条经得起模型升级。
- 把质量标准写明确 —— 空泛的目标只会产出空泛的结果。
- 把记忆当工具,别当垃圾桶。
- 让 harness 在模型变强时主动让路。
总结
我们的目标是让 Claude 成为做这类「长跑、代理式」任务的最佳模型。而这件事很反直觉的一面是:其中很大一部分工作,恰恰是学会什么时候别去过度设计围绕模型的那圈脚手架。