大数跨境

Anthropic:如何构建常驻 Agent

Anthropic:如何构建常驻 Agent AINLP
2026-11-14
0
导读:不必一直醒着

Anthropic 的 William Hu 写了一份常驻 Agent 工程指南,从事件收件箱、定时器、记忆、权限和发件箱五个组件,解释 Agent 如何跨会话持续工作。以下是全文翻译。


常驻 Agent 可以持续运行,自行决定何时以及如何行动,并跨越多个会话。这份指南介绍它们的核心基础组件,以及这些组件如何配合。

过去几个月,我们看到常驻 Agent 再度兴起。

常驻 Agent 具有状态,也会主动行动:它们在不同会话之间管理上下文,并在没有直接监督的情况下采取行动。底层仍然是其他 Agent 也在使用的那套核心循环。不同之处在于外围架构:一组基础组件决定 Agent 何时醒来、哪些信息会延续到下一轮运行,以及工作成果如何送达用户。

这次回潮,很大程度上得益于近期模型能力的进步,让常驻 Agent 更适合投入实际运行。首先,新模型的判断力更好了,更能准确理解用户意图,也更清楚何时该向用户确认。其次,智能正变得更便宜,长时程任务受益尤其明显。例如,在一项长时程编码基准上,Opus 5.5 每成功解决一个任务的成本,比 Opus 5 降低了 78%;而在一般工作负载上,降幅为 40%。

客户开始询问,怎样把这种体验融入自己的产品。有些公司希望现有 Agent 变得更主动,另一些则想从头构建。

本文将拆解常驻 Agent 背后的基础组件,并说明它们如何配合。

常驻 Agent 背后的运行循环

常驻 Agent 并不是真的“一直在线”。这个说法描述的是用户体验。

实际上,Agent 大部分时间都在休眠,只会定期醒来工作。每一段工作称为一轮运行(run):Agent 收到一个事件,完成任务,然后保存这次发生的事情。一轮运行发生在一个会话(session)中,会话记录着消息和工具调用。运行结束后,Agent 再次休眠,这个循环可以一直持续下去。

常驻 Agent 的运行周期

常驻 Agent 的运行周期

核心基础组件

常驻 Agent 的外围架构有五个核心基础组件:事件收件箱、定时器、记忆、权限和发件箱。下面逐一来看。

事件收件箱

大多数 AI Agent 只有在用户发来消息时才运行。常驻 Agent 则可以由多种事件触发,包括 webhook、定时任务和后台作业。

一种很容易想到的做法,是让每个事件源直接调用 Agent,但这会带来几类故障。例如,同时到达的两个事件,可能启动互相竞争的运行;一次崩溃,也可能让某个事件彻底丢失。

事件收件箱(event inbox)就是为此而设。各个事件源不直接调用 Agent,而是把事件送入收件箱,再由工作进程(worker)取出处理。

最简单的实现包含三个部分:

  • 持久保存的事件列表,通常是一张数据库表;
  • 把事件写入列表的处理器(handler),通常是一个 HTTP 端点;
  • 从列表中读取事件的工作进程,通常是一个后台服务。

收件箱应跟踪每个事件的状态,并可根据事件源提供的唯一标识去重。关系型数据库很适合承担这项工作,每个事件都作为一条新记录追加。我们建议先为每个用户建立一个收件箱;如果需要更高的并行度,也可以进一步拆分。

事件收件箱与工作进程

事件收件箱与工作进程

新事件到达时,处理器将其写入收件箱,并唤醒工作进程。工作进程读取待处理事件,启动一轮运行。如果事件是在延续之前的工作,比如用户的一条回复,就恢复已有会话;其他事件则开启新会话。

接着,工作进程把事件交给 Agent 循环,等待运行结束,再将相应事件标记为已完成。实现细节可能比较棘手,下面是一些最佳实践:

  • 处理器应尽快确认收到事件。一些事件源,比如 webhook 提供方,会把响应缓慢视为失败。处理器可以做轻量检查,但更深入的验证,例如检查提示词注入,应在运行过程中完成。
  • 以收件箱作为权威状态源。工作进程被唤醒时,应先从收件箱拉取最新事件。这样,即使它在运行中途退出,新的工作进程也能取出同一个事件重试。
  • 同一个收件箱在同一时刻只能有一个活跃的工作进程,避免两轮运行重复劳动或互相覆盖。如果运行中途又来了新事件,可以留到下一轮处理,也可以并入当前运行,或者中断后重新开始。
  • 工作进程应批量处理待办事件。例如,用户连续发送多条消息时,可以合并成一轮运行,让 Agent 只回复一次。

