
Agent 多层记忆架构:从向量召回到可治理的长期状态
Agent 记忆模块在 2026 年出现了一个明显变化:大家不再只讨论“要不要长期记忆”,而是在讨论记忆如何分层、如何写入、如何更新、如何删除、如何避免错误记忆污染后续决策。
从近期资料看,成熟路线大致分成四类:
- LangGraph / LangMem:把短期记忆和长期记忆拆开,短期用 thread state + checkpointer,长期用 namespace + store。
- Mem0:把记忆做成可挂载到任意 Agent 的 memory engine,重点是 add / search / update / history / rerank。
- Zep / Graphiti:把长期记忆转成带时间、来源和实体关系的 temporal knowledge graph。
- Letta / MemGPT:把记忆放进有状态 Agent 运行时,强调 agent 自己维护 memory blocks 和长期状态。
更前沿的论文又补上了几个关键方向:A-MEM 强调动态链接和记忆演化,MemMachine 强调保留原始情景证据,MemGate 把 memory search 视为安全边界,ProjectMem 把记忆变成 coding agent 的治理层。这些方向合在一起,指向一个很明确的工程结论:
生产级 Agent 记忆不应该只有一个向量库。它应该是一个带生命周期的多层状态系统。
最近值得关注的开源路线
| 方案 | 当前定位 | 适合场景 | 主要风险 |
|---|---|---|---|
| LangGraph Store | 框架级状态与记忆抽象 | 已经用 LangGraph 构建 Agent | 需要自己设计写入、合并、评测 |
| Mem0 | 通用记忆服务 / SDK | 快速接入用户偏好、个人助手、客服 | 抽取和更新策略仍要按业务调 |
| Graphiti / Zep | 时间感知知识图谱 | 企业实体关系、跨会话事实变更 | 工程复杂度高于向量库 |
| Letta | 有状态 Agent runtime | 想直接使用带 memory blocks 的 Agent 平台 | 和自有 Agent loop 耦合更深 |
| A-MEM | 动态笔记网络 | 研究型、知识演化型 Agent | 生产治理能力需要补齐 |
| ProjectMem | 本地事件日志 + 决策门控 | coding agent、项目长期上下文 | 领域偏工程项目,不是通用个人记忆 |
| MemGate | 检索准入门控 | 高隐私、高风险工具调用 | 仍是较新的研究方向 |
这些项目的共同点不是“都用了 embedding”,而是都在试图解决同一个问题:长期记忆一旦进入 prompt,就不再只是信息,而会变成控制信号。
这就是为什么简单的 top-k 相似度召回会越来越危险。一个记忆和当前问题语义相近,并不等于它应该影响当前回答。比如用户在私人场景说过“我喜欢省事”,不应该在企业审批、医疗建议、金融操作里影响工具参数。
推荐的多层记忆架构
我建议把 Agent 记忆拆成六层,而不是把所有内容塞进一个 memories 表。
这套结构里,事件日志是唯一真源。其他层都是从事件日志投影出来的视图:
- 情景记忆回答“发生过什么”;
- 语义记忆回答“现在认为用户/项目/实体是什么状态”;
- 图谱记忆回答“谁和谁有什么关系,这个关系从什么时候到什么时候有效”;
- 程序性记忆回答“下次遇到类似任务应该怎么做”;
- 准入门控回答“这条记忆此刻能不能进入上下文”。
这个设计看起来比一个向量表重,但它有三个好处。
第一,更新可追溯。语义层写错了,可以回放事件日志重新投影,而不是在一堆摘要里找不到证据。
第二,删除可执行。用户要求忘记某件事时,可以删除或封存源事件,再重建投影,避免“表面删了,摘要里还残留”。
第三,评测可拆解。回答错了,可以判断是写入错、检索错、准入错,还是模型推理错。
每一层具体存什么
| 层 | 存储对象 | 推荐后端 | 写入方式 |
|---|---|---|---|
| 工作记忆 | 当前消息、工具输出、临时目标、上传文件引用 | Redis / Postgres checkpoint | 每个 graph step 后保存 |
| 事件日志 | 原始对话片段、工具调用、用户确认、外部事件 | Postgres append-only table / object storage | 同步写入,不做 LLM 改写 |
| 情景记忆 | session 摘要、任务轨迹、失败尝试、证据窗口 | Postgres + pgvector / Qdrant | 后台分段、摘要、索引 |
| 语义记忆 | 用户偏好、项目事实、账号状态、长期约束 | JSONB + schema / Mem0 | hot path 或后台 upsert |
| 图谱记忆 | 实体、关系、来源、valid_from / valid_to | Graphiti / Neo4j / Kuzu | 后台实体解析和关系合并 |
| 程序性记忆 | 系统提示、工具策略、few-shot、操作 playbook | Git / DB versioned prompt store | 人审或评测通过后更新 |
| 治理层 | consent、TTL、敏感标签、删除记录、审计历史 | Postgres policy tables | 所有写入和检索前后都检查 |
最容易犯的错误是把“语义记忆”和“语义搜索”混为一谈。语义记忆是事实或偏好的长期状态,语义搜索只是找相似内容的方法。一个系统可以用 semantic memory,但不一定只靠 semantic search。
对话中如何更新记忆
生产系统里,记忆写入最好拆成两个通道。
热路径写入适合少量、高确定性、用户刚刚显式确认的记忆。比如用户说“以后默认用中文回答”,Agent 可以立即写入偏好,并告诉用户已记录。
后台写入适合长对话总结、任务轨迹、实体关系、失败经验。它不阻塞主回答,允许更复杂的抽取、去重、合并和人工复核。
一个可落地的写入状态机可以这样设计:
observed
-> candidate
-> active
-> superseded
-> expired
-> deleted
candidate
-> pending_review
-> rejected
每条记忆至少要有这些字段:
{
"id": "mem_...",
"type": "semantic.preference",
"subject": "user:alice",
"content": "用户偏好简洁、直接的中文回答",
"source_event_ids": ["evt_001", "evt_002"],
"confidence": 0.86,
"salience": 0.72,
"valid_from": "2026-06-16",
"valid_to": null,
"sensitivity": "normal",
"write_policy": "auto",
"status": "active"
}
写入不是“抽到就存”,而应该有一个评分函数:
write_score =
future_utility
* confidence
* stability
* user_confirmed_weight
- privacy_risk
- volatility
- duplicate_penalty
- token_cost_penalty
低分内容只进事件日志,不进入长期投影。比如“用户今天心情不好”可以留在情景层,但不应该永久写成“用户是悲观的人”。
更新算法:不是 overwrite,而是 reconcile
长期记忆真正难的是更新,而不是新增。
用户今天说“我不吃辣”,三个月后说“现在可以吃一点微辣”,系统不能简单保留两条冲突事实,也不能粗暴覆盖掉来源。更好的做法是:
- 找到同 subject、同 schema、同领域的候选旧记忆;
- 判断关系:补充、修正、冲突、过期、重复;
- 如果是冲突,关闭旧记忆的
valid_to,写入新记忆; - 保留来源事件,支持回溯和解释;
- 对高风险类别进入人工复核。
这也是图谱方案的优势。Graphiti 这类 temporal graph 不是只存“用户喜欢 A”,而是可以表达:
user -> prefers -> spicy_food- 来源是哪几次对话;
- 从什么时候开始有效;
- 什么时候被新事实取代;
- 哪个实体合并到了哪个实体。
向量库可以快速召回相似片段,但它不天然理解“事实已经失效”。生产系统必须额外补这一层。
检索:相似度之后还要做准入
记忆检索至少应该有四步:
- 路由:判断该查哪些 namespace,例如 user profile、project facts、task episodes、tool playbooks。
- 召回:向量、关键词、时间窗口、图谱邻居同时召回。
- 重排:用 reranker 或规则把候选按当前任务重新排序。
- 准入:判断这条记忆是否允许进入当前上下文。
准入是现在最容易被低估的层。MemGate 这类研究的核心提醒是:memory search 是信任边界,不是普通信息检索。一个候选记忆应该同时满足:
- 与当前任务相关;
- 没有跨域泄露;
- 没有被旧事实取代;
- 不会改变高风险工具参数;
- 不会把用户偏见注入需要客观判断的回答;
- 用户或组织策略允许使用。
所以我更推荐把 prompt 里的记忆做成“memory packet”,而不是散乱拼接:
Relevant memory packet:
- fact: 用户偏好中文、简洁回答
source: user_profile
confidence: high
scope: communication_style
expires: none
- episode: 上次在项目 X 中拒绝了全量重构方案
source: task_episode
confidence: medium
scope: project:X
reason_for_use: 当前问题仍属于 project:X
这样模型更容易理解记忆的边界,也方便在日志里审计“为什么这条记忆被用了”。
一个能落地的生产蓝图
如果从零开始做,我会按三阶段落地。
第 1 阶段:先做可审计的双层记忆
目标是两周内上线,而不是一开始就做图谱。
- Postgres 存事件日志;
- LangGraph checkpointer 存 thread state;
- Postgres JSONB 存结构化 profile;
- pgvector 或 Qdrant 存情景片段 embedding;
- 后台 worker 从事件日志抽取候选记忆;
- 所有写入保留
source_event_ids; - 管理后台能搜索、禁用、删除记忆。
这一步已经可以覆盖大部分客服、助手、内部工具场景。
第 2 阶段:引入多投影和更新状态机
当用户、项目、实体关系开始变复杂,再加:
- schema 化语义记忆;
- duplicate / contradict / supplement 判断;
- valid time;
- namespace 级权限;
- reranker;
- shadow evaluation。
这一步的核心不是“召回更多”,而是减少错误写入和错误准入。
第 3 阶段:引入图谱和程序性记忆
只有当业务真的需要跨实体、跨时间、多跳推理时,再接 Graphiti / Zep。
程序性记忆更要谨慎。让 Agent 自动改系统提示或工具策略听起来很诱人,但这相当于让它改变自己的行为规则。生产里建议:
- 先把失败案例写成 episodic memory;
- 离线评测通过后再生成 playbook;
- playbook 进入版本库;
- 高风险工具策略必须人工审批。
技术选型建议
| 你的目标 | 推荐起点 | 原因 |
|---|---|---|
| 快速给现有产品加用户偏好记忆 | Mem0 OSS 或平台版 | SDK 简单,add/search/update/history 都有现成抽象 |
| 已经用 LangGraph 搭 Agent | LangGraph Store + 自写 writer | 和 graph state / namespace 集成自然 |
| 企业知识、客户关系、事实随时间变化 | Graphiti / Zep | temporal graph 更适合实体关系和历史查询 |
| 想直接使用有状态 Agent runtime | Letta | memory blocks 和 agent state 是核心设计 |
| coding agent 记住项目决策和失败尝试 | ProjectMem 思路 + MCP | 本地事件日志和 pre-action gate 很实用 |
| 高隐私个人助手 | 自建事件日志 + 准入门控 | 需要自己控制删除、审计和跨域隔离 |
我的判断是:不要从图谱开始,也不要只停在向量库。
最稳的路径是先做事件日志和语义/情景双投影;当事实更新和实体关系成为瓶颈,再加 temporal graph;当错误记忆开始影响工具调用,再加准入门控和人工复核。
如何评测和优化
Agent 记忆的评测不能只看最终回答是否正确。至少要拆成五类指标:
| 指标 | 看什么 | 常见优化 |
|---|---|---|
| 写入质量 | 该记的是否记了,不该记的是否没记 | schema、阈值、用户确认、候选去重 |
| 更新质量 | 冲突事实是否正确关闭旧版本 | valid time、reconcile prompt、实体解析 |
| 检索质量 | 相关证据是否被召回 | hybrid retrieval、reranker、query rewrite |
| 准入质量 | 不该进入上下文的记忆是否被拦住 | domain filter、policy gate、MemGate 类方法 |
| 运行成本 | 延迟、token、存储、人工审核成本 | hot path/后台拆分、top-k 动态调整 |
线上不要直接打开“自动记忆”。更好的发布方式是:
- shadow writer:只生成候选,不影响回答;
- 人审一批候选,调阈值和 schema;
- 灰度打开低风险记忆;
- 对比 memory-on / memory-off 的回答质量、token 成本和投诉率;
- 再开放自动更新和跨会话调用。
近期 Mem0 的论文和文档都强调了 latency、token cost、reranker、history 的工程价值;Zep / Graphiti 强调时间图谱和来源;MemGate 则提醒我们相似度不是准入许可。这三类观点合在一起,才像一个完整的生产系统。
结论
多层记忆架构的核心不是“多存几份数据”,而是把不同问题放在不同层解决:
- context window 解决当前任务;
- event log 解决证据和回放;
- episodic memory 解决历史经验;
- semantic memory 解决长期事实;
- graph memory 解决实体关系和时间;
- procedural memory 解决行为改进;
- policy gate 解决安全、隐私和边界。
一个可靠的 Agent 不应该什么都记,也不应该什么都忘。真正有价值的是:知道哪些信息值得保留,什么时候更新,什么时候不该使用,以及出错后如何回滚。
这才是 Agent 记忆从 demo 走向生产的分水岭。
参考资料
- LangGraph Memory Overview: https://docs.langchain.com/oss/python/concepts/memory
- Mem0 Open Source Overview: https://docs.mem0.ai/open-source/overview
- Mem0 Python SDK Quickstart: https://docs.mem0.ai/open-source/python-quickstart
- Mem0 Reranker-Enhanced Search: https://docs.mem0.ai/open-source/features/reranker-search
- Mem0 Async Memory: https://docs.mem0.ai/open-source/features/async-memory
- Mem0 paper: https://arxiv.org/abs/2504.19413
- Graphiti GitHub: https://github.com/getzep/graphiti
- Zep paper: https://arxiv.org/abs/2501.13956
- Letta GitHub: https://github.com/letta-ai/letta
- A-MEM paper: https://arxiv.org/abs/2502.12110
- MemMachine paper: https://arxiv.org/abs/2604.04853
- MemGate paper: https://arxiv.org/abs/2606.06054
- ProjectMem paper: https://arxiv.org/abs/2606.12329
- CoALA paper: https://arxiv.org/abs/2309.02427