Agent Memory:短期状态、长期记忆与检索更新
从一次跨会话写作任务出发,拆解 Agent 怎样保存运行状态、筛选长期记忆、检索相关证据,并在事实变化时更新或遗忘。
用户在第一次合作时说:“这个博客里的文章写完后直接提交并推送。”一周后,他又补充:“涉及发布配置时先让我确认。”下一次任务开始时,Agent 应该记住哪一句,怎样知道它只适用于这个博客,又怎样避免旧规则覆盖新规则?
把历史消息全部塞回模型并不能稳定解决这个问题。随着对话增长,成本和延迟会上升,早期事实会被无关内容干扰;若只保存一份摘要,条件、时间和来源又可能在压缩中消失。可用的 Memory 是一条完整的数据路径:它要决定保存什么,用什么结构保存,何时召回,如何处理冲突,以及怎样删除已经失效的内容。
本文回答一个工程问题:怎样为 Agent 设计一套可恢复、可检索、会更新并且能够评测的记忆系统?
事实层主要来自 LangGraph Memory 官方文档、MemGPT、Generative Agents、LongMemEval 与 Mem0。论文结果只说明各自实验设置中的表现,不直接代表任意产品环境。本文的 Schema、版本策略和上线方法属于工程设计建议。
先看结论
Agent 至少需要区分两种状态。短期状态属于一个 Thread 或任务,保存消息、计划、工具结果、审批和检查点,用于下一步推理与中断恢复;长期记忆跨 Thread 存在,保存经过筛选的用户偏好、稳定事实和可复用经验。两者可以使用同一数据库,却不能共享一套生命周期。
Memory 也不等于“给聊天记录做向量检索”。原始事件日志负责追溯,结构化状态负责恢复,长期 Memory 负责在未来任务中提供少量相关证据。向量相似度只是召回手段之一,时间、实体、作用域、权限和有效期往往更重要。
每条长期记忆都应带上来源、适用范围、写入时间、有效期、置信度和版本关系。没有这些元数据,系统无法回答“这条规则来自谁”“是否已经过期”“新旧说法冲突时听谁的”。
Memory 的质量需要沿整条链路评测。只测检索 Recall,会漏掉错误写入、过度记忆、更新失败和“虽然召回了,但模型没有正确使用”等问题。
一、先把五种容易混淆的东西分开
“模型记得”在产品界面上是一个感觉,在系统里却可能来自完全不同的机制。设计之前先给每种信息指定所有者。
| 名称 | 保存什么 | 典型作用域 | 用途与常见误区 |
|---|---|---|---|
| 模型 Context | 本次推理实际可见的消息和资料 | 一次模型调用 | 用于生成下一步动作;窗口大不等于长期记忆 |
| Thread State | 消息、任务变量、计划、工具结果、审批 | 一个 Thread | 用于多步执行和恢复;不要把所有状态都格式化成 Prompt 文本 |
| Event Log | 用户消息、模型输出、工具调用和副作用事件 | Thread 或任务历史 | 用于审计、回放和调试;有日志不等于模型能直接使用 |
| Long-term Memory | 筛选后的事实、偏好和经验 | 用户、组织、项目或 Agent | 用于跨会话召回;不能把整段聊天切块后都称为记忆 |
| Knowledge / RAG | 产品文档、代码、业务资料等外部知识 | 知识域 | 用于回答领域事实;不要把用户状态混进公共知识库 |
Context 是一次调用的输入视图。Memory 存在于调用之外,只有被读取并装配进 Context 后才会影响模型。一个事实已经写入数据库,不代表当前推理看得到它;一个事实出现在当前 Context,也不代表系统以后还能找回来。
Thread State 与长期记忆的界线由作用域决定。某篇文章已经完成到第六节、构建进程的 PID、尚未解决的测试错误,只服务当前任务。用户偏好简洁表达、这个仓库使用 Astro、技术长文提交前必须跑审计,可能在未来 Thread 中继续有用。
Event Log 是最完整的证据,但通常太长,也不适合直接检索。长期记忆可以从日志中提炼,却不应覆盖原始来源。发生争议时,系统需要回到当时的消息或工具结果,而不是把模型生成的摘要当作唯一事实。
上一篇文章讨论的 Skill 保存“某类任务怎样完成”,Memory 保存“当前用户、项目或过去任务有什么事实值得以后使用”。一句“personal-blog 使用 Astro”适合记忆;研究、写作、配图、审计、构建、页面检查和提交组成的完整过程适合 Skill。
两者之间允许升级:Agent 多次观察到同一种成功做法,可以把它标为候选经验,经过回放和人工审核后发布成 Skill。未经验证的一次轨迹不应自动变成流程规则,否则一次偶然成功会固化成长期错误。
Reflection 是生成候选洞察的过程,Memory 是保存和召回状态的系统。Generative Agents 会从经验流中生成更高层的 reflection,再把 reflection 作为新记录参与检索。这个设计说明两者能够组合,也说明它们不能互相替代:反思得出一句结论,不代表结论可靠;数据库保存了一条记录,也不代表它经过反思。
二、短期状态:让任务可以继续,而不是重新猜一遍
LangGraph 的定义很清楚:短期记忆是 Thread 范围内的 State,通过 Checkpointer 持久化,在每一步开始时读取,在调用或步骤完成时更新。这里的“短期”描述作用域,不等于只活几分钟。一个暂停三天的 Thread 仍然可以恢复,只要检查点还在。
短期状态不应只有消息数组。长任务至少还需要目标、当前计划、已完成步骤、待处理工具调用、外部副作用、用户审批、生成产物和验收结果。否则系统恢复时只能让模型从聊天文字里推断真实状态。
type ThreadState = {
threadId: string;
goal: string;
messages: Message[];
plan: PlanStep[];
artifacts: Array<{ path: string; revision?: string }>;
toolCalls: Array<{ id: string; status: "pending" | "done" | "failed" }>;
approvals: ApprovalDecision[];
checkpointVersion: number;
};
这份结构仍然不是事实来源的全集。文件内容属于工作区,远端 PR 状态属于代码托管平台,支付结果属于支付系统。State 保存标识、观察结果和续接位置;恢复后应重新读取可能变化的外部状态。日志里写着“构建通过”,只能证明当时通过,无法证明用户随后改过文件的工作区仍然通过。
Checkpoint 保存可恢复状态,Compact 控制下一次推理要带多少内容。前者强调持久性和一致性,后者是有损的信息选择。把两者合成一个“对话摘要”会制造危险:摘要遗漏工具副作用后,Agent 可能重复执行;摘要生成失败时,系统甚至不知道应该从哪个边界恢复。
可靠做法是先提交结构化检查点,再生成 Context 视图。Context 可以裁剪旧日志、只保留影响后续决策的工具结果并压缩讨论;任务状态和幂等键仍由程序保存。压缩失败不应破坏原检查点。
即使模型支持很长的 Context,消息历史也不应无限增长。旧消息会提高延迟和成本,并让无关内容干扰当前判断。可以按信息性质处理:可重新读取的长日志只保留路径和错误摘要;用户明确决策进入结构化状态;最近交互保留原文;早期讨论生成带来源边界的摘要。
短期状态的验收问题很具体:进程中断后能否从同一步恢复,工具调用会不会重复,审批是否仍然有效,工作区变化能否被重新观察。答不出这些问题,聊天看起来再连贯也只是表面连续。
三、长期记忆:按用途分,不按存储技术分
长期记忆最常见的分类来自认知科学类比。LangGraph 文档将它分为 semantic、episodic 和 procedural。这个分类适合作为设计起点,但工程实现还要把作用域与生命周期放进去。
Semantic memory 保存事实与偏好
Semantic memory 回答“现在已知什么”。例如用户倾向中文技术长文、仓库默认分支是 main、文章图片存放在 public/images/posts/。其中有些是个人偏好,有些是项目事实,不能放进同一全局 Profile。
事实最好保持原子性,同时带上限定条件。“用户喜欢自动推送”过于宽泛;“在 personal-blog 的文章任务中,构建和检查通过后直接提交并推送”包含对象、条件和动作,更不容易误用到公司仓库。
Episodic memory 保存发生过的经历
Episodic memory 回答“以前遇到类似情况时发生了什么”。一次构建因本地端口权限失败、最后通过提升权限启动预览,是带输入、动作和结果的事件。未来遇到同类错误时,这段经历可以提供诊断线索。
原始轨迹通常很长。适合检索的 episode 应保留任务特征、关键动作、失败原因、修复、验收结果和源事件引用。只存最终总结会失去证据,只存完整轨迹又会让检索结果难以阅读。
Procedural memory 应谨慎对待
Procedural memory 描述做事规则。模型权重、系统提示、Agent 代码和 Skills 都可能承载它。运行时可以从用户反馈中生成规则候选,但不建议让 Agent 在没有版本和审核的情况下直接改写高权限流程。
对个人助手,一条低风险表达偏好可以立即生效;对部署、付款和数据删除流程,程序规则仍应由代码、Policy 或经审核的 Skill 管理。把 procedural memory 放进向量库,并让相似度决定是否加载,容易漏掉必须执行的安全约束。
一个实用的四层模型
落地时可以把信息分成四层:活动 Context、Thread State、可检索 Memory、原始 Archive。Context 最快也最贵,Archive 最完整却最慢。每层都保留进入下一层的地址,系统便能先读少量摘要,再按需回到原始证据。
MemGPT把这种做法类比操作系统的分层存储:有限 Context 像主存,外部存储保存更大的信息集合,运行时负责换入换出。类比的价值在资源管理,不应继续外推成“模型拥有像人一样的记忆”。模型仍只对当前输入做推理,哪条信息被换入由外部控制逻辑决定。
四、一条记忆从候选到生效,要经过什么
长期记忆是一条读写闭环,写入与检索只是中间两段。
系统先从用户消息、工具结果或任务轨迹中产生候选;再判断内容是否稳定、未来是否有用、是否允许保存;随后规范化为带作用域与来源的记录。下一次任务到来时,检索层组合语义、关键词、过滤和时间信号,重排少量候选并装配进 Context。任务结果又会形成反馈:记忆被采用、被用户纠正、因过期失效,或因为长期无用而删除。
写入前先回答四个问题。第一,它在未来是否还能帮助决策?“用户今天喝了咖啡”通常没有必要保存;“用户对咖啡因过敏”在健康相关助手中可能重要。价值取决于产品目标,不能靠通用 Prompt 一次决定。
第二,它的作用域是什么?用户偏好、组织政策、项目约束和当前任务状态属于不同 Namespace。作用域过宽会串线,过窄又无法跨会话复用。
第三,来源是否足够可信?用户明确陈述、工具读取的仓库配置、模型从对话推断出的偏好,证据等级不同。推断可以作为低置信候选,不应伪装成确认事实。
第四,保存是否合法且必要?个人身份、健康、凭据和公司数据可能受隐私政策限制。系统应在进入模型提取步骤前先做数据分类与访问控制,不能等写进向量库后再补权限。
LangGraph Memory 文档区分 hot path 和 background 两种写入方式。热路径在当前交互中提取并写入,新信息可立即使用,也容易向用户展示;代价是增加延迟,并让主 Agent 同时承担任务执行和记忆管理。
后台写入把提取、去重和合并放到异步任务中,主链路更快,也便于批量观察一段会话后再决定。缺点是新记忆不会立刻出现在其他 Thread 中,还需要定义触发时机和一致性语义。
实际系统可以混合使用:用户明确说“记住以后文章直接推送”时同步保存;大量任务轨迹在完成后异步提炼;高风险规则只生成待审核候选。每种路径都应记录 writer 和 write_reason,方便追踪是谁做出的保存决定。
五、怎样表示:Profile、Collection、Episode 与 Graph
存储结构会直接影响更新和召回。没有一种表示适合所有 Memory。
| 表示 | 优点 | 代价 | 适合内容 |
|---|---|---|---|
| Profile 文档 | 一次读取即可得到完整画像 | 文档越大越难可靠更新,字段冲突会互相影响 | 稳定、字段明确的用户或项目画像 |
| 原子 Memory Collection | 易追加、易单条更新,检索粒度细 | 需要去重、合并和跨记录推理 | 偏好、事实、约束 |
| Episode / Trajectory | 保留输入、动作、结果和因果线索 | 内容长,索引与摘要成本高 | 故障经验、成功案例、Few-shot |
| Graph | 显式保存实体、关系与时间变化 | 构建和维护复杂,错误关系会扩散 | 多实体关系、跨记录推理 |
LangGraph 文档也比较了 Profile 与 Collection:Profile 容易整体提供上下文,但随规模增长更难更新;Collection 中单条记录更窄,更容易新增,却把去重、删除和检索复杂度留给系统。
记录 Schema 要先于向量索引。向量只解决近似相似度,无法代替业务字段。一条可维护的记忆至少需要内容、类型、作用域、来源、时间、状态和版本关系。
{
"id": "mem_01K...",
"kind": "preference",
"subject": "user_42",
"scope": { "project": "personal-blog", "task": "article" },
"content": "文章完成全部检查后,直接提交并推送到 origin/main",
"source": { "thread_id": "thr_9", "message_id": "msg_31" },
"valid_from": "2026-09-29T10:00:00+08:00",
"valid_to": null,
"confidence": 1.0,
"status": "active",
"supersedes": null,
"tags": ["git", "publishing"]
}
created_at 与 valid_from 不一定相同。系统今天才从历史记录中恢复一条上周已经生效的规则,两者就会不同。对频繁变化的事实,保留这两个时间能避免“数据库最新写入的就是现实最新状态”这一错误。
原文、摘要和索引键各有职责。Memory value 保存希望提供给模型的内容;索引键帮助找到它;source 指向证据。LongMemEval 的实验把长期记忆分成 indexing、retrieval、reading 三个阶段,并发现记录粒度和查询扩展会显著影响结果。过度压缩成孤立事实可能丢失对话上下文,整段 Session 又会带入大量噪声。
一种折中是保存轮次或事件级原文,同时生成事实化索引键和短摘要。召回先用扩展键找候选,读取时带回足够的相邻上下文。摘要可重建,原始来源不可伪造,两者不要覆盖彼此。
六、检索:相似不代表相关,更不代表应当使用
用户说“继续下一篇”时,语义搜索很难直接命中“文章完成后自动推送”。后者没有“继续”的相似词,却会在任务收尾时影响行为。Memory 检索必须结合当前阶段、作用域和任务意图。
一个实用召回器可以并行产生候选:按用户、组织和项目过滤;用关键词找精确名称;用 Embedding 找语义近邻;按实体和关系查关联事实;按时间查最近更新。随后统一重排。
score = 语义相关性
+ 作用域匹配
+ 时间有效性
+ 来源可信度
+ 任务阶段匹配
+ 历史使用收益
- 冲突惩罚
- 过期惩罚
多数系统无需一开始就训练复杂 Ranker。早期版本用过滤规则加简单加权就够了,但要把“能否访问”“是否有效”和“有多相似”分开。权限过滤应在检索前执行,不能先从所有租户取 Top K 再让模型忽略不该看的结果。
检索 Query 不应只复制最后一条用户消息,还要加入任务上下文。它可以包含标准化意图、当前项目、目标实体、任务阶段和时间范围。LongMemEval 报告的设计实验中,time-aware query expansion 能改善时间相关问题,说明“何时发生”需要进入检索表达。
对“继续下一篇”,Harness 知道当前项目是 personal-blog、任务类型是文章、阶段从选题进入写作。这个结构化 Context 会召回写作偏好、项目约束和上一篇文章的完成状态,而不是在全局记忆里搜索“下一篇”三个字。
读取预算会影响最终效果。召回二十条 Memory 不等于把二十条都塞进 Prompt。装配层需要去重、合并同一实体的版本、标出冲突,并在 Token 预算内选择证据。每条记录最好显示来源和时间,让模型能够说“我找到两条相互冲突的要求,需要确认”。
检索结果也不应混进系统指令。Memory 是可变数据,优先级低于系统策略和当前用户明确指令。把历史用户内容拼成高优先级 Prompt,会放大 Prompt Injection:旧网页或工具结果中的恶意文本可能在未来会话里获得指令地位。
七、更新、冲突和遗忘比追加更难
只支持 add 的 Memory 最终一定会堆出矛盾。用户偏好会改变,项目依赖会升级,组织政策也会修订。更新需要保留历史,又要保证默认召回只看到当前有效版本。
Upsert 之前先识别实体与关系。新候选进入时,系统要判断它是在新增事实、补充旧事实、纠正旧事实,还是撤销旧事实。“我现在更喜欢简短回答”可能覆盖原偏好;“代码 Review 时请简短,架构文章仍然详细”是在原偏好上增加作用域。
直接用文本相似度判断重复不够可靠。两句话可能措辞相近却有效期不同,也可能措辞不同却描述同一属性。系统需要结合 subject + predicate + scope 查找已有记录,再让规则或模型给出 insert / merge / supersede / delete / ignore 决策。
新规则替代旧规则时,应保留版本,不把旧记录静默改掉。可以把旧记录标成 superseded,设置 valid_to,并让新记录的 supersedes 指向它。默认检索只返回 active 版本,审计和时间问题仍能看到历史。
对于外部系统事实,最好的做法常常是不写长期 Memory,而是保存“去哪里查”。分支名称、价格、权限和服务状态变化频繁,实时工具比陈旧副本可靠。Memory 可保存仓库地址和查询方式,执行前再读取真实状态。
遗忘也有不同语义。删除可以是停止召回、到期失效、逻辑删除或物理擦除。四者服务不同要求。用户说“以后不要再用这条偏好”通常需要立即停止召回;合规删除还可能要求清除原文、Embedding、缓存、备份索引和派生摘要。
因此每条记忆必须能追踪派生关系。若一条聊天消息生成了 Profile 字段、三个原子事实和一个向量,删除请求要能定位所有副本。没有数据血缘,“已经忘记”只是界面文案。
八、贯穿案例:博客 Agent 怎样跨会话继续工作
初始条件是一个技术博客仓库。用户希望文章写完后自动提交推送,但不希望这一偏好影响其他仓库。一次文章任务在构建后中断,第二天新 Thread 收到“继续吧”。
会话 A:写入候选
用户明确提出长期偏好。写入器产生一条 preference,主体是当前用户,Scope 限定 personal-blog 和 article task,来源指向原消息。因为表达明确,置信度为 1;因为涉及 Git 写操作,Memory 只授权“按流程行动”,真实 push 仍由执行权限和仓库凭据控制。
文章任务的计划、已修改文件和构建状态进入 Thread State。构建日志留在事件记录或文件中,只把退出码和日志位置写入检查点。它们不会进入长期用户 Profile。
会话 B:从检查点恢复
若继续同一个 Thread,系统先加载 Checkpoint,重新检查工作区和 Git 状态,再从未完成步骤推进。自动推送偏好不需要通过语义搜索碰运气,因为任务类型和项目 Scope 已知,可以在收尾阶段按结构化条件读取。
若用户新建 Thread,系统没有旧计划,只能从长期记忆知道项目习惯。它仍需扫描仓库和已有文章,不能把上次的“构建通过”当成今天的验收证据。
会话 C:用户修改规则
后来用户说:“文章仍然直接推送,但涉及部署配置时先确认。”写入器不应删除自动推送规则,而应新增一个更具体的例外。检索时,具体 Scope 优先于通用 Scope;任务同时修改部署配置,就返回确认规则,否则沿用自动推送。
这个例子暴露了四个责任:Memory 保存偏好,Thread State 保存进度,Git 和文件系统保存真实产物,权限系统决定是否允许 push。把四者都塞进一段聊天摘要,会让恢复、更新和安全边界一起变模糊。
九、从最小实现到可上线系统
第一版不需要知识图谱和多个模型。选择一个真实任务,先建立可观察的读写闭环。
最小实现可以让短期状态使用数据库 Checkpointer,按 thread_id 保存结构化 State。长期记忆使用一张支持 Namespace、JSON 字段和全文检索的表。写入只接受用户明确要求记住的内容,读取先做 Scope 过滤,再用关键词或简单向量搜索。
create table agent_memory (
id text primary key,
namespace text not null,
kind text not null,
subject text not null,
content text not null,
metadata jsonb not null,
status text not null,
valid_from timestamptz not null,
valid_to timestamptz,
source_event_id text not null,
embedding vector(1536)
);
读取 API 不直接返回拼好的 Prompt,而是返回结构化记录。Context Builder 根据当前任务选择展示格式,保留 id、来源和时间,便于模型引用或发起纠错。
当明确写入覆盖不了需求,第二阶段再补上候选提取器。提取输出固定 Schema,程序验证 Namespace、敏感字段和来源;冲突解析器只在发现同属性记录时运行。后台任务负责聚合 Episode、清理过期项和重建索引。
所有写入使用幂等键。消息重试或任务恢复时,同一候选不会复制两遍。更新采用版本化事务:新记录与旧记录状态一起提交,避免出现新规则写入成功、旧规则仍保持 active 的半完成状态。
数据规模增长后,第三阶段才值得加入混合检索、Reranker、图关系和分层摘要。此时也要提供用户可见的 Memory 管理界面、租户隔离、保留期限、导出与删除能力。观测面记录写入原因、召回候选、最终注入项和模型是否引用,排查时才能分清错误发生在哪一层。
十、常见失败为什么发生
第一类失败是什么都记,最后什么都找不到。把每轮对话切块入库会迅速制造重复、闲聊和过时内容。Top K 被相似废话占满,需要执行的约束反而召回不到。写入必须有价值判断,Archive 与 Memory 应分开。
另一个极端是只存摘要,细节被压没。递归摘要会逐轮丢失条件和少数例外。MemGPT 也把递归摘要的有损性列为分层管理的动机。摘要适合导航,重要事实和来源需要独立保存。
检索正确时,回答仍然可能错误。模型可能忽略证据、错误合并两个时间版本,或被当前对话中的强提示带偏。评测要区分 Retrieval 与 Reading:先检查正确记录是否进入候选,再检查最终 Context,最后检查行为是否遵守。
向量库不能充当权限边界。Embedding 检索通常按相似度工作,不理解组织权限。若系统先跨租户搜索再过滤,候选内容可能已经进入日志或模型输入。访问控制要进入存储 Namespace 和检索 Query 的最前面。
旧记忆还可能不断自我强化。模型从错误记忆生成回答,后台提取器又把回答当成新证据,错误会出现多个副本。写入器必须区分用户原话、工具事实、模型推断和模型自己生成的内容。模型输出不能在没有外部证据时提升自己的可信度。
把偏好当命令同样危险。“用户通常喜欢简洁”可以调整表达,不能覆盖当前明确要求“详细解释”。长期 Memory 应处于系统规则和当前用户指令之下。发生冲突时,离当前任务更近、Scope 更具体、时间更新且来源更强的记录优先。
十一、安全、隐私与 Prompt Injection
Memory 延长了数据的影响时间,也延长了攻击寿命。一次恶意网页内容如果被错误提取成长期规则,未来多个会话都可能受影响。
写入管道应把不可信内容标记为 Data,禁止它直接成为系统指令或 procedural memory。来自网页、邮件、文档和工具结果的候选,需要来源标签和更低信任等级。只有用户明确指令、管理员策略或审核过的流程才能进入高优先级行为规则。
多租户系统必须在物理或逻辑 Namespace 上隔离用户和组织,并让每次读取携带授权主体。加密解决静态数据泄露,无法修复查询范围错误;日志脱敏也不能代替最小化保存。
产品还应回答用户能否看到、修改、导出和删除自己的记忆。对于模型推断出的偏好,最好显示“系统为何这样认为”和证据来源。无法解释的个性化会让正确行为看起来像监控,让错误行为更难纠正。
十二、怎样评测 Memory,而不是只测聊天感觉
LongMemEval用 500 个问题覆盖信息提取、跨 Session 推理、时间推理、知识更新和无法回答时拒答五种能力。论文报告长 Context 模型在其约 115K Token 设置上出现明显性能下降,并把系统拆成 indexing、retrieval、reading 三阶段。数字只属于该数据集和模型,但评测维度很适合转成工程测试。
写入层的测试给定一段交互,检查系统是否保存应保存的事实,是否拒绝闲聊与敏感内容,是否生成正确 Scope、来源和有效期。指标可以包含写入 Precision、Recall、重复率、冲突识别率和敏感信息泄漏率。
检索层固定 Memory Store 和 Query,检查 Gold 证据是否进入 Top K,错误租户记录是否始终为零,更新后的 active 版本是否压过旧版本。按单事实、跨记录、时间、隐式偏好和无答案问题分别统计,平均数会掩盖最危险的短板。
阅读与行为层把 Gold Memory 直接放进 Context,测试模型能否正确使用。若这一步失败,继续调 Embedding 没有意义。对工具型 Agent,最终指标应是行为约束是否满足,例如有没有在正确仓库自动推送,有没有在改部署配置时请求确认。
生命周期与系统指标包括写入延迟、检索 p95、每轮注入 Token、存储增长、过期清理、删除传播时间和恢复正确率。Mem0 论文在 LoCoMo 上报告了相对其对照的效果、延迟和 Token 成本改进,这类结果提醒我们同时观察质量与成本;其具体百分比依赖论文的模型、基线和评测方法,不应直接拿来做生产承诺。
线上可以做影子召回:先记录新 Memory 系统会返回什么,不注入主模型;人工或 Judge 比较相关性与安全性后,再逐步开放低风险场景。出现行为回归时,保留关闭长期记忆、只使用 Thread State 的降级开关。
十三、设计检查表
开始编码前,先写清这些答案:
- 哪些信息只属于当前 Thread,哪些允许跨 Thread?
- Memory 的用户、组织、项目和任务 Scope 怎样表达?
- 写入候选来自用户原话、工具事实还是模型推断?可信度如何区分?
- 每条记录能否回到原始事件?
- 冲突时按来源、时间、Scope 还是人工规则决定?
- 是否支持 supersede、expire、delete 和物理擦除?
- 检索前怎样执行权限过滤?
- Query 是否包含实体、时间和任务阶段,而非只有最后一句话?
- Context Builder 怎样去重、标注冲突并限制 Token?
- 能否分别观察写入、召回、装配和最终行为?
- 删除一条源数据时,怎样找到 Embedding、摘要和派生记录?
- 关闭长期记忆后,Agent 是否仍能安全完成基本任务?
如果这些问题暂时没有答案,先实现 Thread Checkpoint 和用户显式保存,比搭一套自动抽取、自动反思、自动更新的复杂 Memory 更稳。多数系统最初缺少的是清楚的状态边界和可验证的恢复路径,而不是更大的向量库。
十四、结语
Agent Memory 的工程目标,是在需要时把少量可靠状态带回当前决策。短期状态保证任务能继续,Event Log 保留证据,长期记忆跨会话提供事实与经验,Context Builder 决定本轮真正看见什么。
一套能长期运行的 Memory 系统必须会拒绝写入、保留来源、按 Scope 召回、识别时间变化,并让错误记录退出活动集合。等这些基础路径可测试之后,再增加 Reflection、知识图谱或更复杂的自动整理,收益才有稳定的落点。
参考资料
- Memory overview, LangChain / LangGraph
- Memory implementation guide, LangGraph
- MemGPT: Towards LLMs as Operating Systems
- Generative Agents: Interactive Simulacra of Human Behavior
- LongMemEval: Benchmarking Chat Assistants on Long-Term Interactive Memory
- Mem0: Building Production-Ready AI Agents with Scalable Long-Term Memory
如果这篇文章对你有帮助