Anthropic 发布长时运行智能体的高效 harness 研究与实践方法
Effective harnesses for long-running agents
Anthropic 发布研究文章,介绍让 Claude Agent SDK 在多个上下文窗口间持续有效工作的方法,核心是初始化智能体加编码智能体的两部分方案。
Anthropic 以 claude.ai 克隆实验为例,给出跨多个上下文窗口的长时智能体具体做法,开发者可直接迁移到自己的 harness。
随着 AI 智能体能力不断增强,开发者越来越多地要求它们承担需要跨越数小时甚至数天工作的复杂任务。然而,让智能体在多个上下文窗口之间保持一致的进展,仍是一个未解决的问题。
长时间运行的智能体的核心挑战在于,它们必须在离散的会话中工作,而每个新会话开始时都不记得之前发生了什么。想象一个软件项目由轮班工作的工程师组成,每位新工程师到岗时都不记得上一班发生了什么。由于上下文窗口有限,且大多数复杂项目无法在单个窗口内完成,智能体需要一种方式来弥合编码会话之间的空白。
我们开发了一套双管齐下的解决方案,使 Claude Agent SDK 能够在多个上下文窗口之间高效工作:一个初始化智能体在首次运行时搭建环境,以及一个编码智能体,其任务是在每个会话中取得增量进展,同时为下一个会话留下清晰的产物。你可以在随附的快速入门中找到代码示例。
长时间运行的智能体问题
Claude Agent SDK 是一个强大、通用的智能体框架,擅长编码,也擅长其他需要模型使用工具来收集上下文、规划和执行的任务。它具备上下文管理能力,例如压缩(compaction),使智能体能够在不耗尽上下文窗口的情况下处理任务。理论上,有了这套设置,智能体应当能够持续进行有用的工作任意长的时间。
然而,压缩并不足够。开箱即用的情况下,即便是像 Opus 4.5 这样在 Claude Agent SDK 上循环运行于多个上下文窗口的前沿编码模型,如果只给它一个高层级提示,例如“构建一个 claude.ai 的克隆”,也无法构建出生产质量的 Web 应用。
Claude 的失败表现为两种模式。首先,智能体倾向于一次做太多事——本质上试图一次性完成整个应用。这往往导致模型在实现过程中耗尽上下文,使下一个会话开始时某个功能只实现了一半且没有文档记录。智能体随后不得不猜测发生了什么,并花费大量时间试图让基础应用重新运行起来。即使有压缩也会发生这种情况,因为压缩并不总能向下一智能体传递完全清晰的指令。
第二种失败模式往往出现在项目后期。在已经构建了一些功能之后,后来的智能体实例会环顾四周,看到已经取得了进展,便宣布任务完成。
这将问题分解为两部分。首先,我们需要搭建一个初始环境,为给定提示所要求的所有功能奠定基础,从而使智能体能够逐步、逐个功能地工作。其次,我们应当提示每个智能体朝着目标取得增量进展,同时在会话结束时将环境保持在干净状态。所谓“干净状态”,我们指的是适合合并到主分支的那种代码:没有重大缺陷,代码有序且文档完善,总体而言,开发者可以轻松开始开发新功能,而无需先清理无关的烂摊子。
在内部实验中,我们通过一个由两部分组成的方案解决了这些问题:
- 初始化 agent:第一个 agent 会话使用一个专门的提示词,要求模型搭建初始环境:一个
init.sh脚本、一个记录各 agent 已完成工作的 claude-progress.txt 文件,以及一个展示新增了哪些文件的初始 git 提交。 - 编码 agent:后续每个会话都要求模型进行增量式推进,然后留下结构化的更新。1
这里的关键洞见在于,找到一种方法让 agent 在全新的上下文窗口中启动时能快速理解工作状态,这通过 claude-progress.txt 文件配合 git 历史来实现。这些做法的灵感来自了解高效的软件工程师每天在做什么。
环境管理
在更新后的 Claude 4 提示指南中,我们分享了一些多上下文窗口工作流的最佳实践,包括一种使用“为第一个上下文窗口准备不同提示词”的 harness 结构。这个“不同的提示词”要求初始化 agent 搭建环境,并包含未来编码 agent 高效工作所需的全部必要上下文。在此,我们深入探讨此类环境的一些关键组成部分。
功能列表
为了解决 agent 一次性完成整个应用或过早认为项目已完成的问题,我们提示初始化 agent 编写一份全面的功能需求文件,对用户的初始提示词进行扩展。在 claude.ai 克隆示例中,这意味着超过 200 项功能,例如“用户可以打开新对话、输入查询、按回车,并看到 AI 回复”。这些功能最初全部标记为“失败”,以便后续编码 agent 能清楚了解完整功能应是什么样子。
我们提示编码 agent 只能通过更改 passes 字段的状态来编辑此文件,并使用措辞强硬的指令,例如“删除或修改测试是不可接受的,因为这可能导致功能缺失或出现缺陷”。经过一些实验,我们最终选择使用 JSON,因为与 Markdown 文件相比,模型不太可能不恰当地更改或覆盖 JSON 文件。
增量推进
有了这样的初始环境脚手架,下一轮编码 agent 被要求一次只处理一个功能。这种增量式方法最终被证明对于解决 agent 一次做太多事的倾向至关重要。
在实现增量推进后,模型在做出代码更改后让环境保持干净状态仍然至关重要。在实验中,我们发现引导这种行为的最佳方式是要求模型用描述性的提交信息将进度提交到 git,并在进度文件中写下进度摘要。这让模型能够使用 git 回退糟糕的代码更改,并恢复代码库的可工作状态。
这些方法还提高了效率,因为它们消除了 agent 不得不猜测发生了什么、并花时间试图让基础应用重新运行的需要。
测试
我们观察到的最后一个主要失败模式是 Claude 倾向于在没有适当测试的情况下将功能标记为完成。在缺乏明确提示的情况下,Claude 往往会进行代码更改,甚至针对开发服务器用单元测试或 curl 命令进行测试,但无法认识到该功能并未端到端正常工作。
在构建 Web 应用的情况下,一旦明确提示使用浏览器自动化工具并像人类用户那样进行所有测试,Claude 大多能很好地端到端验证功能。

