本文由 Anthropic 工程师 Justin Young撰写:Effective harnesses for long-running agents。本文探讨了随着 AI Agent能力增强,在处理跨越数小时或数天的复杂任务(如软件工程)时面临的核心挑战:如何在多个有限的上下文窗口(context windows)之间保持工作的连贯性。作者指出,仅靠上下文压缩不足以解决问题,Agent 容易出现试图一次性完成任务(one-shotting)或过早宣布任务完成的失败模式。

为了解决上述问题,作者提出了一套基于 Claude Agent SDK 的双重解决方案:

  1. 初始化Agent (Initializer agent):负责在首次运行时设置环境和规划任务。
  2. 编码Agent (Coding agent):负责在后续会话中进行增量开发,并为下一次会话留下清晰的记录。

这一方案通过结构化的环境设置、详细的功能列表和严格的增量工作流,确保Agent 能够像人类工程师轮班一样,在没有先前记忆的情况下高效接手工作。

关键细节

核心挑战与失败模式

  • 上下文限制:Agent 在离散的会话中工作,新会话开始时没有之前的记忆。
  • 常见错误:在使用 Opus 4.5 等前沿模型时,若仅给出高层级提示,Agent 倾向于试图一次性构建整个应用,导致上下文耗尽、功能半途而废且缺乏文档;或者在仅完成部分功能后误判项目已完成。

解决方案的具体实施

  • 环境初始化:Initializer agent 会创建关键的基础设施,包括:
    • init.sh 脚本:用于启动开发环境。
    • claude-progress.txt 文件:记录Agent 的操作日志。
    • 初始的 git 提交:建立版本控制基础。
    • 功能列表(Feature List):创建一个包含详细需求的 JSON 文件(例如 claude.ai 克隆项目包含 200 多个功能点)。选择 JSON 而非 Markdown 是为了防止模型意外覆盖文件结构。

增量工作流与状态管理

  • 快速上手(Getting up to speed):Coding agent 在每个会话开始时执行标准化步骤:
    1. 运行 pwd 确认工作目录。
    2. 读取 git 日志和进度文件以了解最近的工作。
    3. 读取功能列表,选择优先级最高且未完成的功能。
    4. 运行 init.sh 并进行基础端到端测试,确保环境未损坏。
  • 保持环境整洁:Agent 被要求每次仅专注于一个功能,并在会话结束时通过 git 提交描述性信息和更新进度文件。这允许在代码出错时回滚。

测试的重要性

  • 端到端验证:文章强调仅靠单元测试是不够的。通过 Puppeteer MCP server 等工具让 Claude 进行浏览器自动化测试(像人类用户一样操作),能显著提高发现 bug 的能力。
  • 严格的通过标准:Agent 只能在经过仔细测试后,修改 JSON 文件中的 passes 字段状态,严禁随意删除或编辑测试项。

未来展望

目前的研究集中在全栈 Web 应用开发。未来的工作将探索多Agent 架构(如专门的测试Agent 或 QA Agent )是否优于通用的编码Agent ,并尝试将这些经验推广到科学研究或金融建模等其他领域。

原文:用于长期运行 Agent 的高效框架

发布于 2025 年 11 月 26 日

Agent 在跨越多个上下文窗口工作时仍然面临挑战。我们从人类工程师那里寻求灵感,旨在为长期运行的 Agent 创建更有效的运行框架。

随着 AI Agent 的能力越来越强,开发者越来越多地要求它们承担复杂的任务,这些工作往往需要持续数小时甚至数天。然而,让 Agent 在多个上下文窗口中保持持续进展仍然是一个未解难题。

长期运行 Agent 的核心挑战在于它们必须在离散的会话中工作,并且每个新会话开始时都没有之前的记忆。想象一个由轮班工程师组成的软件项目,每位新工程师在轮班开始时都不记得上一班发生了什么。由于上下文窗口是有限的,而且大多数复杂的项目无法在单个窗口内完成,Agent 需要一种方法来弥合编码会话之间的鸿沟。

我们开发了一个双重解决方案,使 Claude Agent SDK 能够在多个上下文窗口中有效工作:一个是初始化 Agent,负责在首次运行时设置环境;另一个是编码 Agent,负责在每个会话中取得增量进展,并为下一个会话留下清晰的产物。你可以在随附的快速入门中找到代码示例。

长期运行 Agent 的难题

Claude Agent SDK 是一个强大的、通用的 Agent 运行框架,擅长编码以及其他需要模型使用工具来收集上下文、规划和执行的任务。它具有上下文管理功能(如压缩),使 Agent 能够处理任务而不会耗尽上下文窗口。理论上,在此设置下,Agent 应该能够持续进行任意时长的有效工作。

然而,仅靠压缩是不够的。开箱即用状态下,即使像 Opus 4.5 这样的前沿编码模型,在 Claude Agent SDK 上跨多个上下文窗口循环运行,如果只给出一个高层级的提示词,例如“构建一个 claude.ai 的克隆版”,也无法构建出生产级的 Web 应用。

