主题
专题 03 状态管理、记忆与会话设计
本专题解决的是一个非常典型、也非常容易被低估的问题:为什么一个 Agent 刚开始聊天时看起来挺聪明,聊到第三轮、第五轮之后就开始跑偏、遗忘、重复,甚至把上一位用户的信息带到当前会话里。
对前端工程师来说,这个问题并不陌生。它本质上和复杂页面里的状态污染、上下文漂移、生命周期管理失控非常像。区别只是页面状态变成了模型上下文、会话摘要、用户画像和外部记忆。
1. 为什么记忆与会话设计重要
如果一个 Agent 只有单轮能力,它只能算“会回答问题”。 如果它要支撑连续任务、多轮澄清、长期助手、工作流跟进,就必须解决以下问题:
- 这一轮回答时,哪些历史信息应该带上。
- 哪些旧信息应该丢弃,避免污染当前任务。
- 哪些信息应该长期保存,形成用户偏好或业务记忆。
- 哪些信息涉及隐私或权限,不应该跨会话延续。
很多系统失败,不是模型理解能力不够,而是记忆策略失控:
- 该记住的没记住。
- 不该记住的反而长期保存。
- 短期任务和长期偏好混在一起。
- 一个用户的上下文影响到另一个用户。
2. 用前端视角理解“记忆”
前端工程师可以把记忆系统类比成三层状态:
- 页面级临时状态:只对当前一次交互有效。
- 会话级状态:在当前任务或当前聊天窗口持续有效。
- 用户级持久状态:跨会话保留,例如偏好、身份、常用配置。
如果继续往下拆,Agent 场景里通常有四类“记忆”:
- 短期上下文:当前轮次需要立刻使用的信息。
- 会话摘要:为了降低 token 消耗,对多轮历史做压缩后的结果。
- 长期偏好:用户习惯、常用风格、默认工作方式。
- 业务记忆:和任务本身相关的结构化记录,例如已创建的工单、未完成的流程状态。
3. 常见记忆类型与适用边界
3.1 短期记忆
短期记忆主要服务当前任务。 例如用户刚刚补充的约束、当前审批链上下文、最近一次工具调用结果等。
它的特点是:
- 生命周期短。
- 对当下回答影响大。
- 一旦任务结束,很多内容应该被丢弃或摘要化。
3.2 会话摘要
会话摘要的目标不是“保留全部细节”,而是把已经发生的交流压缩成后续仍然有用的事实。
适合被保留下来的通常是:
- 当前任务是什么。
- 已明确的关键约束。
- 已经完成的步骤。
- 尚未解决的问题。
- 用户已确认的决策。
不适合保留的通常是:
- 冗长寒暄。
- 已经失效的猜测过程。
- 对当前目标没有帮助的枝节信息。
3.3 长期偏好记忆
长期偏好是用户画像的一部分,例如:
- 用户喜欢简洁回答还是详细说明。
- 默认使用中文还是英文。
- 更关注技术深度还是业务方案。
- 常用的产品、团队或项目背景。
这类信息适合长期保存,但必须让来源可追踪、可更新、可删除。
3.4 业务状态记忆
这类记忆不只是“聊天历史”,而是任务状态本身。 例如:
- 一个工单已经创建到哪一步。
- 某个审批流程已经经过哪些节点。
- 某个自动化任务是待执行、执行中还是失败待重试。
严格来说,它更接近工作流状态,而不是自然语言记忆。 但很多 Agent 项目里,这类状态会和对话系统混在一起,最终导致系统难以维护。
4. 会话边界怎么设计
这是最容易做错的一层。 你必须先定义“会话”的业务含义,而不是默认把一个聊天窗口视为一个天然会话。
4.1 按用户会话划分
适合通用助手场景。 同一用户在一段时间内的交互共享上下文。
风险在于:
- 不同任务容易串线。
- 历史消息会越来越长。
- 当前问题被旧信息污染。
4.2 按任务会话划分
适合多步骤任务、工作流和办公助手场景。 例如“帮我整理这次产品评审纪要”是一个任务;“再帮我生成周报”是另一个任务。
这种方式更利于:
- 清晰管理上下文。
- 任务完成后归档。
- 在任务级别做回放和审计。
4.3 按资源对象划分
适合知识库、工单、文档协作类场景。 例如:
- 围绕同一份文档展开的交互共享上下文。
- 围绕同一个工单编号展开的交互共享上下文。
这有利于把自然语言交互和业务对象绑定起来。
5. 记忆系统的设计原则
5.1 先分层,再存储
不要一开始就把所有历史对话丢进一个“memory”表。 应该先分清:
- 哪些是临时消息。
- 哪些是摘要。
- 哪些是长期偏好。
- 哪些是业务状态。
只有分层清楚,后续清理、更新、授权和调试才会可控。
5.2 先定义更新规则,再决定保存什么
一个成熟系统必须回答:
- 什么触发记忆写入。
- 谁来更新旧记忆。
- 什么条件下删除记忆。
- 冲突信息出现时如何合并。
如果没有更新规则,记忆会越来越脏。
5.3 记忆必须可解释
当系统表现异常时,你需要能回答:
- 这次回答引用了哪些历史信息。
- 哪一条摘要影响了决策。
- 这个用户偏好是何时写入的。
- 为什么系统认为当前任务仍在继续。
记忆如果不可解释,排查成本会非常高。
5.4 记忆必须有权限边界
尤其在企业场景里,要特别注意:
- 同一个账号能否看到不同团队的历史。
- 用户偏好能否被管理员覆盖。
- 敏感信息是否会被摘要长期保存。
- 是否支持用户删除或重置历史。
6. 一套可执行的设计方法
6.1 先画状态图
建议先画出下面几类状态:
- 会话创建。
- 消息进入。
- 是否触发摘要。
- 是否写入长期记忆。
- 是否触发业务状态变更。
- 会话结束或归档。
前端工程师很适合做这件事,因为你本来就熟悉状态流转图。
6.2 定义摘要时机
不要每轮都摘要,也不要永远不摘要。 建议定义触发条件,例如:
- 超过指定轮数。
- 总 token 超过阈值。
- 任务从探索阶段进入执行阶段。
- 用户已确认关键结论。
6.3 定义长期记忆写入条件
不是所有用户说的话都应该进入长期记忆。 比较适合写入的通常是:
- 明确表达且高频重复的偏好。
- 已确认的个人资料或项目背景。
- 经过用户确认的工作方式。
不适合直接写入的通常是:
- 一次性的临时要求。
- 带有猜测性质的内容。
- 敏感信息。
6.4 为记忆设置过期策略
建议明确:
- 哪些内容在任务结束后即失效。
- 哪些长期偏好需要定期确认。
- 哪些摘要在新任务开始时不应继续沿用。
- 哪些业务状态在流程结束后应该归档。
6.5 把自然语言记忆与结构化状态分开
例如:
- “用户偏好简洁回答”可以是自然语言或结构化标签。
- “工单 #103 进入待审批”则更适合结构化状态表。
不要让模型自己在长段对话里猜当前流程进度。 这类业务状态最好由系统显式维护。
7. 面向前端的实现建议
7.1 UI 层要让用户知道“系统记住了什么”
用户对 Agent 的不信任,很大一部分来自“它到底记住了哪些信息,我并不知道”。
前端可以考虑提供:
- 当前会话摘要概览。
- 已保存的偏好标签。
- 会话重置按钮。
- 删除历史或清空记忆入口。
7.2 区分“聊天历史”与“有效记忆”
聊天记录不等于有效记忆。 有些内容只是展示日志,不应该参与后续推理。
建议在设计上区分:
- 供用户回看的消息流。
- 供系统继续使用的摘要与状态。
7.3 任务型产品建议做“任务面板”
如果 Agent 目标是完成任务,而不只是闲聊,建议增加任务面板展示:
- 当前任务名称。
- 已确认约束。
- 已完成步骤。
- 待办动作。
- 失败与阻塞原因。
这会比单纯依赖聊天记录更可靠。
8. 常见失败模式
8.1 全量透传历史消息
现象:对话越久越乱、越慢、越偏。 原因:历史对当前目标贡献不大,但持续占用上下文预算。
8.2 摘要过早或过度压缩
现象:模型忘记关键约束。 原因:还没稳定下来的信息被过早摘要,或者摘要粒度太粗。
8.3 长期记忆污染短期任务
现象:用户这次临时说“输出详细一点”,系统后面每次都变得很啰嗦。 原因:把一次性要求错误写入了长期偏好。
8.4 业务状态只靠自然语言维持
现象:Agent 对当前流程走到哪一步说不清楚。 原因:把结构化工作流状态交给自然语言上下文去记。
8.5 缺少记忆重置机制
现象:用户想开始一个全新话题,但系统仍受旧对话影响。 原因:没有显式的新会话入口或任务切换逻辑。
9. 验证方式
可以用以下指标或检查项验证设计是否站住:
- 长会话场景下,回答质量不会明显随轮次下降。
- 相同任务跨 5 到 10 轮后,关键约束仍能被正确遵守。
- 新任务开始后,旧任务信息不会污染当前输出。
- 用户偏好更新后,系统能稳定生效且可撤销。
- 任务状态在 UI、日志和服务层三处保持一致。
10. 可复用模板
10.1 会话状态清单模板
text
会话 ID:
会话类型:通用聊天 / 任务执行 / 文档协作 / 工单处理
当前任务:
关键约束:
最近已完成动作:
待确认事项:
是否需要写入长期记忆:是 / 否
是否需要生成会话摘要:是 / 否10.2 长期记忆写入判断模板
text
候选记忆:
来源:用户明确表达 / 系统推断 / 人工录入
类型:偏好 / 背景 / 业务状态
是否跨会话有效:是 / 否
是否涉及敏感信息:是 / 否
是否允许用户删除:是 / 否
写入结论:保留 / 不保留 / 待确认11. 面试表达
你可以这样讲:
“我在做 Agent 时,没有把记忆理解成简单的聊天历史,而是拆成了短期上下文、会话摘要、长期偏好和业务状态四层。这样做的好处是每类信息的生命周期、更新策略和权限边界都更清晰。前端侧我还增加了会话重置、摘要展示和任务面板,避免系统越聊越乱,也让用户知道系统到底记住了什么。”