长周期 AI Agent 的高效 Harness 设计 —— Anthropic 工程实践深度解析

发布时间: 2025 年 11 月 26 日
作者: Justin Young (Anthropic)
原文: Effective harnesses for long-running agents


引言

随着 AI Agent 能力不断增强,开发者越来越多地让它们承担需要数小时甚至数天才能完成的复杂任务。然而,让 Agent 在多个上下文窗口之间持续取得进展仍然是一个未解决的难题

Anthropic 工程团队通过研究人类工程师的工作方式,为 Claude Agent SDK 设计了一套高效的长周期任务 Harness 系统。本文将深入解析这套方案的核心设计思路和实现细节。


一、核心问题:长周期 Agent 的困境

1.1 上下文窗口的限制

长周期 Agent 的核心挑战在于:它们必须在离散的会话中工作,每个新会话开始时对之前的工作没有任何记忆

想象一个软件项目由轮班工作的工程师负责,但每个新来的工程师都不记得上一班发生了什么——这就是当前 Agent 面临的处境。由于上下文窗口有限,而大多数复杂项目无法在单个窗口内完成,Agent 需要一种方法来弥合编码会话之间的差距。

1.2 两种典型失败模式

Anthropic 团队在实验中发现,即使是 Opus 4.5 这样的前沿编码模型,在仅给出高级提示(如"构建一个 claude.ai 克隆")的情况下,也会出现两种失败模式:

失败模式一:一次性完成(One-Shot)倾向

  • Agent 倾向于尝试一次性完成整个应用
  • 经常在实现中途耗尽上下文
  • 下一个会话开始时面对的是半完成、无文档的功能
  • 后续 Agent 必须猜测之前发生了什么,花费大量时间让应用重新运行
  • 即使使用上下文压缩(compaction),也无法总是传递清晰的指令

失败模式二:过早宣布完成

  • 在项目后期,后续 Agent 实例查看已构建的功能后
  • 错误地认为工作已经完成
  • 实际上还有很多功能未实现

二、解决方案:双 Agent 架构

Anthropic 开发了一个两部分解决方案,使 Claude Agent SDK 能够有效跨越多个上下文窗口工作:

┌─────────────────────────────────────────────────────────┐
│                   长周期 Agent Harness                    │
├─────────────────────────────────────────────────────────┤
│  ┌─────────────────┐         ┌─────────────────────┐   │
│  │ Initializer     │  ────→  │  Coding Agent       │   │
│  │ Agent           │         │  (循环执行)         │   │
│  │ (首次运行)       │         │                     │   │
│  └─────────────────┘         └─────────────────────┘   │
│         ↓                          ↓                    │
│  • init.sh 脚本              • 每次会话 incremental   │
│  • claude-progress.txt       • 清晰的交接文档        │
│  • 初始 git commit           • 描述性 commit message  │
│  • 完整功能列表              • 进度总结              │
└─────────────────────────────────────────────────────────┘

2.1 Initializer Agent(初始化 Agent)

第一个 Agent 会话使用专门的提示,要求模型设置初始环境,包括:

组件 作用
init.sh 脚本 启动开发服务器,运行基础端到端测试
claude-progress.txt 记录每个 Agent 完成的工作日志
初始 git commit 显示添加了哪些文件
功能需求列表 扩展用户初始提示的完整功能清单

2.2 Coding Agent(编码 Agent)

每个后续会话要求模型:

  • 每次只实现一个功能(增量式进展)
  • 提交带有描述性 commit message 的 git 提交
  • 在进度文件中写下工作摘要
  • 保持代码处于"干净状态"(可合并到主分支的状态)

关键洞察:让 Agent 在开始新上下文窗口时快速理解工作状态的方法是通过 claude-progress.txt 文件和 git 历史记录。这一灵感来自有效软件工程师的日常实践。


三、环境管理详解

3.1 功能列表(Feature List)

为了解决 Agent 一次性完成应用或过早认为项目完成的问题,Initializer Agent 被提示编写一个全面的功能需求文件,扩展用户的初始提示。

以 claude.ai 克隆为例:

  • 超过 200 个功能点,例如:“用户可以打开新聊天、输入查询、按回车、看到 AI 响应”
  • 所有功能初始标记为"failing"
  • 后续编码 Agent 有清晰的目标清单

格式选择:使用 JSON 格式存储功能状态

  • 原因:模型不太可能不当地更改或覆盖 JSON 文件(相比 Markdown)
  • Agent 只能通过更改 passes 字段的状态来编辑此文件
  • 使用强烈措辞的指令:“删除或编辑测试是不可接受的,因为这可能导致功能缺失或 bug”

3.2 增量式进展

有了初始环境框架后,编码 Agent 被要求一次只处理一个功能。这种增量方法被证明对解决 Agent 一次性做太多事情的倾向至关重要。

3.3 保持干净状态

一旦实现增量工作,模型在代码更改后保持环境干净仍然至关重要:

  • 提交到 git,使用描述性的 commit message
  • 在进度文件中写入摘要
  • 允许模型使用 git 回退不良代码更改,恢复代码库的工作状态

这些方法提高了效率,因为消除了 Agent 猜测之前发生的情况并花费时间让应用重新运行的需要。


