会话内的事算记忆吗

有人说不算。理由是:工作记忆就是 prompt 本身,模型读一遍就完事了,压根没存下来,那算什么记忆。
也有人说,这就是短期记忆。
其实会话内真正在做的事不是"存",是"取舍":什么留在窗口里、什么换出去、什么等要用的时候再拉回来。
举两个例子你就明白为什么这事要紧。你在会话内把工具结果全清光了,回头就没法从里面提炼出"这个工具到底该怎么用"的经验;你压缩的时候把用户那句纠正当噪声丢了,那它就是真的没了,找不回来。
所以哪怕你只关心长期记忆,也得关心会话内这层------它在整条链路的最上游。
一、窗口变大并没有解决问题
先破除一个直觉:上下文都到百万 token 了,是不是把东西全塞进去就行?
通常不行。有两个常见失效模式挡在前面。
Context rot(上下文腐蚀)。 当上下文很长、噪声较多,或任务需要跨越多个位置整合信息时,模型从新增 token 中获得的有效收益可能逐渐下降,甚至出现幻觉、自相矛盾和含糊回答。它不意味着"上下文一长就必然失效",具体程度仍取决于模型、任务、内容组织和提示方式。Anthropic 在工程指南里强调:在碰到硬上限之前,每增加一个 token 的边际收益就可能开始下降。
Lost-in-the-middle。 长 prompt 中段的信息往往比头尾更难被稳定召回,但影响程度会随模型架构、训练方式、窗口长度、提示布局和任务类型变化,并不是"跟模型和窗口都没关系"。对一个跑了几十轮的 Agent 来说,用户偏好、早先的承诺、上个问题怎么处理的,恰好容易落到这段不利位置。
Anthropic 给的框架很适合拿来做工程判断:上下文是有限的、边际收益递减的资源,核心纪律是找到足够完成任务的高信号 token 集合。
把它当 RAM 看就对了。RAM 变大能缓解压力,但有没有换页策略,仍然决定它好不好用。
二、三个手段
很多人把这三件事糊成一个模块,结果三边都做不好。
| 手段 | 做什么 | 解决什么问题 | 会话结束后 |
|---|---|---|---|
| 压缩 | 把窗口内容蒸馏成高保真摘要,Agent 带着摘要继续跑 | 对话变长后的性能衰减 | 通常消失 |
| 清理 | 丢掉旧的、可重新获取的工具结果,同时保留调用记录 | 工具输出膨胀 | 消失 |
| 记忆 | 结构化记笔记,写到持久外部存储 | 跨任务、跨会话的进度追踪 | 留下 |
三者的区别一句话就能记住:压缩是维持有效上下文,清理是去噪,记忆是留档。 压缩有时也能降低 token 成本,但那是结果,不是首要目标。
工具结果清理这条里有个细节特别容易被跳过:只丢结果,留住调用记录。 因为对推理来说,"我查过这个了"和"结果是什么"是两种不同的信息------前者防止 Agent 白干一遍,后者才是真占地方的那部分。很多自己写清理逻辑的实现,一刀把整条 tool call 连根删掉,然后 Agent 就开始转圈重查。
Anthropic 公布过一组实测数据(link):
- 内部检索类任务评测上,清理 + 记忆组合相比基线提升 39%
- 只做清理提升 29%
- 一个 100 轮网页搜索评测里,清理让原本会因上下文耗尽而失败的工作流跑完,token 消耗降低 84%
这些数字说明特定评测中的收益,不应直接当成所有模型和业务的预期值。
三、压缩的四种思路:多维对照,不是单轴排序
压缩不是一件事,而是一组处在不同维度、不同抽象层的思路:截断 / 滑窗和滚动摘要是内容处理方式,分级渐进是调度策略,自主折叠则同时涉及触发机制与训练方案。下面按触发、输出、可逆性和训练要求做多维对照,不把它们解释成代价或可逆性单调递增的四级阶梯。