Claude 在测试 claude.ai 克隆版时通过 Puppeteer MCP 服务器拍摄的截图。
为 Claude 提供这类测试工具显著提升了性能,因为该智能体能够识别并修复仅凭代码无法发现的缺陷。
仍存在一些问题,例如 Claude 的视觉能力和浏览器自动化工具的限制,使得难以识别每一种缺陷。例如,Claude 无法通过 Puppeteer MCP 看到浏览器原生的警告模态框,因此依赖这些模态框的功能往往更容易出现缺陷。
快速上手
在以上各项就位后,每个编码智能体都会被提示执行一系列步骤来熟悉情况,其中一些相当基础但仍然有用:
- 运行
pwd查看你当前工作的目录。你只能编辑此目录中的文件。 - 阅读 git 日志和进度文件,了解最近的工作内容。
- 阅读功能列表文件,选择尚未完成的最高优先级功能来处理。
这种方法在每个会话中为 Claude 节省了一些 token,因为它不必弄清楚如何测试代码。同时,要求初始化智能体编写一个 init.sh 脚本也很有帮助,该脚本可以运行开发服务器,然后在实现新功能之前运行一次基本的端到端测试。
在 claude.ai 克隆版的情况下,这意味着该智能体总是先启动本地开发服务器,并使用 Puppeteer MCP 启动新聊天、发送消息并接收响应。这确保了 Claude 能够快速识别应用是否处于损坏状态,并立即修复任何现有缺陷。如果该智能体转而开始实现新功能,则很可能使问题变得更糟。
鉴于以上所有情况,一个典型的会话以以下助手消息开始:
总结长时间运行的 AI 智能体中四种常见失败模式及解决方案。
未来工作
这项研究展示了一组可能的解决方案,用于长时间运行的智能体框架,使模型能够在多个上下文窗口中取得渐进式进展。然而,仍存在一些未解决的问题。
最值得注意的是,目前仍不清楚是单个通用编码智能体在各种情境下表现最佳,还是通过多智能体架构可以获得更好的性能。似乎合理的是,像测试智能体、质量保证智能体或代码清理智能体这样的专用智能体,可以在软件开发生命周期的各个子任务上做得更好。
此外,此演示针对全栈 Web 应用开发进行了优化。未来的一个方向是将这些发现推广到其他领域。这些经验中的部分或全部很可能可以应用于例如科学研究或金融建模中所需的那类长时间运行的智能体任务。
来源:Anthropic:Newsroom · anthropic.com