让Agent跑十几个小时不崩:记忆外化与跨Session状态继承的实战思考

April 12, 2026

blog-cover-poster.png 本周Anthropic发了篇工程博客 Managed Agents,副标题叫"Decoupling the brain from the hands"——把脑和手解耦,架构层面聊了很多,但我最感兴趣的还是:它怎么处理跨 session 的上下文。

正好我自己在DeepResearch-Agent 里刚补充做了类似的东西——跨会话的云端文件状态恢复和记忆压缩,踩了不少坑,有些感受可以拿出来唠一唠。


一、Managed Agents 这篇文章到底在说什么

先快速过一遍核心架构,不展开讲"脑手分离"那些(那部分更偏运维和基础设施),聚焦在上下文管理上。

Anthropic 把 agent 拆成三个独立抽象:

  • Session:一份 append-only 的事件流,持久化在外部,不依赖任何容器的生死
  • Harness(脑):无状态的循环,崩了就用 wake(sessionId) 从事件流里恢复
  • Sandbox(手):纯粹的执行环境,用完即弃

Session-Harness-Sandbox

其中 session 的定位最有意思。博文里有一句话点明了一切:

The session is not Claude's context window.

也就是说,session 是一个独立于上下文窗口的、可查询的外部状态对象。harness 通过 getEvents() 从 session 中按需拉取事件切片,做变换后再注入 Claude 的上下文。上下文窗口只放"此刻需要的",完整历史始终留在外面。

这解决了长程任务最头疼的矛盾——上下文有限但任务无限。传统做法是摘要、裁剪、压缩,但这些操作都不可逆,你砍掉的 token 未来可能恰恰是关键的。Managed Agents 的策略是:别急着丢,先全量存,用的时候再选择性地拿。


二、我的做法:更粗暴但够用

我在 DeepResearch-Agent 里也做了跨轮次状态恢复(特别是多轮对话间的沙箱文件状态),但选了一个更朴素的路线:不存事件流,只存文件。

原理很简单:

    1. 每轮对话结束,扫描沙箱里所有新增/修改的文件,上传到 OSS进行对象存储
    1. 多轮对话时,把多轮涉及的全量的 {文件(含文件路径): OSS地址} 这个映射表攒起来,跨轮次累积
    1. 下一轮开始时,后端创建全新沙箱,把这些文件 curl 回原始路径,模拟出一个和上轮结束后文件状态一致的沙箱

考虑每轮新建沙箱,而不是维持原沙箱的初衷是:我们不知道用户何时开启下一轮对话,中间可能隔了几十个小时甚至数天,我们为用户维持原沙箱的持续运行时的成本太大,不如每一轮结束后kill原沙箱,等到用户续问的时候,再重建全新沙箱;

e2b也做了类似的沙箱快照的功能e2b沙箱快照.png

    1. 额外的,多轮对话时,系统提示词里还append注入了:多轮涉及的文件清单让模型感知到前序工作的交付结果 + 多轮对话压缩说明 ;模型开局先 cat TODO.md,立刻知道之前做到哪了

这等于做了一次极其激进的信息蒸馏:几十甚至上百万 token 的对话历史——中间的搜索结果、工具调用、思考过程——全部扔掉,只留下:每轮的最后的总结那部分的final_answer+文件清单。

为什么敢这么做?因为对研究类任务来说,结果远比过程重要。你不需要回忆"第3轮第17次搜索返回了什么",你只需要打开 research/market_analysis.md 看结论就够了。推理过程是脚手架,建完就可以拆。

TODO.md 在这个体系里充当"状态机入口"。它不只是个待办清单,它是整个多轮对话的握手协议——新轮次的模型读完它,就完成了和上一轮对话任务的"交接班"。

实际跑下来,单轮 15-30 分钟,串 10-20 轮,就是好几个小时的持续工作。绝大部分运行时的上下文窗口只需要用于承载当前轮的负载,上下文空间运行压力暴减。


三、两种方案的对比

拉到一起看,两个方案解决的是同一个问题,但选择了不同的粒度:

Managed Agents 是事件级外化。 每一条消息、每一次工具调用都是 session 中的一个事件,可以精确定位、选择性回放。好处是信息完全无损,坏处是 harness 需要做复杂的筛选和变换逻辑来决定"把哪些事件塞回上下文"。

我的方案是产物级外化。 只保留文件,中间过程全丢。好处是实现简单、恢复快、模型理解成本低(就是读文件),坏处是如果某个关键决策没有沉淀到文件里,下一轮就真的丢了(信息有损压缩)。

Anthropic在做通用基础设施,必须支持"我要回看3小时前那次 API 调用的返回值"这种场景,所以选事件级。我在做深度研究类agent,任务模式相对固定,产物级也够了。