方案 1:截断 / 滑动窗口
留最近 N 轮,其余全扔。实现成本很低,也基本不判断信息价值。
它更适合短对话、没有长程依赖的客服问答。放到长任务里风险很高------因为它扔掉的可能就是最早出现的任务目标。
方案 2:滚动摘要 / 分块读 + 状态更新
不一口吞下整个文档,而是分块读,每读完一块就更新一份紧凑的状态。
这条路研究做得比较系统。MemAgent 的做法是一块块读文档、更新一份紧凑记忆、最后拿累积记忆生成答案,效果是从 8K 上下文训练外推到 350 万 token 的 QA 任务、性能损失不到 10%,512K 的 NIAH / RULER 测试上 95%+(arXiv:2507.02259)。QwenLong-L1.5 是同一思路的完整后训练配方:先把一个 30B 推理模型做到能稳定吃下 256K,再靠外部记忆 Agent 扩到 100 万--400 万 token 区间(arXiv:2512.12967)。
工程上真正值得抄的是它的状态结构:不光存"读到了什么"(Memory),还存"接下来要读什么"(Plan)。 只有摘要没有计划,Agent 在长文档里更容易迷路;有 Plan,相当于给滚动压缩装了个方向盘。
这类结果至少提示了一件事:在某些任务上,小窗口 + 合适的压缩策略,可能优于大窗口 + 没有策略。窗口大小不是唯一变量,换页策略同样重要。
方案 3:分级渐进压缩
一次压缩可以由一组策略逐级兜底:前一级不足以释放所需空间时,再进入下一级。
AgentScope 的 AutoContextMemory 给出了一套框架特定的六级顺序:先处理历史工具调用,再扩大消息卸载范围,最后摘要当前轮。
- 历史工具调用压缩(要调 LLM,token 超阈值触发)
- 大消息卸载(不调 LLM,保护最近 N 条)
- 卸载范围扩大(不调 LLM)
- 历史轮次 LLM 摘要
- 当前轮大消息 LLM 摘要
- 当前轮整体按比例压缩(兜底)
这套顺序表达的是该框架的逐级兜底流程,不是严格的代价排序,也不能推出所有实现都应先避开 LLM。落地时应测量自身消息分布、模型调用成本、卸载与回取延迟,再按评测结果安排顺序。所有压掉的内容都按 UUID 存档,配专门的工具随时把原文拉回来------这是懒加载,不是截断。
这也说明它跟第一种处理方式的关键差别:信息离开了窗口,但没离开系统。
方案 4:自主触发的结构化折叠
这个方案把部分触发权交给 Agent 自己。
DeepAgent 的记忆折叠(memory folding)就是这一路:Agent 在推理过程中自己判断时机,把过往交互压成结构化的情景(episodic)、工作(working)、工具(tool)三类记忆 ,然后拿压缩后的结构替代原始历史,接着往下推。论文把目标归纳为两个问题------工具调用导致的上下文长度增长,以及交互历史堆积带来的错误累积。项目 README 的说法是让 Agent 暂停一下,重新整理策略再继续,内容经改写)。
它还配了一套端到端 RL(ToolPO),用 LLM 模拟的 API 来训练,把奖励归因到工具调用的 token 上。
"自主触发"为什么重要? 固定阈值压缩是在 token 数达标时触发,不一定碰巧对应推理陷进死胡同 的时刻。而后者也可能需要重新组织历史------这时候目标不是单纯减少 token,而是从已经跑偏的路径上退出来。DeepAgent 的三类记忆分区(发生了什么 / 现在要干什么 / 工具怎么用),本质上是给下一轮推理准备一份交接文档。
4 个方案的多维对照
| 思路及定位 | 触发时机 | 输出形态 | 可逆 | 需训练 | 适合 |
|---|---|---|---|---|---|
| 截断/滑窗(处理方式) | 固定阈值 | 无 | ❌ | ❌ | 短对话 |
| 滚动摘要(处理方式) | 每块读完 | Memory + Plan | ❌ | 通常需要 | 超长文档处理 |
| 分级渐进(调度策略) | 框架特定的逐级兜底 | 摘要 + UUID 存档 | ✅ | ❌ | 通用 Agent 框架 |
| 自主折叠(触发与训练方案) | Agent 自己决定 | 结构化 JSON 三分区 | 取决于实现 | 需要(RL) | 长时序工具型推理 |
工程上的默认起点可以是:分级渐进 + 可逆卸载。它不要求额外训练,原文仍可回取,代价也相对容易控制。等 Agent 频繁出现"在错误路径上原地打转"的症状,再评估是否需要自主触发与相应训练方案。
四、卸载:让不必进窗口的内容留在窗口外
上面四种思路都在处理"已经进了窗口的东西"。更直接的做法,是让不需要立即参与推理的内容先别进来。
两条路:
大结果落盘,窗口里只留引用。 工具返回 50 万字的日志,进窗口的可以是一个文件路径加一句摘要;模型真需要细节时,再用文件工具去读。Anthropic 把这类做法归到"programmatic tool calling"------让大结果不直接进入模型上下文。
大消息按需回取。 就是上面第 3 种思路说的 UUID 存档机制。差别在于,卸载可以是主动的(预判这部分短期内大概率用不到),而不是等超过阈值再被动执行。
这条思路推到更远,就是 Anthropic 的 memory tool:记忆可以表现为一个目录里的文件,模型用普通文件工具增删改查。 存储在自己的基础设施上,通过工具调用在客户端执行。它本身是跨会话机制,但本文只取它在会话内的一个用途:把窗口当索引,把文件系统当可回取的外部存储。
五、KV cache:它不是记忆,但会约束记忆怎么注入
KV cache 不是记忆本体:它不决定记住什么,也不负责压缩、卸载或回取。对记忆注入来说,初中级开发者先掌握下面三条工程规则即可。

