Anthropic 详解 Always-on Agent 架构与五大核心原语
Building always-on agents | Claude by Anthropic
Agent 工程师必读,Anthropic 给出了常驻智能体的完整架构原语与落地细节,直接指导如何设计高可用系统。
Over the past few months, we’ve seen a resurgence of always-on agents.
在过去几个月里,我们看到了常驻智能体(always-on agents)的复兴。
Always-on agents are stateful and proactive, meaning they manage context across sessions and take actions without direct supervision. Underneath, they run on the same core loop as other agents. The difference is the surrounding architecture, which is built from primitives that control when the agents wake up, what carries over between runs, and how their work reaches the user.
常驻智能体是有状态的且具备主动性,这意味着它们能够跨会话管理上下文,并在无需直接监督的情况下采取行动。在底层,它们与其他智能体运行在相同的核心循环之上。区别在于周围的架构,该架构由控制智能体何时唤醒、哪些信息在运行之间保留以及如何将工作结果呈现给用户的原语构建而成。
The resurgence is largely due to recent model advancements, which have made always-on agents more practical to run. First, the latest models have better judgment: they’re more reliable at understanding user intent and knowing when to check in. Second, intelligence is becoming cheaper, with long-horizon tasks benefiting the most. For example, on one long-horizon coding benchmark, Opus 5.5 cost 78% less per solved task than Opus 5, compared with 40% less on typical workloads.
这一复兴主要得益于近期模型技术的进步,使得常驻智能体的运行更加实用。首先,最新模型具备更好的判断力:它们在理解用户意图以及知道何时进行检查方面更加可靠。其次,智能成本正在降低,长周期任务从中受益最多。例如,在一个长周期编码基准测试中,Opus 5.5 解决每个任务的成本比 Opus 5 降低了 78%,而在典型工作负载下仅降低了 40%。
Customers have started to ask us how to integrate this type of experience into their own products. Some companies want to make their existing agents more proactive, while others are looking to build them from the ground up.
客户开始询问我们如何将此类体验集成到他们自己的产品中。一些公司希望使其现有的智能体更具主动性,而另一些公司则希望从头构建这类智能体。
This post breaks down the primitives behind always-on agents and walks through how they fit together.
本文将拆解常驻智能体背后的原语,并阐述它们如何协同工作。
The cycle behind the always-on agent
常驻智能体背后的循环机制
An always-on agent is not actually “always on.” This is just a description of the user experience.
常驻智能体实际上并非“始终在线”。这仅仅是对用户体验的描述。
In reality, the agent spends most of its time asleep, waking up periodically to do work. Each stretch of work is called a run: the agent receives an event, completes its task, and then saves information about what happened. A run works inside a session, which is the transcript of messages and tool calls. Once the run is finished, the agent goes back to sleep, and the cycle repeats indefinitely.
实际上,智能体大部分时间处于休眠状态,定期醒来执行工作。每一段工作时间被称为一次运行(run):智能体接收一个事件,完成任务,然后保存关于所发生情况的信息。一次运行在一个会话(session)内进行,会话是消息和工具调用的记录。一旦运行结束,智能体便回到休眠状态,如此循环往复。
The core primitives
核心原语
The surrounding architecture of an always-on agent has five core primitives: an event inbox, timers, memory, permissions, and an outbox. Let’s take a look at each.
常驻智能体的周围架构包含五个核心原语:事件收件箱(event inbox)、定时器(timers)、记忆(memory)、权限(permissions)和发件箱(outbox)。让我们逐一查看。
Event inbox
事件收件箱
Most AI agents only run when the user sends a message. In contrast, always-on agents can be triggered by many types of events, including webhooks, scheduled tasks, and background jobs.
大多数 AI 智能体仅在用户发送消息时运行。相比之下,常驻智能体可以由多种类型的事件触发,包括 Webhook、定时任务和后台作业。
One tempting approach is to have each event source call the agent directly, but that has a few failure modes. For example, two events arriving at the same time can start competing runs, and a crash can lose an event entirely.
一种诱人的方法是为每个事件源直接调用智能体,但这存在几种故障模式。例如,同时到达的两个事件可能启动竞争性的运行,而崩溃可能导致整个事件丢失。
This is where the event inbox comes in. Instead of calling the agent, every source sends an event to an inbox, where a worker picks it up.
这就是事件收件箱发挥作用的地方。与其调用代理,每个来源都会向一个收件箱发送事件,由工作进程从中拾取。
The simplest version has three components:
最简单的版本包含三个组件:
- A durable list of events, usually a database table;
- A handler, usually an HTTP endpoint, that writes events to the list; and
- A worker, usually a background service, that reads from the list.
- 一个持久的事件列表,通常是一个数据库表;
- 一个处理器,通常是一个 HTTP 端点,用于将事件写入列表;以及
- 一个工作进程,通常是一个后台服务,用于从列表中读取数据。
The inbox should track the status of each event, and events can be deduplicated based on unique identifiers from the source. A relational database works well for the inbox, with every event appended as a new row. We recommend starting with one inbox per user, but you can split this further if you need more parallelism.
收件箱应跟踪每个事件的状态,并且可以根据来源的唯一标识符对事件进行去重。关系型数据库非常适合用作收件箱,每个事件都作为新行追加。我们建议每个用户使用一个收件箱开始,但如果需要更高的并行度,可以进一步拆分。
When a new event comes in, the handler writes the event to the inbox and wakes the worker. The worker reads whatever is pending and starts a run. Events that continue earlier work, such as a reply from the user, resume an existing session, while everything else starts a new session.
当新事件进入时,处理器将事件写入收件箱并唤醒工作进程。工作进程读取所有待处理的事件并开始运行。延续之前工作的事件(例如用户的回复)会恢复现有会话,而其他所有内容则启动新会话。
From there, the worker passes the events to the agent loop, waits for the run to finish, and marks the corresponding events as done. The implementation details can get tricky, so here are a few best practices:
此后,工作进程将事件传递给代理循环,等待运行结束,并将相应的事件标记为已完成。实现细节可能很棘手,因此这里有一些最佳实践:
- The handler should acknowledge events quickly. Some sources, such as webhook providers, treat slow responses as failures. The handler can still run lightweight checks, but any deeper verification, such as checking for prompt injection, should be done during the run.
- The inbox should be the source of truth. When the worker is woken up, it should pull the latest events from the inbox first. That way, if the worker dies mid-run, a new one can pick up the same event and retry.
- An inbox should only have one active worker at a time. This prevents two runs from duplicating work or overwriting each other. When a new event shows up mid-run, you can either push it to the next run, fold it into the current run, or interrupt and restart.
- The worker should batch pending events together. For example, if the user sends several messages in a row, the worker can merge them into a single run, so the agent only needs to reply once.
- 处理器应快速确认事件。某些来源(如 webhook 提供商)会将缓慢的响应视为失败。处理器仍可以运行轻量级检查,但任何更深入的验证(例如检查提示注入)应在运行期间完成。
- 收件箱应是唯一事实来源。当工作进程被唤醒时,它应首先从收件箱拉取最新的事件。这样,如果工作进程在运行中途死亡,新的工作进程可以拾取相同的事件并重试。
- 收件箱一次只能有一个活跃的工作进程。这防止了两次运行重复工作或相互覆盖。当新事件在运行中途出现时,你可以将其推送到下一次运行、合并到当前运行中,或中断并重新启动。
- 工作进程应将待处理的事件批量处理。例如,如果用户连续发送多条消息,工作进程可以将它们合并为单次运行,这样代理只需回复一次。
Timers
定时器
Together with the event inbox, timers let always-on agents be proactive. Timers generally fall into one of two categories: follow-ups or schedules. A follow-up is a deadline that the agent sets for itself, such as checking in on a reply. A schedule, on the other hand, is a recurring task that happens on a known cadence, such as a daily newsletter.
结合事件收件箱,定时器使始终在线的代理能够主动行动。定时器通常分为两类:跟进或计划。跟进是代理为自己设定的截止时间,例如检查回复情况。另一方面,计划是在已知频率下发生的重复任务,例如每日新闻通讯。
Timers live in their own durable store, usually another database table, separate from the inbox. The inbox should only hold events that are ready to be worked on. A follow-up and a schedule can share a similar schema, but a schedule needs to track its recurrence as well.
计时器存在于其自身的持久化存储中,通常是另一个数据库表,与收件箱分开。收件箱应仅保存准备好处理的事件。跟进和计划可以共享类似的架构,但计划还需要跟踪其重复性。
A timer doesn’t initiate a run on its own. Instead, a scheduler, usually a background service, polls the store at a fixed interval and fires anything that’s due. On each pass, the scheduler:
计时器不会自行启动运行。相反,调度程序(通常是一个后台服务)会以固定间隔轮询存储,并触发任何到期的任务。在每次遍历中,调度程序会执行以下操作:
- Scans the store and finds timers that are due.
- Updates each timer based on its category.
- A follow-up should be marked as done.
- A schedule should get its due time updated to the next occurrence.
- Adds an event to the inbox and wakes the worker.
- 扫描存储并查找已到期的计时器。
- 根据其类别更新每个计时器。
- 跟进应标记为已完成。
- 计划应将其到期时间更新为下一次出现的时间。
- 向收件箱添加事件并唤醒工作进程。
For the scheduler, you can either build your own service or use a durable execution engine.
对于调度程序,你可以构建自己的服务或使用持久化执行引擎。
Memory
内存
Always-on agents work across many disjointed runs and rely on memory to maintain continuity.
常驻代理跨多个不连续的运行工作,并依赖内存来保持连续性。
Similar to the event inbox and timers, memory should have its own store. In our products, such as Claude Code’s auto memory and the Messages API’s memory tool, this is implemented as a directory of files. For an always-on agent, the directories should map to durable storage, usually a database or an object store. This way memories outlive the worker.
类似于事件收件箱和计时器,内存也应该有自己的存储。在我们的产品中,例如 Claude Code 的自动记忆功能和 Messages API 的记忆工具,这是以文件目录的形式实现的。对于常驻代理,这些目录应映射到持久化存储,通常是数据库或对象存储。这样记忆就能超越工作进程的生命周期。
As a rule of thumb, memory should only hold what the agent can’t look up again. If something already lives in another system, such as an issue tracker, you should save a pointer instead. Here is a breakdown of the types of memory an always-on agent should store:
作为经验法则,内存只应保存代理无法再次查询的内容。如果某事物已经存在于其他系统中,例如问题追踪器,你应该保存一个指针。以下是常驻代理应存储的内存类型分解:
- User instructions: Any instructions from the user about agent behavior should be saved in their own file and loaded at the start of every run. The user won’t always be around to steer the agent, so the instructions have to carry over between runs.
- User notes: The agent should save what it’s learned about the user, such as their role, their preferences, or any corrections they’ve given. You can start with one file and move to several small files as the notes grow. In the latter case, only an index is loaded at the start of each run, but the agent can pull the individual files into context when it needs more details.
- Past messages: The agent should keep track of what it’s already told the user so nothing is repeated. It can either store this in a separate file that’s loaded at the start of each run, or have the worker load the agent’s last few messages with the user.
- Task progress: For each ongoing task, the agent should keep a progress file that covers what’s been done and what’s left. Any new run can then read that file and pick up where the previous run left off. Similar to user notes, only an index is loaded at the start of each run, but the agent can pull the individual files into context when it needs more details.
- 用户指令:关于代理行为的任何用户指令都应保存在其自己的文件中,并在每次运行时加载。用户并不总是随时在场来指导代理,因此指令必须在运行之间延续。
- 用户笔记:代理应保存它关于用户的所学内容,例如其角色、偏好或他们给出的任何纠正。你可以从单个文件开始,随着笔记的增加迁移到多个小文件。在后一种情况下,仅在每次运行时加载索引,但当需要更多细节时,代理可以将各个文件拉入上下文。
- 历史消息:代理应跟踪它已经告诉用户的内容,以避免重复。它可以将这些内容存储在每次运行时加载的单独文件中,或者让工作进程加载代理与用户的最后几条消息。
- 任务进度:对于每个进行中的任务,代理应维护一个进度文件,涵盖已完成和未完成的工作。任何新的运行都可以读取该文件,并从上次运行的中断处继续。类似于用户笔记,每次运行时仅加载索引,但当代理需要更多详细信息时,可以将各个文件拉入上下文。
The diagram below shows one example setup.
下图展示了一个示例设置。
更进一步:量化金融体系
看懂新闻只是起点——沿量化金融路径,把它变成能交付的工程能力