当 Agent 从单轮问答走向连续办事,记忆管理就会成为绕不开的工程问题:聊天历史放多少、跨会话信息存在哪里、上下文接近上限时怎样保住关键状态,都需要明确规则。下面从长短期记忆的边界出发,逐步分析多轮会话衔接、上下文预算与压缩策略,并用具体业务流程检验这些设计是否可靠。
这题问的是:Agent 怎么记住事,又怎么在记不住的时候不崩。
按顺序答:先分清短期和长期、再讲多轮对话怎么接上、然后讲上下文塞满了怎么压、最后用制度问答项目走一遍。每块一句口播。
整件事可以先记成一张图:
短期记忆 = 这一单的对话和状态,放在上下文里。
长期记忆 = 跨会话的偏好和事实,放在库里,用的时候再捞。
上下文快满了 = 先压旧的、留新的,关键信息落成结构化字段。
面试最爱问「你们 Agent 的记忆怎么做的」。别只答一句「存聊天记录」。记忆至少分两层:
| 短期记忆 | 长期记忆 | |
|---|---|---|
| 存什么 | 这一单的对话、槽位、调过哪些工具 | 用户偏好、历史事实、知识 |
| 放哪 | 上下文窗口 + 会话状态 | 数据库 / 向量库 |
| 活多久 | 这一单结束就丢 | 跨会话长期保留 |
| 怎么用 | 直接进提示词 | 检索出来再进提示词 |

短期记忆是「这一单做到哪」:用户刚说的日期、缺的原因、上一步调了什么。它必须进上下文,模型才接得上。
长期记忆是「这个人是谁」:他常驻上海、偏好邮件通知、上次请假是病假。它不该全塞进上下文,而是需要时检索几条出来。
面试一句话:短期记这一单,长期记这个人;短期进上下文,长期进库再捞。
多轮对话不是把历史全堆进提示词。核心是两件事:会话 ID 和 状态。
用户每来一条消息,带上同一个 thread_id(会话 ID)。后端拿这个 ID 去捞这一单的状态:之前的对话、已填的槽、走到哪一步。和新消息合并后再跑。

几个必须说清的点:
1. 对话要追加,不能覆盖。 上一轮用户的话丢了,模型就断片。对话列表用追加(add_messages 这类 reducer)。
2. 不是所有字段都追加。 检索到的条款块、意图用覆盖。如果检索块也追加,几轮之后提示词被旧条款塞满,还可能带进已废止版本。
3. 槽位要按键合并。 请假先记「明天」,再补「家里有事」。如果节点只返回 {原因: ...} 又没合并,日期会被整份盖掉。字典槽位要浅合并:新键覆盖旧键,没传的留下。
4. 补槽时别重新判意图。 用户补「原因是家里有事」,路由不要重新判成闲聊。槽位未齐、上一跳是办事,就继续走补槽。
面试一句话:会话 ID 把同一单串起来;对话追加、检索覆盖、槽位合并。
上下文窗口再大也是有限的。系统提示词、工具定义、检索块、历史对话、当前问题,全都要占地方。塞满了要么报错,要么模型开始忽略中间的内容。
所以要有预算意识:先给谁、留多少、超了砍谁。

一个实用的分配顺序:
面试一句话:窗口是预算,不是仓库;先保系统提示和当前问题,再按重要性分配。
对话一长,历史必然超预算。压缩不是简单删掉,而是把旧的压成更短、更稳的形式。

三种常用手段,从轻到重:
1. 滑动窗口。 只留最近 N 轮,更早的直接丢。最简单,但会丢信息。
2. 摘要压缩。 把更早的对话让模型压成一段摘要,替换掉原文。省地方,但摘要可能丢细节、也可能编。
3. 结构化落字段。 把关键信息(日期、原因、单号、偏好)抽成结构化字段存进状态。这是最稳的:不依赖模型记住,代码直接读。
实际做法是组合:最近几轮原样留,更早的压成摘要,关键信息落成字段。
几条原则:
面试一句话:压缩是保信息、去冗余;旧的压成摘要,关键落成字段,别指望模型自己记住。
长期记忆不是把所有对话存下来。存什么、怎么取、怎么更新,三件事都要想清楚。
存什么:
怎么取: 和 RAG 一样,按当前问题检索相关的几条,不要全量加载。取多了又变成上下文负担。
怎么更新: 新信息覆盖旧信息,冲突时以最新为准。比如用户说「我搬到北京了」,要更新而不是追加两条矛盾记录。
边界: 长期记忆和 RAG 知识库要分开。知识库是制度全文,长期记忆是「这个用户」。两者检索源不同,别混在一个库里。
面试一句话:长期记忆存偏好和事实,按需检索、冲突覆盖;和知识库分开。
记忆分两层:短期记这一单的对话和状态,进上下文;长期记用户偏好和事实,进库按需捞。
多轮对话靠会话 ID 把同一单串起来,对话追加、检索覆盖、槽位合并。
上下文是预算不是仓库,先保系统提示和当前问题,再按重要性分配。
快满了就压缩:最近几轮原样留,更早的压成摘要,关键信息落成结构化字段。
长期记忆存偏好和事实,按需检索、冲突覆盖,和知识库分开。
压轴一句:短期管这一单,长期管这个人;上下文要算预算,压缩要保信息。
还是制度问答助手。用户先说「帮我请明天的假」,隔一轮又补「原因是家里有事」。

评测就三句:补槽时有没有丢已填的槽;压缩后还记不记得缺什么;长期偏好有没有在需要时被取出来。
Q:短期记忆和长期记忆的区别?
A:短期是这一单的对话和状态,进上下文,结束就丢;长期是跨会话的偏好和事实,进库按需检索。
Q:多轮对话就是把历史全塞进提示词吗?
A:不是。靠会话 ID 捞状态,对话追加、检索覆盖、槽位合并。全塞又贵又吵,还会淹没关键信息。
Q:上下文满了怎么办?
A:压缩。最近几轮原样留,更早的压成摘要,关键信息落成结构化字段。有触发条件,不是每轮都压。
Q:压缩会不会把重要信息压没?
A:会。所以单号、日期、金额、明确偏好要落成字段,不依赖摘要。摘要给模板,别让模型自由发挥。
Q:长期记忆和 RAG 知识库是一回事吗?
A:不是。知识库是制度全文,长期记忆是「这个用户」。检索源不同,要分开。
Q:记忆冲突了听谁的?
A:以最新为准,覆盖旧的。用户说搬家了,就更新,不要留两条矛盾记录。
Q:记忆要不要全交给模型自己管?
A:不要。存什么、怎么取、什么时候压,都要代码定规则。模型可以建议,但字段和触发条件写在代码里。