本页目录8
- 长运行代理的两大失败模式:一次性做太多导致上下文耗尽留下半成品;或看到已有进展就误判任务已完成
- 解决思路是两阶段架构:「初始化代理」负责搭好 init.sh、claude-progress.txt 和初始 git 提交;「编码代理」负责后续每轮的增量推进
- 用 JSON 而非 Markdown 维护功能清单(feature list),并用严厉指令禁止代理擅自删改测试项,减少模型「篡改验收标准」的倾向
- 每个编码代理会话开始时执行固定流程:pwd 看目录、读 git log 与 progress 文件、读功能清单选一个最高优先级功能来做
- 仅靠单元测试和 curl 不足以验证端到端行为,配合 Puppeteer MCP 做浏览器级别的真实操作测试效果提升明显,但对原生弹窗等仍有盲区
- 是否该用单一通用编码代理还是拆分为测试代理、QA 代理、代码清理代理等专科角色,目前还是开放问题
本文是对 Anthropic 官方文章 Effective harnesses for long-running agents 的中文要点摘要,完整内容以原文为准:https://www.anthropic.com/engineering/effective-harnesses-for-long-running-agents
问题背景
当任务从「几分钟内完成」扩展到「横跨数小时甚至数天」时,Claude Code 这类智能体必须在一个个离散的会话(session)里断续工作——每个新会话都不记得上一个会话发生了什么。文章把这个处境比作「轮班的工程师,但每一位新工程师都不记得上一班做了什么」。
这带来两种典型的失败模式:
- 一次性塞太多工作:代理试图在单个会话里把任务做完,结果耗尽上下文窗口,留下一个「做了一半、没有文档」的功能给下一个会话。
- 误判任务已完成:后续会话的代理一看到已经有不少进展,就倾向于「宣布任务完成」,即便实际上还有大量工作没做。
核心架构:初始化代理 + 编码代理
文章给出的解法是把长任务拆成两类角色:
初始化代理(Initializer Agent) 只在第一个会话里跑,专门负责搭脚手架:
- 写一个
init.sh脚本,用来一键启动开发服务器等环境 - 生成
claude-progress.txt,作为跨会话的工作日志 - 提交一次初始 git commit,把已添加的文件记录下来
编码代理(Coding Agent) 负责后续所有会话,职责是:
- 每次只推进一小步(增量式进展)
- 每轮结束时留下结构化的更新(git 提交 + progress 文件摘要)
- 保持仓库处于「干净状态」——没有明显 bug、代码有条理、文档跟得上
用功能清单防止「假装做完」
为了避免代理过早宣布完成或悄悄放水,初始化代理会先生成一份详尽的功能清单文件。文章举了一个 claude.ai 克隆项目的例子,清单里列了 200 多条具体功能点,比如「用户能打开新聊天、输入查询、按回车、看到 AI 响应」。
这份清单用 JSON 而不是 Markdown 存储,每一项初始都标记为 passes: false,例如:
{
"category": "functional",
"description": "新聊天按钮创建新对话",
"passes": false
}
之所以选 JSON,是因为模型「不太可能不当修改 JSON 文件」的结构,配合提示词里「删除或编辑测试项是不可接受的」这类强约束,能有效防止代理为了显得「已完成」而擅自削弱验收标准。
每个会话的固定启动流程
为了让新会话快速接上下文,文章建议每个编码代理会话开始时都走一套固定动作:
- 执行
pwd确认工作目录 - 读 git log 和
claude-progress.txt,了解最近做了什么 - 读功能清单,挑一个优先级最高、还没通过的功能来做
这套流程能省去代理每次都要「重新猜测该怎么测试」的开销,直接进入正题。一个典型的会话开场大致是:先看 progress 文件和功能清单,再看 git log,然后跑 init.sh 或直接启动开发服务器,做一轮基础功能的手动验证,再挑一个功能开始干活。
测试要动手,不能只靠单元测试
文章提到一个反直觉的观察:Claude「倾向于在没有充分测试的情况下就标记功能完成」,而单元测试和 curl 命令并不足以验证端到端的用户体验。
解法是给代理配上浏览器自动化工具(文中用的是 Puppeteer MCP),让它能「像真实用户一样」点击、输入、观察页面,这样代理才能发现并修掉那些从代码本身看不出来的 bug。文章也坦承局限性:Claude 目前无法通过 Puppeteer MCP 看到浏览器原生的 alert 弹窗一类的模态框,所以依赖这类交互的功能仍然更容易出问题。
失败模式与对应设计的对照
| 常见问题 | 初始化代理怎么应对 | 编码代理怎么应对 |
|---|---|---|
| 过早宣布项目完成 | 依据需求规格生成结构化功能清单 JSON | 会话开始先读清单,只挑一个功能推进 |
| 留下带 bug、无文档的烂摊子 | 建好初始 git 仓库和 progress 文件 | 会话开始读 progress+git log,跑基础测试;会话结束提交并更新 progress |
| 谎报某功能已完成 | 建好功能清单文件 | 只有认真测试通过后才把 passes 改为 true |
| 浪费时间摸索怎么跑起来 | 写好 init.sh | 会话开始先读 init.sh 直接执行 |
尚未解决的问题
文章坦率地留了两个开放问题:
- 到底是用一个通用的编码代理贯穿始终更好,还是拆成多个专科代理(比如专门的测试代理、QA 代理、代码清理代理)分工协作效果更佳,目前还不明确。
- 当前这套方法主要是针对全栈 Web 应用开发场景打磨出来的,能否推广到科学研究、财务建模等其他长任务领域,还有待验证。
本站解读:对 Claude Code 使用者的启示
(本站引申,非原文内容)即便不自己写多代理系统,普通用户在用 Claude Code 处理长任务时也可以借鉴这套思路:主动让 Claude 维护一份具体到「每一条可验证行为」的功能/任务清单(而不是笼统的 TODO),坚持用 git 做频繁的小颗粒度提交,并在每轮对话开始时明确要求它先读进度记录和 diff 再动手,这些做法能显著降低「Claude 说做完了但其实没做完」的情况。