定时器

定时器与事件收件箱配合,让常驻 Agent 能够主动行动。定时器通常分为两类:后续跟进和周期任务。后续跟进是 Agent 为自己设定的一个时间点,例如到时检查是否收到回复。周期任务则按已知频率重复执行,例如每日简报。

定时器应有自己独立的持久存储,通常是另一张数据库表,与收件箱分开。收件箱只保存已经可以开始处理的事件。后续跟进和周期任务可以采用相似的数据结构,但周期任务还需要记录重复执行的规则。

定时器与调度器

定时器与调度器

定时器本身不会启动运行。调度器通常是一个后台服务,按固定间隔轮询存储,触发到期的定时器。每次轮询时,调度器会:

  1. 扫描存储,找出已到期的定时器。
  2. 按类别更新定时器:后续跟进应标记为已完成;周期任务则应将到期时间更新为下一次执行的时间。
  3. 向收件箱添加一个事件,并唤醒工作进程。

调度器可以自行开发,也可以使用持久化执行引擎。

记忆

常驻 Agent 的工作分散在许多彼此独立的运行中,需要依靠记忆维持连续性。

与事件收件箱和定时器一样,记忆也应有自己的存储。在 Claude Code 的自动记忆和 Messages API 的记忆工具等产品中,我们用一个文件目录来实现它。对于常驻 Agent,这些目录应映射到持久存储,通常是数据库或对象存储。这样,即使工作进程结束,记忆也能保留下来。

一个基本原则是,记忆只保存 Agent 无法再次查到的信息。如果信息已经存在于另一个系统中,比如问题跟踪系统,就应保存指向它的引用。常驻 Agent 应保存以下几类记忆:

  • 用户指令:用户对 Agent 行为提出的要求,应单独保存为文件,并在每轮运行开始时加载。用户不一定始终在场指导,因此这些要求必须能延续到后续运行。
  • 用户笔记:Agent 应保存自己对用户的了解,例如用户的职责、偏好,以及用户给过的纠正。起初可以只用一个文件,随着笔记增多,再拆成若干小文件。拆分后,每轮运行开始时只加载索引,需要更多细节时,再把相应文件读入上下文。
  • 历史消息:Agent 应记住已经告诉过用户什么,避免重复。可以把这些信息存成单独文件,在每轮运行开始时加载;也可以由工作进程加载 Agent 最近与用户交流的几条消息。
  • 任务进度:为每项进行中的任务维护一份进度文件,记录已经完成什么、还剩什么。新的运行读取这份文件,就能接着上一轮的工作继续。与用户笔记一样,每轮运行开始时只加载索引,需要更多细节时再读取相应文件。

下图展示了一种配置示例。

记忆文件的组织方式

记忆文件的组织方式

以上都是在运行过程中保存的记忆。也可以加入 dreaming,通过回顾过去的会话来整理记忆。Dreaming 可以替换过时条目,并发现只有跨越多轮运行才能看出的规律。如果想进一步了解,我们关于 Agent 记忆的文章对此有更详细的介绍。

上下文窗口内部

开始工作前,Agent 会加载系统提示词、工具定义和记忆文件。每轮运行都要承担这部分初始上下文“开销”,因此我们建议尽量保持精简,并使用提示词缓存来降低成本。

新会话开始时,上下文只包含这些初始内容,以及触发本轮运行的事件。已有会话则会带回之前各轮运行中的消息和工具调用。

如果会话过长,可以压缩较早的消息,或开启新会话。两种方法都会丢失细节,因此需要长期保留的信息,应在工作过程中及时写入记忆。

会话延续与上下文压缩

会话延续与上下文压缩

权限

权限是常驻 Agent 风险最大的地方。每轮运行都持有用户的访问权限,而且按设计是在无人值守的情况下工作。对于每次工具调用,Agent 都要决定是自行执行、阻止,还是等待批准。

权限所需的组件,与其他 Agent 相同:

  • 凭据存储:常驻 Agent 要发挥作用,往往需要用户的密码或访问令牌等敏感凭据。推荐的做法,是在 Agent 环境之外设置一个代理,为发出的请求添加凭据。Agent 发出不带凭据的请求,由代理注入真实凭据后转发。
  • 自动模式:常驻 Agent 应能在不需要用户持续输入的情况下工作。我们已经在 Claude Code 的自动模式中处理过这类问题。自动模式使用分类器审查风险较高的操作,拦截被识别为危险的操作,让 Claude 寻找更安全的做法。不过,最重要的决策仍然需要用户审阅。
  • 延后工具调用:在 Claude Code 中,hook 可以延后一次工具调用,等待用户补充信息。常驻 Agent 也适用这种模式,因为它们在执行某些操作前,可能需要澄清或批准。调用被延后时,本轮运行结束,会话保存在工具调用进行到一半的位置。请求会展示给用户,例如通过 MCP Apps 构建的交互卡片;用户的回答则作为一个事件返回收件箱。这个事件触发新一轮运行,带着用户输入恢复已保存的会话。在等待回复期间,工作进程可以处理其他事件,因此不会阻塞 Agent 处理其他事情。