Claude 的失败主要表现为两种模式。首先,Agent 倾向于试图一次做太多事情——本质上是试图一次性(one-shot)完成应用。通常,这会导致模型在实现过程中耗尽上下文,留给下一个会话的是实现了一半且没有文档记录的功能。随后的 Agent 不得不猜测发生了什么,并花费大量时间试图让基础应用重新运行起来。即使有压缩功能也会发生这种情况,因为它并不总能向下一个 Agent 传递完美清晰的指令。

第二种失败模式通常发生在项目的后期。在构建了一些功能之后,后来的 Agent 实例会环顾四周,看到已经取得了一些进展,便宣布工作完成。

这可以将问题分解为两个部分。首先,我们需要设置一个初始环境,为给定提示词所需的所有功能奠定基础,从而让 Agent 能够按功能逐步工作。其次,我们应该提示每个 Agent 朝着目标取得增量进展,同时在会话结束时将环境保持在整洁状态。所谓的“整洁状态”指的是适合合并到主分支的代码:没有重大 Bug,代码有序且文档齐全,总体而言,开发者可以轻松开始新功能的工作,而无需先清理不相关的烂摊子。

在内部实验时,我们使用两部分解决方案解决了这些问题:

  1. 初始化 Agent:第一个 Agent 会话使用专门的提示词,要求模型设置初始环境:一个 init.sh 脚本,一个记录 Agent 已完成工作的 claude-progress.txt 文件,以及一个显示添加了哪些文件的初始 git 提交。
  2. 编码 Agent:随后的每个会话都要求模型取得增量进展,然后留下结构化的更新。<sup>1</sup>

这里的关键洞察是找到一种方法,让 Agent 在以全新的上下文窗口开始时能够快速理解工作状态,这通过 claude-progress.txt 文件和 git 历史记录来实现。这些实践的灵感来自于了解高效软件工程师每天的所作所为。

环境管理

在更新后的 Claude 4 提示词指南中,我们分享了一些关于多上下文窗口工作流的最佳实践,包括使用“在第一个上下文窗口使用不同提示词”的框架结构。这个“不同的提示词”要求初始化 Agent 设置环境,并包含未来编码 Agent 有效工作所需的所有必要上下文。在这里,我们将深入探讨这种环境的一些关键组件。

功能列表

为了解决 Agent 试图一次性完成应用或过早认为项目完成的问题,我们提示初始化 Agent 编写一个详尽的功能需求文件,以扩展用户的初始提示词。在 claude.ai 克隆版的例子中,这意味着超过 200 个功能,例如“用户可以打开新聊天,输入查询,按回车键,并看到 AI 的回复”。这些功能最初都被标记为“failing”(未通过),以便后续的编码 Agent 对完整功能的样子有一个清晰的大纲。

{
    "category": "functional",
    "description": "新建聊天按钮创建新的对话",
    "steps": [
      "导航至主界面",
      "点击 'New Chat' 按钮",
      "验证是否创建了新对话",
      "检查聊天区域是否显示欢迎状态",
      "验证侧边栏是否出现对话"
    ],
    "passes": false
  }

我们提示编码 Agent 只能通过更改 passes 字段的状态来编辑此文件,并使用措辞强硬的指令,如“不可删除或编辑测试,因为这可能导致功能缺失或 Bug”。经过一些实验,我们最终决定使用 JSON 格式,因为与 Markdown 文件相比,模型不太可能不恰当地更改或覆盖 JSON 文件。

增量进展

有了这个初始环境脚手架,下一次迭代的编码 Agent 被要求一次只处理一个功能。这种增量方法对于解决 Agent 试图一次做太多事情的倾向至关重要。

一旦开始增量工作,在进行代码更改后让模型将环境保持在整洁状态仍然至关重要。在我们的实验中,我们发现引出这种行为的最佳方法是要求模型将其进展提交到 git,并附上描述性的提交信息,并在进度文件中编写其进展摘要。这使得模型可以使用 git 回滚糟糕的代码更改,并恢复代码库的工作状态。

这些方法也提高了效率,因为它们消除了 Agent 猜测发生过什么以及花费时间试图让基础应用重新工作的需要。

测试

我们要观察的最后一个主要失败模式是 Claude 倾向于在没有适当测试的情况下将功能标记为完成。如果没有明确的提示,Claude 往往会进行代码更改,甚至使用单元测试或针对开发服务器的 curl 命令进行测试,但无法识别该功能并未通过端到端的验证。

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

Claude 通过 Puppeteer MCP 服务器在测试 claude.ai 克隆版时截取的屏幕截图。

为 Claude 提供这类测试工具显著提高了性能,因为 Agent 能够识别并修复那些仅凭代码无法明显发现的 Bug。

