精读Anthropic《Effective harnesses for long-running agents》

来源:Anthropic 博客,2025-11-26,作者 Justin Young
主题:如何为跨多个 context window 的长期运行 Agent 设计有效的 harness原文链接:https://www.anthropic.com/engineering/effective-harnesses-for-long-running-agents
一句话总结
长期运行 Agent 的核心难点不是单次能力,而是跨离散会话保持一致进展。
解决方案是 Initializer Agent + Coding Agent 双阶段模式,并配合 feature list JSON、progress 文件、git 历史、init.sh,让每个新会话快速恢复状态,一次只推进一个功能,测试后提交,并留下干净状态。
1. 核心问题
长期运行 Agent 必须在离散 session 中工作,每个新 session 开始时没有此前记忆。
这就像软件项目由轮班工程师开发,但每个新工程师都不记得上一班发生了什么。
即使有 context compaction,也不够。
前沿编码模型在 Claude Agent SDK 中循环跨多个 context window,如果只给“build a clone of claude.ai”这种高层 prompt,仍会失败。
主要失败表现为:
- 试图一次做完整个应用:导致 context 中途耗尽,留下半实现、无文档的功能,下一会话只能猜测并花大量时间恢复。
- 项目后期过早宣布完成:后续 Agent 看到已有进展,就认为任务完成。
2. 双代理方案
Initializer Agent
第一次 session 使用专门 prompt,负责搭建初始环境:
- 写
init.sh脚本 - 写
claude-progress.txt进度日志 - 创建初始 git commit,记录添加了哪些文件
- 根据用户输入 spec 写一份完整 feature list 文件
Coding Agent
之后每个 session 要求模型:
- 做增量进展
- 留下结构化更新
- 结束时保持环境干净
关键洞察:让 Agent 在 fresh context 中快速理解工作状态。
实现方式是 progress 文件 + git history,灵感来自高效软件工程师的日常工作方式。
3. 关键工件与设计
Feature List
为应对 Agent 一次做完或过早完成,Initializer Agent 要写一份全面的功能需求文件。
示例:claude.ai clone 中列出 200+ 个功能,例如:
用户能打开新聊天、输入查询、按回车、看到 AI 回复。
所有功能初始标记为 passes: false,让后续 Coding Agent 清楚完整功能范围。
示例结构:
{
"category": "functional",
"description": "New chat button creates a fresh conversation",
"steps": [
"Navigate to main interface",
"Click the 'New Chat' button",
"Verify a new conversation is created",
"Check that chat area shows welcome state",
"Verify conversation appears in sidebar"
],
"passes": false
}
规则:
- Coding Agent 只能修改
passes字段。 - 使用强措辞禁止删除或编辑测试,例如:“It is unacceptable to remove or edit tests because this could lead to missing or buggy functionality.”
- 使用 JSON 而不是 Markdown,因为模型更不容易不当修改或覆盖 JSON。
Progress 与 Git
每个 session 结束时:
- 用有描述性的 commit message 提交进度到 git
- 在 progress 文件中写进度总结
好处:
- 可以用 git 回滚坏改动
- 可以恢复代码库的工作状态
- 下一会话不必猜测发生了什么
- 提高整体效率
干净状态
“Clean state”指适合合并到 main branch 的状态:
- 没有重大 bug
- 代码有序、文档良好
- 开发者可以直接开始新功能,而不必先清理无关烂摊子
4. 失败模式与解决方案
| 问题 | Initializer Agent 行为 | Coding Agent 行为 |
|---|---|---|
| Claude 过早宣布整个项目完成 | 基于输入 spec,创建结构化 JSON feature list,包含端到端功能描述 | 开始时读 feature list,选择一个功能开始工作 |
| Claude 留下有 bug 或未记录进展的环境 | 写初始 git repo 和 progress notes 文件 | 开始时读 progress notes 和 git commit logs,并在开发服务器上跑基本测试,捕捉未记录 bug;结束时写 git commit 和 progress update |
| Claude 过早把功能标记为完成 | 创建 feature list 文件 | 自验证所有功能,只有仔细测试后才标记为 passing |
| Claude 花时间搞清如何运行应用 | 写 init.sh 脚本,可运行开发服务器 |
开始时读 init.sh |
5. 增量进展
Initializer 搭好环境后,Coding Agent 每次只做一个功能。
这种增量方式是解决“一次做太多”的关键。
即使增量工作,也必须保持干净状态:
- 提交 git
- 写 progress 摘要
- 只更新 feature list 中对应功能的
passes状态
6. 测试与验证
Claude 常见问题是:没有真正端到端测试,就标记功能完成。
它可能做单元测试或对开发服务器发 curl 请求,但没意识到功能端到端不可用。
解决方案:
- 显式提示使用浏览器自动化工具
- 像真实人类用户一样做所有测试
- 使用 Puppeteer MCP server 截图和验证
效果:显著提升性能,因为 Agent 能发现仅看代码不明显的 bug。
仍有限制:
- Claude 视觉能力有限
- 浏览器自动化工具有限
- 例如 Claude 通过 Puppeteer MCP 看不到浏览器原生 alert modal,依赖这些 modal 的功能更容易有 bug
7. 新会话启动流程
每个 Coding Agent 开始时被提示运行一系列步骤:
- 运行
pwd查看工作目录。只能编辑该目录中的文件。 - 读 git logs 和 progress files,了解最近做了什么。
- 读 features list 文件,选择最高优先级且尚未完成的功能。
- 读
init.sh,启动开发服务器。 - 跑基本端到端测试,确认应用没有坏。
- 开始实现新功能。
在 claude.ai clone 案例中:
- Agent 启动本地开发服务器
- 用 Puppeteer MCP 开新聊天、发消息、接收回复
- 快速判断应用是否被留在 broken state
- 如果有 bug,立即修复,而不是继续加新功能导致更糟
典型 session 开头:
[Assistant] I'll start by getting my bearings and understanding the current state of the project.
[Tool Use] <bash - pwd>
[Tool Use] <read - claude-progress.txt>
[Tool Use] <read - feature_list.json>
[Assistant] Let me check the git log to see recent work.
[Tool Use] <bash - git log --oneline -20>
[Assistant] Now let me check if there's an init.sh script to restart the servers.
<Starts the development server>
[Assistant] Excellent! Now let me navigate to the application and verify that some fundamental features are still working.
<Tests basic functionality>
[Assistant] Based on my verification testing, I can see that the fundamental functionality is working well...
<Starts work on a new feature>
8. 未来工作
仍待探索:
- 单一通用 coding agent 是否最优,还是多 Agent 架构更好。
- 专用 Agent,如 testing agent、QA agent、code cleanup agent,可能更适合软件生命周期中的子任务。
- 当前 demo 优化的是全栈 Web 应用开发。
- 未来可推广到科学研究、金融建模等长期 agentic 任务。
9. 重要脚注
文中把 initializer agent 和 coding agent 称为不同 Agent,只是因为它们的初始用户 prompt 不同。
系统 prompt、工具集和整体 agent harness 在其他方面完全相同。
10. 可操作清单
Initializer Agent 应产出
feature_list.json:完整功能列表,初始passes: falseclaude-progress.txt:进度日志init.sh:启动开发服务器并跑基本端到端测试- 初始 git commit
Coding Agent 每次开始
pwd- 读 progress 文件和 git log
- 读 feature list,选最高优先级未完成功能
- 读
init.sh - 启动开发服务器
- 跑基本端到端测试,确认当前状态可用
Coding Agent 每次结束
- 只完成一个功能
- 做端到端测试,像人类用户一样验证
- 只更新 feature list 的
passes字段 - 写描述性 git commit
- 更新 progress 文件
- 确保环境干净,适合合并到 main branch
核心结论
长期运行 Agent 的关键不是“更长的 context”,而是:
用外部工件和流程桥接 session:feature list 防止过早完成,progress + git 恢复状态,init.sh 降低启动成本,端到端测试防止虚假完成,一次一个功能防止 context 爆炸。