发件箱

大多数 AI Agent 会一边生成回答,一边将其流式传给用户,让用户跟随 Claude 的思考、工具调用和作答过程。

常驻 Agent 则把大部分工作放在后台完成。用户收到的是结果和少量细节,而不是完整的逐步过程。

发件箱与消息分发

发件箱与消息分发

一轮运行可以有三种结束方式:

  • Agent 向发件箱发送一条消息;
  • Agent 判断没有任何内容需要发送;
  • Agent 通过延后的工具调用,请求用户批准或补充信息。

大多数常驻 Agent 只需一个直接向用户送达消息的“send”工具。只有在需要控制消息发送节奏,或让 Agent 从错误中恢复时,才需要正式的发件箱。

发件箱(outbox)是一张独立的待发消息表,与事件收件箱相对应。它还有一个分发器(dispatcher),通常是后台服务,对应收件箱一侧的工作进程。分发器读取待发送消息,决定哪些需要送达,再将其发给用户。延后工具调用产生的请求,可以经由发件箱发送,也可以直接展示在产品界面中。

除了送达机制,Agent 发送多少消息也需要调整。发得太多会成为噪声,发得太少又会漏掉用户需要知道的事情。我们建议通过评测找到合适的平衡。实际使用中,最好让 Agent 一开始安静一点,再逐步赢得用户更多的注意力。

这些组件如何配合

五个基础组件的配合方式如下:

五个基础组件如何配合

五个基础组件如何配合

每轮运行都从收件箱中的一个事件开始,无论它来自用户消息、webhook,还是定时器。工作进程取出事件后,启动一轮运行,在新会话或已有会话中唤醒 Agent。Agent 先读取记忆以了解基本情况,再在权限范围内采取行动,最后把新学到的信息写回记忆。运行结束后,Agent 向发件箱写入一条记录,由分发器将消息送达用户。

这些环节构成了一个循环。一次运行可以设置定时器,让 Agent 稍后再次醒来;用户回复消息时,回答又会作为事件回到收件箱。每轮运行都很短,但循环可以一直持续,这就是 Agent 看起来始终在线的原因。

致谢

本文由 William Hu 撰写。特别感谢 Rodrigo Olivares 和 Michael Segner 的贡献。

参考链接

  • 原文:https://claude.com/resources/articles/building-always-on-agents
  • 构建高效 Agent:https://www.anthropic.com/research/building-effective-agents
  • 成本与智能优化:https://platform.claude.com/docs/en/about-claude/models/optimizing-for-cost-and-intelligence
  • Claude Code 自动记忆:https://code.claude.com/docs/en/memory
  • Messages API 记忆工具:https://platform.claude.com/docs/en/agents-and-tools/tool-use/memory-tool
  • Agent 记忆组件:https://www.anthropic.com/research/components-of-agent-memory
  • 提示词缓存:https://platform.claude.com/docs/en/build-with-claude/prompt-caching
  • 上下文压缩:https://platform.claude.com/docs/en/build-with-claude/compaction
  • 安全部署中的凭据代理:https://code.claude.com/docs/en/agent-sdk/secure-deployment
  • Claude Code 自动模式:https://www.anthropic.com/research/claude-code-auto-mode
  • Claude Code hooks:https://code.claude.com/docs/en/hooks
  • MCP Apps:https://modelcontextprotocol.io/extensions/apps/overview

【声明】内容源于网络
0
0
AINLP
一个有趣有AI的自然语言处理公众号:关注AI、NLP、大模型LLM、机器学习、推荐系统、计算广告等相关技术。公众号可直接对话双语聊天机器人,尝试对对联、作诗机、藏头诗生成器、自动写作等,查询相似词,测试NLP相关工具包。
内容 6123
粉丝 0
AINLP 一个有趣有AI的自然语言处理公众号:关注AI、NLP、大模型LLM、机器学习、推荐系统、计算广告等相关技术。公众号可直接对话双语聊天机器人,尝试对对联、作诗机、藏头诗生成器、自动写作等,查询相似词,测试NLP相关工具包。
总阅读40.6k
粉丝0
内容6.1k