译:长时间运行智能体的有效控制框架
原文:https://www.anthropic.com/engineering/effective-harnesses-for-long-running-agents
作者:Justin Young
译者:Gemini 3 Pro High
发布于 2025 年 11 月 26 日
智能体在跨多个上下文窗口工作时仍面临挑战。我们从人类工程师那里汲取灵感,为长时间运行的智能体创建了更有效的控制框架。
随着 AI 智能体能力的不断增强,开发者们越来越多地要求它们承担需要数小时甚至数天才能完成的复杂任务。然而,如何让智能体在多个上下文窗口之间持续取得进展,仍是一个悬而未决的问题。
长时间运行智能体的核心挑战在于它们必须在离散的会话中工作,而每个新会话开始时都没有之前的记忆。想象一下,一个软件项目由轮班工作的工程师负责,每位新工程师到来时都对上一班发生的事情一无所知。由于上下文窗口有限,而且大多数复杂项目无法在单个窗口内完成,智能体需要一种方法来弥合编码会话之间的差距。
我们开发了一个双重解决方案,使 Claude Agent SDK 能够有效地跨多个上下文窗口工作:一个初始化智能体在首次运行时设置环境,以及一个编码智能体负责在每个会话中取得增量进展,同时为下一个会话留下清晰的工件。您可以在附带的 快速入门 中找到代码示例。
长时间运行智能体问题
Claude Agent SDK 是一个强大的通用智能体控制框架,擅长编码以及其他需要模型使用工具来收集上下文、规划和执行的任务。它具有上下文管理功能,例如压缩,这使智能体能够在不耗尽上下文窗口的情况下处理任务。从理论上讲,有了这种设置,智能体应该能够在任意长的时间内继续做有用的工作。
然而,压缩是不够的。开箱即用的情况下,即使是像 Opus 4.5 这样的前沿编码模型在 Claude Agent SDK 上跨多个上下文窗口循环运行,如果只给它一个高级别的提示,例如"构建一个 claude.ai 的克隆",它也无法构建出生产级质量的 Web 应用程序。
Claude 的失败表现为两种模式。首先,智能体倾向于一次尝试做太多事情——本质上是试图一步到位完成整个应用程序。这通常会导致模型在实现过程中耗尽上下文,使下一个会话不得不从一个实现了一半且没有文档记录的功能开始。然后,智能体不得不猜测发生了什么,并花费大量时间试图让基本应用程序再次运行。即使使用压缩也会发生这种情况,因为压缩并不总是能向下一个智能体传递完全清晰的指令。
第二种失败模式通常发生在项目的后期。在一些功能已经构建之后,后来的智能体实例会四处查看,看到已经取得了进展,就宣布任务完成了。
这将问题分解为两部分。首先,我们需要设置一个初始环境,为给定提示所需的所有功能奠定基础,这使智能体能够逐步、逐个功能地工作。其次,我们应该提示每个智能体朝着其目标取得增量进展,同时在会话结束时将环境保持在干净状态。我们所说的"干净状态"是指适合合并到主分支的代码:没有重大错误,代码整洁且有良好的文档记录,通常,开发人员可以轻松地开始开发新功能,而无需先清理无关的混乱。
在内部实验时,我们使用两部分解决方案解决了这些问题:
- 初始化智能体:第一个智能体会话使用专门的提示,要求模型设置初始环境:一个
init.sh脚本、一个记录智能体已完成工作的 claude-progress.txt 文件,以及一个显示添加了哪些文件的初始 git 提交。 - 编码智能体:每个后续会话都要求模型取得增量进展,然后留下结构化的更新。¹
这里的关键洞察是找到一种方法,让智能体在以全新的上下文窗口启动时能够快速了解工作状态,这通过 claude-progress.txt 文件和 git 历史记录来实现。这些做法的灵感来自于了解高效软件工程师每天所做的事情。
环境管理
在更新后的 Claude 4 提示指南 中,我们分享了一些多上下文窗口工作流的最佳实践,包括使用"第一个上下文窗口的不同提示"的控制框架结构。这个"不同的提示"要求初始化智能体使用未来编码智能体有效工作所需的所有必要上下文来设置环境。在这里,我们将深入探讨此类环境的一些关键组件。
功能列表
为了解决智能体一步到位完成应用程序或过早认为项目已完成的问题,我们提示初始化智能体编写一个全面的功能需求文件,扩展用户的初始提示。在 claude.ai 克隆示例中,这意味着超过 200 个功能,例如"用户可以打开新聊天、输入查询、按回车键并看到 AI 响应"。这些功能最初都被标记为"失败",以便后来的编码智能体能够清楚地了解完整功能是什么样的。
{
"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
}
我们提示编码智能体只能通过更改 passes 字段的状态来编辑此文件,并且我们使用措辞强烈的指令,例如"删除或编辑测试是不可接受的,因为这可能导致功能缺失或错误"。经过一些实验,我们决定使用 JSON,因为与 Markdown 文件相比,模型不太可能不当地更改或覆盖 JSON 文件。
增量进展
有了这个初始环境脚手架,编码智能体的下一次迭代被要求一次只处理一个功能。事实证明,这种增量方法对于解决智能体一次做太多事情的倾向至关重要。
一旦开始增量工作,模型在进行代码更改后仍然必须将环境保持在干净状态。在我们的实验中,我们发现引出这种行为的最佳方法是要求模型使用描述性的提交消息将其进度提交到 git,并在进度文件中写入其进度摘要。这允许模型使用 git 回滚错误的代码更改并恢复代码库的工作状态。
这些方法还提高了效率,因为它们消除了智能体猜测发生了什么并花时间试图让基本应用程序再次运行的需要。
测试
我们观察到的最后一个主要失败模式是 Claude 倾向于在没有适当测试的情况下将功能标记为完成。在没有明确提示的情况下,Claude 倾向于进行代码更改,甚至使用单元测试或针对开发服务器的 curl 命令进行测试,但无法识别该功能端到端不起作用。
在构建 Web 应用程序的情况下,一旦明确提示 Claude 使用浏览器自动化工具并像人类用户一样进行所有测试,它在端到端验证功能方面表现得相当不错。