仍然存在一些问题,例如 Claude 的视觉限制以及浏览器自动化工具的局限性,使得识别每种类型的 Bug 变得困难。例如,Claude 无法通过 Puppeteer MCP 看到浏览器原生的警告弹窗(alert modals),因此依赖这些弹窗的功能往往会有更多 Bug。

快速上手

有了上述所有准备,每个编码 Agent 都会被提示运行一系列步骤来熟悉环境,有些步骤非常基础但仍然很有帮助:

  1. 运行 pwd 查看你正在工作的目录。你只能编辑此目录中的文件。
  2. 阅读 git 日志和进度文件,以快速了解最近的工作内容。
  3. 阅读功能列表文件,并选择尚未完成的最高优先级功能进行处理。

这种方法在每个会话中为 Claude 节省了一些 Token,因为它不需要弄清楚如何测试代码。这也有助于要求初始化 Agent 编写一个可以运行开发服务器的 init.sh 脚本,然后在实现新功能之前运行基本的端到端测试。

在 claude.ai 克隆版的案例中,这意味着 Agent 总是启动本地开发服务器,并使用 Puppeteer MCP 开始新聊天、发送消息并接收回复。这确保了 Claude 能够快速识别应用是否处于损坏状态,并立即修复任何现有的 Bug。如果 Agent 转而开始实现新功能,很可能会使问题变得更糟。

鉴于此,一个典型的会话通常以以下助手消息开始:

[Assistant] 我将从熟悉环境和了解项目的当前状态开始。
[Tool Use] <bash - pwd>
[Tool Use] <read - claude-progress.txt>
[Tool Use] <read - feature_list.json>
[Assistant] 让我检查 git 日志以查看最近的工作。
[Tool Use] <bash - git log --oneline -20>
[Assistant] 现在让我检查是否有 init.sh 脚本来重启服务器。
<启动开发服务器>
[Assistant] 太好了!现在让我导航到应用程序并验证一些基本功能是否仍然正常工作。
<测试基本功能>
[Assistant] 根据我的验证测试,我可以看到基本功能运行良好。核心聊天功能、主题切换、对话加载和错误处理都正常运行。现在让我更全面地查看 tests.json 文件,以了解接下来需要实现什么。
<开始处理新功能>

Agent 故障模式与解决方案

问题初始化 Agent 行为编码 Agent 行为
Claude 过早宣布整个项目胜利。设置功能列表文件:根据输入规范,设置一个结构化的 JSON 文件,其中包含端到端功能描述列表。在会话开始时阅读功能列表文件。选择单个功能开始工作。
Claude 留下的环境存在 Bug 或未记录进展。编写初始 git 仓库和进度说明文件。通过阅读进度说明文件和 git 提交日志开始会话,并在开发服务器上运行基本测试以捕获任何未记录的 Bug。通过编写 git 提交和进度更新结束会话。
Claude 过早将功能标记为完成。设置功能列表文件。自我验证所有功能。仅在仔细测试后将功能标记为“通过”。
Claude 必须花费时间弄清楚如何运行应用。编写一个可以运行开发服务器的 init.sh 脚本。通过阅读 init.sh 开始会话。

总结长期运行 AI Agent 中的四种常见故障模式及解决方案。

未来工作

这项研究展示了长期运行 Agent 运行框架中一套可能的解决方案,使模型能够在多个上下文窗口中取得增量进展。然而,仍有未解的问题。

最值得注意的是,目前尚不清楚是单个通用编码 Agent 在跨上下文中表现最佳,还是通过多 Agent 架构(multi-agent architecture)能实现更好的性能。似乎有理由认为,像测试 Agent、质量保证 Agent 或代码清理 Agent 这样的专用 Agent,可能在软件开发生命周期的子任务中做得更好。

此外,该演示针对全栈 Web 应用开发进行了优化。未来的方向是将这些发现推广到其他领域。这些经验中的部分或全部很可能可以应用于其他需要长期运行 Agent 任务的领域,例如科学研究或金融建模。

致谢

作者:Justin Young。特别感谢 David Hershey, Prithvi Rajasakeran, Jeremy Hadfield, Naia Bouscal, Michael Tingley, Jesse Mu, Jake Eaton, Marius Buleandara, Maggie Vo, Pedram Navid, Nadine Yasser, 和 Alex Notov 的贡献。

这项工作反映了 Anthropic 多个团队的共同努力,正是他们使 Claude 能够安全地进行长周期的自主软件工程,特别是代码 RL 和 Claude Code 团队。有兴趣做出贡献的候选人欢迎在 anthropic.com/careers 申请。

脚注

1. 我们在此上下文中将它们称为单独的 Agent,仅仅是因为它们具有不同的初始用户提示词。系统提示词、工具集和整体 Agent 运行框架在其他方面是相同的。

获取开发者通讯

产品更新、操作指南、社区焦点等。每月发送至您的收件箱。

如果您想接收我们的每月开发者通讯,请提供您的电子邮件地址。您可以随时退订。