获取开发者简报
产品更新、操作指南、社区聚焦等更多内容。每月发送至您的收件箱。
随着 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 的视觉限制和浏览器自动化工具的限制,使得难以识别每一种错误。例如,Claude 无法通过 Puppeteer MCP 看到浏览器原生的警告模态框,因此依赖这些模态框的功能往往更容易出现缺陷。
有了上述所有措施,每个编码代理都会被提示运行一系列步骤来了解情况,其中一些非常基础但仍然有帮助:
pwd
以查看您正在工作的目录。您只能编辑此目录中的文件。这种方法在每个会话中为 Claude 节省了一些 token,因为它不必弄清楚如何测试代码。它还有助于要求初始化代理编写一个 init.sh 脚本,该脚本可以运行开发服务器,然后在实现新功能之前运行基本的端到端测试。
在 claude.ai 克隆的情况下,这意味着代理总是启动本地开发服务器,并使用 Puppeteer MCP 启动新聊天、发送消息并接收响应。这确保了 Claude 能够快速识别应用是否处于损坏状态,并立即修复任何现有错误。如果代理反而开始实现新功能,则可能会使问题变得更糟。
鉴于所有这些,典型的会话以以下助手消息开始:
[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 使环境处于存在缺陷或进度未记录的状态。 | 写入初始 git 仓库和进度笔记文件。 | 通过读取进度笔记文件和 git 提交日志开始会话,并在开发服务器上运行基本测试以捕获任何未记录的缺陷。通过写入 git 提交和进度更新来结束会话。 |
| Claude 过早将功能标记为完成。 | 设置一个功能列表文件。 | 自行验证所有功能。只有在仔细测试后才将功能标记为“通过”。 |
| Claude 不得不花时间弄清楚如何运行应用。 | 编写一个可以运行开发服务器的 init.sh 脚本。 |
通过读取 init.sh 开始会话。 |
这项研究展示了一组可能的解决方案,用于长期运行的 agent harness,使模型能够在多个上下文窗口中逐步取得进展。然而,仍存在未解决的问题。
最值得注意的是,目前仍不清楚是单个通用编码 Agent 在各种情境下表现最佳,还是通过多 Agent 架构可以实现更好的性能。像测试 Agent、质量保证 Agent 或代码清理 Agent 这样的专用 Agent,似乎有可能在软件开发生命周期的各个子任务上做得更好,这似乎是合理的。
此外,此演示针对全栈 Web 应用开发进行了优化。未来的一个方向是将这些发现推广到其他领域。这些经验中的部分或全部很可能可以应用于例如科学研究或金融建模中所需的那种长期运行的 agentic 任务。
作者: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 申请。
- 在此上下文中,我们之所以称它们为单独的 Agent,仅是因为它们有不同的初始用户提示。系统提示、工具集和整体 agent harness 在其他方面完全相同。
产品更新、操作指南、社区聚焦等。每月发送到您的收件箱。