Claude 在测试 claude.ai 克隆时通过 Puppeteer MCP 服务器截取的屏幕截图。
为 Claude 提供这类测试工具显著提高了性能,因为智能体能够识别和修复仅从代码中不明显的错误。
一些问题仍然存在,例如 Claude 的视觉限制和浏览器自动化工具的限制使其难以识别每种类型的错误。例如,Claude 无法通过 Puppeteer MCP 看到浏览器原生的警告模态框,因此依赖这些模态框的功能往往更容易出现错误。
快速上手
有了以上所有准备,每个编码智能体都会被提示执行一系列步骤来确定方向,其中一些非常基本但仍然有帮助:
- 运行
pwd查看你正在工作的目录。你只能编辑此目录中的文件。 - 阅读 git 日志和进度文件,了解最近的工作内容。
- 阅读功能列表文件,选择尚未完成的最高优先级功能进行工作。
这种方法在每个会话中为 Claude 节省了一些令牌,因为它不必弄清楚如何测试代码。要求初始化智能体编写一个可以运行开发服务器的 init.sh 脚本,然后在实现新功能之前运行基本的端到端测试也很有帮助。
在 claude.ai 克隆的情况下,这意味着智能体总是启动本地开发服务器,并使用 Puppeteer MCP 开始新的聊天、发送消息并接收响应。这确保了 Claude 能够快速识别应用程序是否处于损坏状态,并立即修复任何现有的错误。如果智能体转而开始实现新功能,可能会使问题变得更糟。
鉴于以上所有内容,典型的会话以以下助手消息开始:
[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. The core chat features, theme switching, conversation loading, and error handling are all functioning correctly. Now let me review the tests.json file more comprehensively to understand what needs to be implemented next.
<Starts work on a new feature>
智能体失败模式和解决方案。
| 问题 | 初始化智能体行为 | 编码智能体行为 |
|---|---|---|
| Claude 过早宣布整个项目胜利。 | 设置功能列表文件:根据输入规范,设置一个包含端到端功能描述列表的结构化 JSON 文件。 | 在会话开始时读取功能列表文件。选择单个功能开始工作。 |
| Claude 使环境处于存在错误或未记录进度的状态。 | 编写初始 git 仓库和进度记录文件。 | 通过读取进度记录文件和 git 提交日志开始会话,并在开发服务器上运行基本测试以捕获任何未记录的错误。通过编写 git 提交和进度更新结束会话。 |
| Claude 过早地将功能标记为已完成。 | 设置功能列表文件。 | 自我验证所有功能。只有在仔细测试后才将功能标记为"通过"。 |
| Claude 必须花时间弄清楚如何运行应用程序。 | 编写一个可以运行开发服务器的 init.sh 脚本。 |
通过读取 init.sh 开始会话。 |
总结长时间运行 AI 智能体中的四种常见失败模式和解决方案。
未来工作
这项研究展示了长时间运行智能体控制框架中的一组可能解决方案,使模型能够跨多个上下文窗口取得增量进展。然而,仍有一些悬而未决的问题。
最值得注意的是,目前仍不清楚单个通用编码智能体是否在各种上下文中表现最佳,或者是否可以通过多智能体架构实现更好的性能。专门的智能体,如测试智能体、质量保证智能体或代码清理智能体,似乎可以在软件开发生命周期的子任务中做得更好。
此外,此演示针对全栈 Web 应用程序开发进行了优化。未来的方向是将这些发现推广到其他领域。这些经验教训中的部分或全部很可能可以应用于例如科学研究或金融建模中所需的长时间运行智能体任务类型。
致谢
作者: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 能够安全地进行长期自主软件工程,特别是 code RL 和 Claude Code 团队。有兴趣做出贡献的候选人欢迎在 anthropic.com/careers 申请。
脚注
- 我们在此上下文中将它们称为单独的智能体,只是因为它们具有不同的初始用户提示。系统提示、工具集和整体智能体控制框架在其他方面是相同的。