四、测试策略

4.1 端到端测试的必要性

另一个主要失败模式:Claude 倾向于在没有适当测试的情况下标记功能为完成

在没有明确提示的情况下,Claude 会:

  • 进行代码更改
  • 使用单元测试或 curl 命令对开发服务器进行测试
  • 但未能认识到功能在端到端层面不起作用

4.2 浏览器自动化测试

在构建 Web 应用的情况下,一旦明确提示使用浏览器自动化工具并像人类用户一样进行所有测试,Claude 在端到端验证功能方面表现良好。

具体实现

  • 使用 Puppeteer MCP 进行浏览器自动化
  • 启动本地开发服务器
  • 模拟用户操作:打开新聊天 → 发送消息 → 接收响应
  • 确保 Claude 能快速识别应用是否处于损坏状态,并立即修复现有 bug

效果:提供这些测试工具显著提高了性能,因为 Agent 能够识别和修复仅从代码中不明显的 bug。

4.3 现有局限性

一些问题仍然存在:

  • Claude 的视觉能力有限
  • 浏览器自动化工具的限制使其难以识别每种 bug
  • 例如:Claude 无法通过 Puppeteer MCP 看到浏览器原生的 alert 模态框
  • 依赖这些模态框的功能往往 bug 更多

五、标准会话流程

每个编码 Agent 都被提示通过一系列步骤来获取状态,有些非常基础但仍然有用:

5.1 会话开始步骤

1. 运行 pwd 查看工作目录(只能编辑此目录中的文件)
2. 阅读 git 日志和进度文件,了解最近工作内容
3. 阅读功能列表,选择优先级最高且未完成的功能
4. 运行 init.sh 启动开发服务器
5. 运行基础端到端测试确保应用正常工作
6. 开始实现新功能

5.2 典型会话的 Assistant 消息

典型会话以以下 assistant 消息开始:

1. "首先,让我检查一下当前目录和最近的更改..."
2. "让我阅读功能列表以确定下一个要处理的功能..."
3. "在开始之前,让我运行 init.sh 并验证应用是否正常工作..."
4. "现在开始实现 [功能名称]..."
5. "实现完成后,让我运行测试并提交更改..."

这种方法为 Claude 节省了每个会话的 token,因为它不必弄清楚如何测试代码。


六、失败模式与解决方案总结

失败模式 解决方案
Agent 尝试一次性完成整个应用 功能列表 + 增量式进展(一次一个功能)
后续 Agent 过早宣布完成 功能列表明确标记完成状态
会话之间丢失上下文 claude-progress.txt + git 日志
代码状态混乱 描述性 commit + 进度摘要
测试不充分 浏览器自动化 + 端到端测试
无法快速恢复工作状态 init.sh + 基础测试流程

七、未来工作方向

这项研究展示了一套可能的解决方案,但仍有未解决的问题:

7.1 多 Agent 架构

关键问题:单个通用编码 Agent 在跨上下文时表现最佳,还是通过多 Agent 架构可以获得更好的性能?

潜在方向

  • 测试 Agent:专门负责测试
  • 质量保证 Agent:专门负责代码审查
  • 代码清理 Agent:专门负责重构和优化

这些专业化 Agent 可能在软件开发生命周期的子任务上表现得更好。

7.2 领域泛化

当前 demo 针对全栈 Web 应用开发进行了优化。未来方向是将这些发现推广到其他领域:

  • 科学研究
  • 金融建模
  • 其他需要长周期 Agent 任务的领域

这些经验教训的部分或全部可能适用于这些领域。


八、实践建议

基于 Anthropic 的工程实践,以下是构建长周期 Agent Harness 的关键建议:

8.1 初始化阶段

  1. 使用专门的 Initializer Agent 设置环境
  2. 创建详细的功能列表(JSON 格式)
  3. 所有功能初始标记为未完成
  4. 创建 init.sh 脚本用于环境验证

8.2 执行阶段

  1. 强制增量式进展(一次一个功能)
  2. 要求描述性 git commit
  3. 维护进度日志文件
  4. 每次会话前运行基础测试

8.3 测试策略

  1. 使用浏览器自动化进行端到端测试
  2. 像人类用户一样测试功能
  3. 在实现新功能前验证现有功能正常

8.4 上下文管理

  1. 使用 git 日志传递历史信息
  2. 使用进度文件记录决策
  3. 保持代码处于可合并状态

九、代码资源

Anthropic 提供了配套的 quickstart 代码示例


结语

Anthropic 的这套长周期 Agent Harness 设计展示了一个重要原则:有效的 Agent 系统设计需要从人类工程实践中汲取灵感

通过模拟人类工程师的轮班交接流程(进度文档、版本控制、测试流程),Agent 能够在多个离散会话中保持一致性和效率。虽然这仍然是一个探索中的领域,但这些实践为构建可靠的长周期 Agent 系统提供了坚实的基础。

随着 AI Agent 能力的不断提升,我们可以期待看到更多针对特定领域优化的 Harness 设计,以及可能出现的更复杂的多 Agent 协作架构。

原文链接:https://www.anthropic.com/engineering/effective-harnesses-for-long-running-agents

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