Agent 系统的状态管理困局:为什么「暂停继续」比想象中难

LLM 推理本质上是无状态的,Agent 系统想要实现「暂停后继续」不是保存一个上下文那么简单——从 KV Cache 到 prompt 重建,每一层都有自己的物理约束。

你正在跑一个复杂的 Agent 工作流。

Agent 已经和用户来回聊了十几轮,中间调了三次工具、查了两个数据库、生成了一版方案。这时网络断了,或者服务器需要重启。

你想:没事,把对话历史存起来,等恢复后重新送进去就行。

这个想法对吗?对,也不对。说它对,是因为 Agent 的「记忆」确实就是历史对话。说它不对,是因为LLM 推理不是从零开始重新读一遍历史那么简单。

这背后藏着 Agent 系统中最容易被忽视的瓶颈——状态管理。

物理事实:LLM 天生无状态

先从最底层说起。

每一次 LLM 推理,都是一次独立的计算。你发送一个 prompt 过去,模型做一次前向传播,生成 tokens,返回结果。计算完成,模型内部除了 weights 之外不保留任何东西。

这和 REST API 的设计哲学一模一样:无状态(stateless)。每个请求都是完整的、自包含的。服务器不需要记住上一个请求是什么。

但 Agent 恰恰需要「有状态」——它需要记住用户说了什么、自己做过什么、工具返回了什么。这两者之间的矛盾,就是一切 Agent 状态管理困难的根源。

KV Cache:被低估的「状态载体」

你可能会说:上下文窗口就是状态啊。我保持 prompt 不变,每次追加新的内容不就行了?

对,prompt 是逻辑上的状态。但物理上,真正承载「状态」的是 KV Cache。

当你第一次发送一个长 prompt 时,模型需要计算每一层的 Key 矩阵和 Value 矩阵。这个过程是推理中最昂贵的部分之一——每多一个 token,KV Cache 的大小就增加 2 × num_layers × num_heads × head_dim × precision

一个 7B 模型,单层单头的 KV 维度约 128,共 32 层、32 个 head。每个 token 的 KV Cache 大小大约是:

2 × 32 × 32 × 128 × 2 bytes (fp16) = 524,288 bytes ≈ 0.5 MB/token

一个 4K 的对话,KV Cache 就要 2GB。这不包括模型 weights 本身占的 14GB。

这意味着什么?Agent 的「记忆」是有物理成本的。 每多一轮对话,显存占用就多一分。这就是为什么很多 Agent 框架会在上下文中做截断——不是不想记住,是真的装不下。

「暂停继续」的真实代价

现在回到开头的场景:你要暂停一个 Agent 工作流,之后恢复。

最 naive 的做法:把对话历史存到磁盘,恢复时重新送进去。

但重新送进去意味着什么?重新计算全部 KV Cache。 一个 4K 上下文的预热推理,做一次就需要几秒到十几秒。这对用户体验是致命打击。

更微妙的问题:Agent 不只有对话历史。

假设 Agent 在暂停前调用了工具——查询数据库、调用 API、执行代码。工具的返回结果被纳入了上下文。恢复时,这些工具调用需要重新执行吗?

  • 如果重新执行:工具可能有副作用(比如扣费、发邮件),重复执行就是灾难
  • 如果不重新执行:那你要保存的就不只是对话历史,还有每次工具调用的结果、时间戳、状态

这就是 Agent 状态管理和普通聊天状态管理的本质区别。Agent 的状态不仅包括说了什么,还包括做了什么。

现实中的实践策略

了解了物理约束,再看工程上的解法就清晰了。

策略一:Prefix Caching(通用做法)

把系统 prompt、工具定义等不变的前缀做 KV Cache 预计算,缓存起来。恢复时只需要计算新追加的内容。

代价:额外的一层缓存管理,需要 LRU 淘汰策略。但这是最基础的优化,几乎所有推理框架都支持。

策略二:异步 Checkpoint + 惰性恢复

将 Agent 运行状态(对话历史 + 工具调用结果 + 中间产物)序列化为结构化记录。恢复时先加载轻量元数据,只在需要推理时才重建完整上下文。

这和游戏引擎的 loading screen 策略很像——先让用户能操作,后台再偷偷加载资源。

策略三:事件溯源

借鉴后端的事件溯源模式。Agent 的每次交互(用户消息、工具调用、模型回复)都作为不可变事件存储。恢复时按需回放事件流,而不是全量重建。

好处是审计能力和断点续传,坏处是需要精确记录每个事件的因果依赖。

回到最初的问题:Agent 能「暂停继续」吗?

技术上可以,但代价取决于你对「状态」的定义有多深。只是保存对话历史,用 Prefix Caching 就能做到秒级恢复。但如果你需要 Agent 记住工具调用的中间状态、保持外部系统的上下文一致,那就进入了后端状态管理的经典领域——和分布式系统中的 session 管理、事务恢复面临的是同一类问题。

Agent 的状态管理,本质上是一个「把有状态的业务逻辑跑在无状态的推理引擎上」的问题。理解了这个矛盾,你就理解了为什么所有 Agent 框架在处理长对话时都显得捉襟见肘——不是不够努力,是物理上它本来就很难。

评论

此博客中的热门博文

我写了半年 prompt,最后发现最好的技巧就三个