AI Agent Memory vs RAG:长期记忆、会话状态、Checkpoint 和知识库到底怎么分?
AI Agent Memory、RAG、Session State、Checkpoint 和 Knowledge Base 经常被混为一谈。本文从数据来源、写入者、生命周期、作用域、检索方式、删除与权限边界拆解生产级 Agent Memory,并给出可落地的数据分层与决策表。
Evidence 10 条资料来源
本文目录
AI Agent Memory vs RAG:长期记忆、会话状态、Checkpoint 和知识库到底怎么分?
如果一个 Agent 能记住“这个用户默认用 Objective-C”,能继续上一次没有做完的任务,也能从产品文档里查到最新 API,这三种“记住”看起来很像,但在生产系统里其实是三条不同的数据链路。
把它们统称为 Memory,最容易得到一种看似简单、实际很难治理的架构:聊天记录、用户偏好、工具结果、知识库文档、工作流快照全部进同一个向量库,再靠相似度决定下一次给模型什么。Demo 往往能跑,系统一旦长期运行,问题会集中出现在旧信息覆盖新信息、跨用户串线、恢复状态混乱、删除不彻底,以及检索出来的内容到底是“事实证据”还是“用户约束”无法区分。
真正需要先回答的不是“用哪个向量数据库”,而是:
这条信息是谁产生的、需要活多久、对谁生效、是否会变化、是否需要在失败后恢复,以及它进入 Prompt 时应该被当成知识证据、执行状态,还是长期约束。
这篇文章只解决这个边界问题。关于长期记忆如何做混合检索、重排、时效性和冲突消解,继续看 AI Agent Memory Retrieval 实战;关于具体 Coding Agent 的记忆效果,可以看 Funes Agent Memory 实测;如果要看 Memory、State、RAG 如何进一步进入会跨 App 执行任务的个人智能体,可以继续看 Personal AI Agent 架构。
先给结论:五种东西不要混成一层
| 数据层 | 解决的问题 | 典型数据 | 典型作用域 | 主要读法 |
|---|---|---|---|---|
| Session / Thread State | 当前会话正在发生什么 | 消息、当前步骤、临时变量、工具结果 | session / thread | 精确读取 |
| Checkpoint | 失败或中断后如何恢复 | 图状态快照、节点进度、pending interrupt | thread + checkpoint | 按 thread/checkpoint 恢复 |
| Long-term Agent Memory | 以后还需要记住什么 | 用户偏好、项目约束、历史决策、经验 | user / project / agent | 精确查询 + 检索 |
| RAG | 当前问题需要什么外部证据 | 文档、代码、政策、手册、知识片段 | corpus / tenant | 检索 + rerank |
| Knowledge Base | RAG 从哪里取知识 | 原始文档、结构化知识、图谱、索引 | org / product / corpus | 索引与版本管理 |
它们可以共用 PostgreSQL、对象存储、向量库或全文索引,但共用基础设施不代表共用数据模型、生命周期和权限规则。
LangGraph 的官方持久化文档把这条边界拆得很直接:Checkpointer 保存 thread 的 graph state,承担短期、thread-scoped 的连续性和恢复;Store 保存 graph state 之外的应用数据,用于跨 thread 的长期记忆。Google ADK 也把 Session、State 和 Memory 分成不同概念:Session/State 面向当前会话,MemoryService 面向跨 Session 的可搜索信息。
这两个框架的术语并不完全相同,但共同点很明确:当前执行状态和跨会话长期信息不是同一个数据面。
Memory 和 RAG 为什么经常被混淆
因为它们的“读取动作”可能非常像。
两套系统都可能执行:
query
→ embedding
→ metadata filter
→ vector / hybrid search
→ rerank
→ context assembly
如果只看读取链路,Memory 很容易被理解成“对聊天历史做 RAG”。
问题在于,Memory 还有一条 RAG 通常不负责的写入与治理链路:
interaction / tool result / user correction
→ 判断是否值得长期保存
→ 提取结构化事实或经验
→ 标记来源、身份、作用域和权威级别
→ 与旧记忆比较
→ ADD / UPDATE / SUPERSEDE / DELETE / NOOP
→ 持久化
→ 后续按权限召回
所以最实用的区分不是“是否用了向量检索”,而是:
- RAG:现在回答这个问题,需要从外部知识资产取回哪些证据?
- Memory:之前发生过什么、用户明确要求过什么、哪些约束或经验需要继续影响后续行为?
一份 API 文档属于知识库;“这个项目禁止引入某个依赖”更像项目 Memory。两者都可能被检索,但进入 Prompt 后的权威性完全不同。
Session State:当前会话的工作台
Session State 适合保存当前会话或当前 thread 正在变化的数据,例如:
- 当前表单已经收集了哪些字段;
- 多步流程走到第几步;
- 最近一次工具调用返回了什么;
- 当前任务有哪些 pending action;
- 当前会话临时选择了什么模式。
Google ADK 把 session.state 描述为 Session 的 scratchpad,并区分 session、user、app、temp 等不同作用域。LangGraph 则把短期 memory 放在 graph state 中,通过 Checkpointer 持久化,使同一个 thread 可以继续。
这里有一个容易误判的点:
持久化的 Session State 仍然不等于长期 Agent Memory。
一个状态即使被 PostgreSQL 永久保存,也不代表它应该跨项目、跨 thread 被自动拿来影响未来决策。持久化方式解决“会不会丢”,作用域解决“应该对谁生效”,两者不能混在一起。
Checkpoint:为了恢复执行,不是为了塑造长期偏好
Checkpoint 的核心职责是恢复可执行状态。
在 LangGraph 中,Checkpointer 会保存 graph state 的 checkpoint,使应用能够:
- 继续同一 thread;
- Human-in-the-loop 后恢复;
- 从中断点继续;
- 做 fault tolerance;
- 查看或回到历史状态。
这和“记住用户以后都喜欢什么”不是同一个问题。
一个典型 Checkpoint 可能包含:
{
"thread_id": "support-781",
"current_node": "awaiting_approval",
"retry_count": 2,
"pending_tool_call": "refund_order",
"messages": ["..."]
}
长期 Memory 更像:
{
"subject": "user:42",
"scope": "project:mobile-app",
"kind": "explicit_preference",
"content": "iOS 示例默认使用 Objective-C。",
"source": "user_statement",
"valid_from": "2026-09-01",
"status": "active"
}
前者回答“这次执行走到哪里”;后者回答“未来遇到相关任务时什么约束仍然有效”。
需要特别修正一个常见说法:Checkpoint 并不会因为 thread 在业务上“结束”就自动消失。 是否保留、清理和过期取决于具体持久化实现与应用的数据保留策略。不要把“thread-scoped”误写成“thread 结束后一定物理删除”。
Knowledge Base:知识资产本身,不等于 RAG,也不等于 Memory
Knowledge Base 是数据资产;RAG 是利用这些资产的一种运行时模式。
知识库可以包括:
- 产品文档;
- API Reference;
- 企业制度;
- 代码库;
- PDF;
- 工单;
- 数据库记录;
- 知识图谱。
RAG 负责在当前问题发生时,从这些资产里找出需要的证据并交给模型。
因此:
Knowledge Base = what you know
RAG = how you retrieve evidence now
Agent Memory = what should continue to affect this agent/user/task over time
现实系统当然会有重叠。例如 Google ADK 的 MemoryService 文档明确允许 Memory 包含过去 Session,也可能接外部数据;其 RAG Memory 实现甚至直接把对话存进 Knowledge Engine 做向量检索。这恰好说明:实现技术可以重叠,系统语义仍然必须自己定义清楚。
Long-term Memory:最重要的不是“长期”,而是“会改变未来行为”
长期 Memory 不应该等同于“保存时间超过一天的数据”。
更合理的准入问题是:
如果下一次没有把这条信息提供给 Agent,它的行为是否可能明显变差、违背用户约束或重复已经解决过的问题?
适合进入长期 Memory 的例子:
- 用户明确、稳定的输出偏好;
- 项目或仓库长期约束;
- 已确认的业务事实;
- 上次做过的重要决策以及原因;
- 能避免重复失败的历史经验;
- 长任务跨会话需要延续的少量高价值状态。
通常不应该直接进入长期 Memory:
- 寒暄;
- 一次性的临时数字;
- 未验证的模型推断;
- 一次工具调用的原始长日志;
- 已经过期的中间结果;
- 可以随时从权威系统重新查询的事实;
- 无明确保留目的的敏感数据。
不要先选“向量库”,先选读取方式
Agent Memory 不一定需要向量数据库。
适合精确查询
例如:
- 用户语言;
- 当前订阅计划;
- 项目技术栈;
- 是否允许调用生产工具;
- 默认时区;
- 账号或租户作用域。
这类数据有稳定键,应该优先:
tenant_id + user_id + project_id + key
用关系库、KV Store 或文档库做确定性查询。
适合语义检索
例如:
- 历史故障处理经验;
- 类似项目决策;
- 很长的自然语言事件;
- 用户过去多次表达的非结构化偏好。
这时才考虑向量检索、全文检索或混合检索。
研究层面也开始越来越强调“没有一种 Memory substrate 在所有任务上都最好”。2026 年关于 Memory Substrate 的系统评估指出,不同任务、历史长度和决策场景需要不同存储与检索方式;过量检索甚至会把注意力从当前行动关键信息上移开。
一条可落地的生产级分层
我更推荐把 Agent 上下文至少拆成六个数据面:
1. Invocation Context
└─ 只活一次调用
2. Session / Thread State
└─ 当前会话、任务进度、近期消息
3. Checkpoint / Durable Execution
└─ 可恢复的执行快照
4. Long-term Memory
├─ user facts
├─ preferences
├─ project constraints
├─ decisions
└─ experiences
5. Knowledge Base / RAG
└─ docs, code, policies, external facts
6. Audit / Trace
└─ 为调试、风控、审计保留,不默认注入模型
真正重要的是第 4、5、6 层不要偷懒混在一起。
Audit Log 可能保存多年,但它不应该因此变成“长期 Memory”;生产日志是给工程师和审计系统看的,不应因为时间长就自动回灌 Prompt。
再加一层边界:Memory 不等于“当前世界状态”
2026 年 10 月这批新的 Memory 讨论又暴露了一个容易被忽略的问题:即使已经把 RAG、长期 Memory 和 Session State 分开,系统仍然可能把“历史上曾经成立的事实”误当成“现在仍然成立的事实”。
例如,“这个项目默认使用 Objective-C”可以是长期项目 Memory;“当前构建失败”更像当前任务状态;“线上版本现在是 3.2.1”如果能从发布系统实时读取,就不应该只靠历史 Memory;“某个 API 昨天返回 500”属于历史观测,不等于当前 API 仍故障。
生产系统最好显式区分三种语义:
| 类型 | 回答的问题 | 典型来源 | 使用方式 |
|---|---|---|---|
| Durable Memory | 哪些历史约束、偏好、决策以后仍应生效 | 用户明确输入、项目规则、确认决策 | 可跨会话持续影响行为 |
| Current State / Belief State | 系统此刻认为世界是什么状态 | 实时工具、当前任务状态、最新验证 | 进入当前决策,但需要时效与来源 |
| Historical Observation | 过去发生过什么 | Trace、事件、旧工具结果 | 默认不冒充当前事实,需要重新验证 |
这里的 belief state 不是让模型自由猜测,而是要求系统把当前可操作状态及其证据显式表示出来:来源是什么、什么时候验证、是否可能过期、能不能被实时 source of truth 覆盖。
这能避免一个典型故障:Memory 检索命中一条旧记录,语义上很相关,但它的事实时效已经失效。向量相似度无法解决这个问题,必须依赖 provenance、validity 和 source-of-truth 策略。
Long-term Memory 的完整生命周期
如果一个 Memory 系统只有 insert() 和 search(),它还没有进入生产级。
至少要考虑:
1. Admission:是否值得写
写入前判断:
- 是否明确影响未来任务;
- 来源是谁;
- 是用户明确陈述、工具观测还是模型推断;
- 是否属于敏感信息;
- 应该属于哪个 scope;
- 预计有效多久。
2. Normalize:变成可治理的数据
不要只保存一句裸文本。
一个更可控的结构可能是:
{
"memory_id": "mem_...",
"tenant_id": "t1",
"user_id": "u42",
"scope": "project:recalai-ios",
"kind": "project_constraint",
"content": "iOS 示例默认使用 Objective-C。",
"source_kind": "explicit_user",
"source_ref": "conversation:...",
"confidence": 1.0,
"valid_from": "2026-09-01T00:00:00Z",
"valid_to": null,
"status": "active",
"supersedes": null
}
3. Reconcile:新信息和旧信息怎么处理
新信息不是永远 append。
应该允许:
- ADD
- UPDATE
- SUPERSEDE
- INVALIDATE
- DELETE
- NOOP
例如用户从“默认 Python”改成“这个项目必须 Objective-C”,系统需要判断这是全局偏好变化,还是只对一个项目生效,而不是把两句话都检索出来交给模型猜。
4. Retrieve:什么时候该读
不是每一轮都读长期 Memory。
纯格式转换、计算、翻译、一次性摘要通常不需要长期记忆。需要延续历史任务、遵循稳定偏好、复用项目规则或历史经验时才进入 Memory Retrieval。
具体召回、重排、时效性和冲突消解,可以继续看 AI Agent Memory Retrieval 实战。
5. Forget / Delete:怎么让旧记忆真正退出
“遗忘”至少有三种:
- 逻辑失效:旧记录保留审计,但不再允许召回;
- TTL / 过期:到期后自动失效;
- 删除:按产品与合规要求从相关数据面删除并验证。
这里不能承诺“100% 一键擦除”这种不受实现保证的说法。生产系统应该建立 deletion ledger,逐个数据面记录:
primary store
vector index
cache
derived summary
backup / retention boundary
audit record
然后对可删除的数据做 delete + read-back verification。
站内 Google ADK delete_session() 与长期 Memory 删除实测 已经验证过一个典型边界:删除 Session 不等于长期 Memory 一定被级联删除。
多用户系统:身份和 Scope 必须在召回前生效
最危险的 Memory 问题不是“没记住”,而是记住了别人的东西。
生产查询至少应该把这些字段当作硬约束:
tenant_id
user_id
agent_id
project_id / workspace_id
memory status
authorization scope
优先在数据库 / 检索引擎查询阶段完成过滤,而不是先召回整个集合,再让应用层删除“不该看的结果”。
同时要区分:
- 身份隔离:这条数据属于谁;
- 权限判断:当前 Agent 能不能用;
- 作用域:在哪个项目/任务里有效;
- 权威性:用户明确要求,还是模型推断;
- 生命周期:是否已经失效。
Vector similarity 只回答“像不像”,它不能替你回答这些问题。
Agent Memory 的评估不能只看 Recall
一个 RAG 系统经常关注 Recall@K、Precision@K、MRR 等检索指标。
Memory 还需要额外看:
- Useful Recall:真正改变当前任务的记忆是否被拿到;
- Stale Memory Rate:召回结果里有多少已过期;
- Conflict Error Rate:冲突记忆是否被同时注入;
- Cross-user Leakage Rate:是否出现跨身份结果;
- Unnecessary Recall Rate:本来不需要 Memory 的请求却加载了多少;
- Write Precision:写进去的长期记忆有多少真的值得长期保存;
- Correction Success:用户纠正后旧记忆是否停止生效;
- Deletion Verification:删除请求后各数据面是否验证不可再读;
- Prompt Token Cost:Memory 实际占用了多少上下文;
- P95 Retrieval Latency:召回对端到端延迟造成多少影响。
2026 年的 Memory 研究越来越把问题从“存在哪”转向“如何管理持续演化的状态”。这也是为什么单纯提高 embedding 维度或 top_k,通常解决不了长期记忆真正的可靠性问题。
RecalAI 的第一方实现:资料库、Memory 和当前状态为什么分开
我自己在做 RecalAI 本地个人知识库时,实际遇到的也是同一个边界问题:资料库检索能力很强,不代表它就应该承担长期用户 Memory。
RecalAI 的资料链路是“保存原件 → OCR/解析 → 规范化 → Chunk → FTS 立即可搜 → 后台 Embedding/摘要/标签/图片理解”;查询再走“FTS + Query Embedding → Chunk 混合召回 → RRF/去重 → Rerank → Evidence → 本地或云端生成”。这本质上是一套 Knowledge Base + RAG 数据面,解决的是“我保存过哪些资料、当前问题需要哪些证据”。
如果继续加入真正的 Personal Memory,更稳妥的做法不是把用户偏好、长期项目约束、当前任务状态和 PDF Chunk 全塞进一个索引,而是把它们拆开:原始资料和 Chunk 属于知识库;用户明确偏好和长期项目约束进入独立 Memory Store;当前任务进度进入 Session / Task State;登录状态、订阅等级、设备信息等实时业务事实仍从业务 source of truth 获取;最终 Context Assembly 再按任务决定是否同时读取 Memory 和 RAG。
这个实现经验说明,Memory vs RAG 不是术语争论,而是数据生命周期、权威性和权限边界问题。即使两个数据面共用了 SQLite、FTS、Embedding 或向量索引,也不代表它们应该共享写入策略、删除策略和权威级别。
选型决策表:这条数据到底放哪里
| 例子 | 应该放哪里 | 原因 |
|---|---|---|
| 当前对话最近 10 条消息 | Session / Thread State | 只服务当前会话连续性 |
| 工作流已完成 4/7 个节点 | State + Checkpoint | 需要恢复执行 |
| 用户明确要求“以后默认中文回答” | Long-term User Memory | 跨会话稳定偏好 |
| 某仓库禁止使用 Swift | Project-scoped Memory | 跨会话但只对项目有效 |
| API 官方文档 | Knowledge Base + RAG | 外部知识证据 |
| 上次部署失败因为环境变量缺失 | Episodic / Experience Memory | 未来相似任务可能复用 |
| 第三方 API 本次返回的 500 原始日志 | Trace / Audit | 默认不应成为长期行为约束 |
| 当前账号订阅等级 | 业务数据库实时查询 | 权威事实应从 source of truth 读取 |
| “用户可能喜欢极简设计”的模型猜测 | 默认不写,或低权威候选 | 推断不能冒充明确偏好 |
这张表比“Memory 用 Redis 还是向量库”更早,也更重要。
一套更稳妥的 Agent 上下文组装顺序
请求进入 Agent 后,可以按下面的顺序构建 Context:
1. identity / authorization
2. current invocation inputs
3. session/thread state
4. active checkpoint state
5. deterministic user/project constraints
6. optional long-term memory retrieval
7. RAG / external knowledge retrieval
8. tool results / live system facts
9. prompt budget + conflict resolution
10. model inference
其中第 6、7 步不是固定都执行,而是按任务需要打开。
这种分层有一个直接收益:当答案错了,你可以定位“是知识证据错、Memory 过期、State 没恢复、还是权限过滤错”,而不是面对一个匿名的向量检索结果集猜原因。
对 LangGraph、Google ADK 和自研 Agent 怎么映射
LangGraph
可以粗略映射为:
- graph state + checkpointer → thread-scoped short-term memory / durable execution;
- Store → cross-thread long-term memory;
- 外部 retriever / vector store → RAG 或 Memory Retrieval 的具体实现。
这不是说 Store 就自动解决记忆治理,身份、写入策略、冲突和删除仍然由应用负责。
Google ADK
可以粗略映射为:
- Session → 一次 conversation thread;
- State → Session 内动态状态;
- MemoryService → 跨 Session 的可搜索信息;
- RAG Memory / Memory Bank → 不同长期记忆实现路径。
ADK 官方文档本身就展示了一个很有价值的事实:同样叫 Memory,不同实现也可能是“完整会话检索”或“抽取后长期记忆”,所以应用层必须明确自己需要的是哪一种。
自研 Agent
不要从“我要一个 Memory 模块”开始。
先定义:
Data class
→ scope
→ authority
→ source of truth
→ write policy
→ retention
→ read policy
→ conflict policy
→ delete policy
→ evaluation
然后再选数据库和框架。
最后:Memory 的核心不是让 Agent“记得更多”
真正好的 Agent Memory 不是无限增加历史,而是让正确的信息在正确的作用域、正确的时间、以正确的权威级别影响下一次行动,并且在它失效时能够退出。
所以一个生产系统里:
- RAG 负责“现在需要什么外部证据”;
- Session State 负责“当前会话正在发生什么”;
- Checkpoint 负责“中断后怎么恢复”;
- Long-term Memory 负责“哪些历史信息以后仍应影响行为”;
- Knowledge Base 负责“可检索的知识资产是什么”;
- Audit / Trace 负责“发生过什么,如何追溯”。
把这几个概念分开以后,存储选型反而是后面比较容易的一步。
延伸阅读
- AI Agent Memory Retrieval 实战:混合检索、重排、时效性与冲突消解
- Funes Agent Memory 实测:长期记忆召回、旧记忆污染与本地隐私边界
- Google ADK delete_session 为什么删不掉长期 Memory?
- Context Engineering:Retrieval、Tool Search、Memory 怎么降低上下文成本
- AI Agent RAG Integration
- AI Agent Tool Authorization:Policy Gate、HITL 与逐调用权限控制
继续按生产级 LangGraph 路线读,不再重复看泛入门
这一类文章统一沉淀到 LangGraph 专题页,按状态隔离、Checkpointer、HITL、失败恢复、Observability、Supervisor/Worker、Subgraph 和 Memory 顺序阅读。
下一步:继续处理状态与恢复
完整专题路径 →从当前问题继续走到 State、Checkpoint、Resume 或失败恢复边界,避免只修表面症状。
参与讨论
问题、验证与勘误
登录后可发表评论。所有新评论先进入审核;审核期间仅评论者本人和管理员可见,通过后才公开。