规则一:稳定前缀放前面
system prompt、工具定义、长期人设、团队规范这些每轮相对稳定的内容,适合放在前面。
规则二:动态内容后置或按需查询
检索结果、时间戳、动态状态等高频变化内容尽量往后放,避免反复改写稳定前缀。对于每轮都可能增删改的原子记忆,也可以提供只读查询工具,在模型需要时再调用,并把结果追加到当前历史末尾。
按需查询会多一次工具调用往返,因此要结合查询延迟和调用频率判断是否划算。
规则三:以实际平台测试为准
不同推理服务的缓存匹配、保留和路由方式并不相同。工程上应查看所用平台的文档,并实测命中率、延迟和成本,不要把某一种实现假定为通用规则。
进阶:自建推理服务中的实例亲和与共享缓存可以组合
因果掩码使 token 只能依赖前文,因此稳定前缀在 prefill 阶段的计算有机会复用;中间内容变化后,后续位置通常需要重新计算。在多实例服务中,可以同时使用会话实例亲和与共享缓存后端来提高复用机会,它们不是二选一。托管 API 用户通常无需、也未必能够控制这些底层后端,应以平台提供的能力和实测结果为准。
六、注入预算:从小预算开始,用评测调参
缺少业务数据时,先设保守的小预算,再根据任务成功率、召回质量和延迟逐步调整,不把起始配置当作通用定律。
成熟实现一般会让三重限制同时生效:条数上限、字符/token 预算上限、检索超时上限。召回变慢时,可以减少返回内容,避免卡住主链路。
当注入内容占窗口显著比例时,应优先排查是否大段搬入原文、是否缺少摘要和按需回取、是否真的需要这么多内容;最终边界仍由具体模型、任务和评测决定。
七、这些取舍会传导到下游
最后提醒一件事:会话内这三个决策,会直接决定之后还能做什么。
- 清理工具结果时丢了什么 → 决定能不能从这个会话里提炼出"这个工具到底该怎么用"的经验
- 压缩摘要保留了什么维度 → 决定沉淀下来的东西是有结构的(发生了什么 / 现在要干什么 / 工具怎么用),还是一段难以复用的自然语言
- 压缩是截断还是可逆卸载 → 决定事后还能不能回去核对原文。派生内容可能失真,因此需要保留可追溯的原始层
所以下面清单的最后一条,服务的不只是当前会话,也是后续提取长期记忆时的可追溯性。
八、会话内落地清单
- 分清三类动作:压缩维持有效上下文,清理移除可重取噪声,持久记忆留给跨会话层处理
- 先定保留规则:任务目标、用户纠正、关键决策、未完成事项和工具调用记录优先保留
- 给压缩设触发条件:同时考虑 token 压力、工具结果膨胀和推理是否跑偏,不只盯固定阈值
- 大结果先卸载:原文落盘,窗口保留摘要、引用和回取工具;删除前确认内容可重取
- 摘要带状态与计划:至少说明已经完成什么、当前结论、下一步和未决问题
- 稳定前缀与动态内容分开:减少在 prompt 中段反复重写,并按实际服务验证缓存收益
- 保留可追溯原始层:让摘要、结论和后续长期记忆都能回到原始工具结果或对话片段核对
可观测性:记录"压过什么",也记录"能不能继续做"
每次压缩或卸载至少记录:触发原因、被卸载内容的引用、后续回取次数、压缩前后 token,以及任务在压缩后是否恢复并继续完成。这样才能区分"窗口确实变短了"和"Agent 仍然知道自己在做什么"。如果只看 token 降幅,很容易把丢任务状态误当成优化成功。
参考来源
- Anthropic --- Context engineering: memory, compaction, and tool clearing(cookbook)
- Anthropic --- Managing context on the Claude Developer Platform
- Anthropic --- Memory tool(官方文档)
- arXiv:2507.02259 --- MemAgent: Reshaping Long-Context LLM with Multi-Conv RL-based Memory Agent
- arXiv:2512.12967 --- QwenLong-L1.5: Post-Training Recipe for Long-Context Reasoning and Memory Management
- arXiv:2510.21618 --- DeepAgent: A General Reasoning Agent with Scalable Toolsets
- RUC-NLPIR/DeepAgent(GitHub)
- The state of AI memory in 2026: claimed vs observed
- Tencent/TencentDB-Agent-Memory(GitHub)