Agent 真的有记忆吗?短期、长期、状态与 RAG 的区别
内容摘要:"记忆"是最容易被含糊使用的词。本章把它拆成七类明确的数据,讲清各自的实现、写入与过期删除策略,以及与 RAG、任务状态的边界——混淆它们会导致串号、隐私泄露与幻觉。 难度:进阶 | 前置知识:05 上下文工程、09 状态
常见误区
只要接入向量数据库并保存全部对话,Agent 就拥有了长期记忆,而且记得越多越个性化。
先给结论
Agent 的“记忆”是多类由应用保存的数据,不是模型内部自动形成的能力。会话历史、任务状态、用户偏好、情景记录、语义知识和 RAG 语料具有不同生命周期、权限与删除规则。
带着这三个问题阅读:
- 七类常被称为“记忆”的数据分别存在哪里、活多久?
- 记忆、RAG 与任务状态为什么不能共用一套写入策略?
- 谁有权写入长期记忆,错误记忆如何纠正和删除?
一、先把"记忆"拆开
Agent 里被笼统称作"记忆"的,其实是七类不同数据,存储、生命周期、信任级别都不同:
| # | 类别 | 例子 | 存储 | 生命周期 |
|---|---|---|---|---|
| 1 | 当前请求上下文 | 本次 messages | 内存 | 请求结束即弃 |
| 2 | 会话历史 | 本轮对话 | 会话存储 | 会话级,可摘要 |
| 3 | 任务状态 | phase、待审批动作 | DB(Checkpoint) | 任务级(09) |
| 4 | 用户偏好 | "回答用中文" | 长期存储 | 长期,可删 |
| 5 | 业务事实 | 实例白名单 | 业务库 | 由业务决定 |
| 6 | 检索知识 | 文档块 | 向量库/文档库 | 见 11 RAG |
| 7 | 可过期/需删除数据 | 敏感信息、GDPR 请求 | 带 TTL/删除流程 | 必须可删 |
二、短期记忆:会话内的上下文
短期记忆就是上下文工程管理的会话历史:保留近期原文、早期摘要、关键事实转入状态。它不跨会话。
三、长期记忆:情景 vs 语义
- 情景记忆(Episodic):记"发生过的事件"——如"用户上周确认过删除策略"。
- 语义记忆(Semantic):记"事实/知识"——如"用户偏好中文""该团队负责 mysql-test-*"。
一个最小长期记忆存储(带命名空间隔离与过期):
import time
from dataclasses import dataclass, field
@dataclass
class MemoryItem:
key: str
value: str
kind: str # "preference" | "fact" | "episode"
created_at: float = field(default_factory=time.time)
ttl_s: float | None = None # None = 永久;否则到期可删
def expired(self, now: float) -> bool:
return self.ttl_s is not None and now - self.created_at > self.ttl_s
class MemoryStore:
"""按 (tenant, user) 命名空间隔离,防止多租户串号。"""
def __init__(self):
self._data: dict[tuple[str, str], dict[str, MemoryItem]] = {}
def write(self, tenant: str, user: str, item: MemoryItem) -> None:
self._data.setdefault((tenant, user), {})[item.key] = item
def read(self, tenant: str, user: str) -> list[MemoryItem]:
now = time.time()
ns = self._data.get((tenant, user), {})
# 读时过滤过期项(惰性过期)
return [it for it in ns.values() if not it.expired(now)]
def delete(self, tenant: str, user: str, key: str) -> None:
self._data.get((tenant, user), {}).pop(key, None) # 支持"被遗忘权"四、记忆写入:什么该记,什么不该记
该记:稳定偏好、被确认的决定、可复用的业务事实。 不该记:一次性上下文、未经确认的推测、敏感个人数据(除非有合规依据与删除机制)、其他用户的数据。
写入即信任提升:一旦把某内容写入长期记忆,它以后会被当作"可信事实"注入上下文。因此写入前要校验来源——不要把不可信的工具返回值/用户注入内容直接写进记忆(否则形成"记忆投毒",14)。
五、记忆 vs RAG vs 状态:别混
| 维度 | 记忆 | RAG | 任务状态 |
|---|---|---|---|
| 内容 | 用户/事件相关 | 通用知识文档 | 当前任务进度 |
| 粒度 | 条目 | 文档块 | 结构化字段 |
| 何时用 | 个性化、连续性 | 回答需外部知识 | 恢复、审批 |
六、失败路径
- 多租户串号:命名空间隔离缺失,把 A 用户的记忆给了 B——严重事故。
- 记忆投毒:把注入内容写入记忆,后续被当事实使用。
- 无法删除:无 TTL/删除流程,违反隐私合规。
- 记忆膨胀:无限写入,检索噪声大、成本高。
七、测试与验证
- 隔离测试:写入租户 A,读取租户 B 必须为空。
- 过期测试:设短 TTL,过期后读不到。
- 删除测试:删除后确实读不到("被遗忘权")。
八、安全与权限
- 命名空间隔离 + 访问控制 + 敏感字段加密/脱敏。
- 写入前来源校验;删除流程可审计。
九、性能与成本
- 长期记忆检索命中会占上下文预算;只注入 Top-K 相关项(05)。
十、框架差异
- LangGraph 提供 store/持久化;各框架"memory"抽象差异大,且很多把 RAG 也叫 memory——用本章的七分类去对齐,不要被命名误导。
十一、关联章节
面试复述
模型调用无状态,所谓记忆都是应用层数据。短期历史服务当前会话,状态保证任务执行,长期记忆保存经筛选的信息,RAG 提供可追溯知识;四者必须分开治理。
复述时先给结论,再补机制、适用边界和一个可验证指标;不要只罗列框架名称或产品功能。
迁移练习
为一个客服 Agent 的候选记忆逐条分类:用户偏好、订单状态、产品手册、一次投诉、模型总结,并为每类定义保留期限与删除入口。
检索关键词
记忆分类 短期 长期 情景 语义记忆 记忆过期 TTL 多租户隔离 记忆投毒 被遗忘权
官方来源
- 各框架 memory/store 文档;隐私合规(如 GDPR"被遗忘权")作为工程约束(
verified_at: 2026-09-07)。