但底层逻辑基本一致:把状态从上下文窗口搬到外部存储,让"记忆"变成"可以翻阅的笔记本"而不是"脑子里的印象"。


四、上下文窗口的真实瓶颈

聊到这里得面对一个现实:当前大模型宣称的上下文窗口和实际能稳定工作的窗口是两码事(特别是对于一些开源模型)。

标称100万甚至更长的窗口,真正不"腐烂"的范围大概在 10-20 万 token。当它们接近自身认为的上下文极限时(上下文焦虑),更易表现出摆烂的迹象,选择草草的结束任务糊弄事。

关于这点,anthropic的harness-design-long-running-apps这篇博文也有表述 anthropic关于上下文焦虑的表述.png

这个硬约束决定了一件事:任何耗时超过单次上下文容量的任务,都必须做记忆的卸载和恢复。 不是可选项,是必选项。

而且这个约束不仅存在于跨 session 场景,在单 session 内部也一样。比如主智能体把任务分派给5个子智能体,每个子智能体的结果如果都是几万token,汇总回来就可能把主智能体的上下文撑爆。这时候你要么压缩子智能体的返回(有损),要么让子智能体把结果写文件、主智能体只拿到文件路径和摘要(外化)。

我选了后者。子智能体有独立的工作目录(agents/<name>_<id>/),所有中间产物写在自己的目录里,主智能体只读摘要和关键输出。文件系统在这里同时充当了跨智能体的通信总线记忆卸载层


五、从 Test-Time Scaling 的视角看这一切

如果拉远一步看过去几年 agent 能力的演进:

  • 思考模型(CoT)→ 给单次推理更多的计算预算
  • 工具调用 → 给单次任务更多的外部交互
  • 多(子)智能体 → 给单次任务更多的并行算力
  • 跨 Session 状态继承 → 给单次任务更多的时间跨度

每一步都在拓展同一个维度:test-time 投入的总算力。Manus 提的 "agentic hour",就是这个意思——你愿意为一个任务烧多少小时的 agent 运行时间?

理论上,投入越大效果越好,这是 scaling law 在 test-time 的自然延伸。

但实际上存在一个信息保真度的天花板:每多跑一轮,记忆的压缩和恢复就多一次,每次都可能丢信息或引入偏差。当累积的信息损耗超过新轮次带来的增量价值时,再跑下去就是做无用功。

所以各家拼到最后,拼的不是"谁能跑更久",而是谁在跑得久的同时记忆腐烂得更慢。这是记忆外化方案设计的核心考验。


六、为什么我认为文件系统还是当前最优解

做记忆外化,载体的选择有很多——数据库、向量存储、事件日志、KV缓存。但在当前阶段,文件系统有几个很难被替代的优势:

模型不需要学新东西。 所有 coding agent 天然就在读写文件,catlsecho >> 这些操作零学习成本。你让模型去查一个事件日志 API,它可能搞错参数;你让它 cat TODO.md,几乎不可能出错。

目录结构就是语义索引。 research/outputs/data/ 这种组织方式本身就传达了信息的类别和优先级,比向量相似度检索更可控。模型看到目录树就知道去哪找什么。

人也能看。 用户可以直接下载文件检查中间结果,不需要理解什么事件流格式。对调试和信任建立都很重要。

沙箱天然就是文件系统。 不管是 e2b、Docker 还是别的容器方案,文件系统都是开箱即用的,不需要额外搭建基础设施。

说到底——让模型把成果写成文件,持久化到云上,跨 session 时恢复回来。这和人类几千年来用文字记录知识的逻辑完全一样。上下文窗口是"工作记忆",文件系统是"笔记本"。工作记忆会满、会遗忘,笔记本不会。

三体里,罗辑在冥王星上建造了一座地球文明博物馆,以把文字刻在石头上的方式记录下地球文明;做的事情和我们一样:把关键信息从易逝的载体转移到持久的载体上。 对罗辑来说,易逝的载体是人的记忆和电子设备,持久的是石头。对 agent 来说,易逝的是上下文窗口,持久的是文件系统。


七、什么任务真需要跑这么久?

诸如大规模的代码任务(可能涉及几百上千个脚本的代码库)、复杂的研究类任务等,这些任务场景因为本身任务的复杂度,都需要持久的 agentic hour 运行时。

而且,这些场景还有个共同特征:交付物本身就是一组文件(代码、报告、数据集),而不是一段对话。这恰恰是文件系统作为记忆层最适配的场景。

如果你判断未来这类长程任务需求会爆发式增长(我个人判断会),那 session / 记忆外化就是 agent 基础设施里绕不开的一环。