Agent Memory:短期状态、长期记忆与检索更新

从一次跨会话写作任务出发,拆解 Agent 怎样保存运行状态、筛选长期记忆、检索相关证据,并在事实变化时更新或遗忘。

本文使用humanizerdocumd-visuals

用户在第一次合作时说:“这个博客里的文章写完后直接提交并推送。”一周后,他又补充:“涉及发布配置时先让我确认。”下一次任务开始时,Agent 应该记住哪一句,怎样知道它只适用于这个博客,又怎样避免旧规则覆盖新规则?

把历史消息全部塞回模型并不能稳定解决这个问题。随着对话增长,成本和延迟会上升,早期事实会被无关内容干扰;若只保存一份摘要,条件、时间和来源又可能在压缩中消失。可用的 Memory 是一条完整的数据路径:它要决定保存什么,用什么结构保存,何时召回,如何处理冲突,以及怎样删除已经失效的内容。

本文回答一个工程问题:怎样为 Agent 设计一套可恢复、可检索、会更新并且能够评测的记忆系统?

事实层主要来自 LangGraph Memory 官方文档、MemGPT、Generative Agents、LongMemEval 与 Mem0。论文结果只说明各自实验设置中的表现,不直接代表任意产品环境。本文的 Schema、版本策略和上线方法属于工程设计建议。

先看结论

Agent 至少需要区分两种状态。短期状态属于一个 Thread 或任务,保存消息、计划、工具结果、审批和检查点,用于下一步推理与中断恢复;长期记忆跨 Thread 存在,保存经过筛选的用户偏好、稳定事实和可复用经验。两者可以使用同一数据库,却不能共享一套生命周期。

Memory 也不等于“给聊天记录做向量检索”。原始事件日志负责追溯,结构化状态负责恢复,长期 Memory 负责在未来任务中提供少量相关证据。向量相似度只是召回手段之一,时间、实体、作用域、权限和有效期往往更重要。

每条长期记忆都应带上来源、适用范围、写入时间、有效期、置信度和版本关系。没有这些元数据,系统无法回答“这条规则来自谁”“是否已经过期”“新旧说法冲突时听谁的”。

Memory 的质量需要沿整条链路评测。只测检索 Recall,会漏掉错误写入、过度记忆、更新失败和“虽然召回了,但模型没有正确使用”等问题。

Agent Memory 从运行状态到长期记忆的分层结构

一、先把五种容易混淆的东西分开

“模型记得”在产品界面上是一个感觉,在系统里却可能来自完全不同的机制。设计之前先给每种信息指定所有者。

名称 保存什么 典型作用域 用途与常见误区
模型 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 的降级开关。

十三、设计检查表

开始编码前,先写清这些答案:

  1. 哪些信息只属于当前 Thread,哪些允许跨 Thread?
  2. Memory 的用户、组织、项目和任务 Scope 怎样表达?
  3. 写入候选来自用户原话、工具事实还是模型推断?可信度如何区分?
  4. 每条记录能否回到原始事件?
  5. 冲突时按来源、时间、Scope 还是人工规则决定?
  6. 是否支持 supersede、expire、delete 和物理擦除?
  7. 检索前怎样执行权限过滤?
  8. Query 是否包含实体、时间和任务阶段,而非只有最后一句话?
  9. Context Builder 怎样去重、标注冲突并限制 Token?
  10. 能否分别观察写入、召回、装配和最终行为?
  11. 删除一条源数据时,怎样找到 Embedding、摘要和派生记录?
  12. 关闭长期记忆后,Agent 是否仍能安全完成基本任务?

如果这些问题暂时没有答案,先实现 Thread Checkpoint 和用户显式保存,比搭一套自动抽取、自动反思、自动更新的复杂 Memory 更稳。多数系统最初缺少的是清楚的状态边界和可验证的恢复路径,而不是更大的向量库。

十四、结语

Agent Memory 的工程目标,是在需要时把少量可靠状态带回当前决策。短期状态保证任务能继续,Event Log 保留证据,长期记忆跨会话提供事实与经验,Context Builder 决定本轮真正看见什么。

一套能长期运行的 Memory 系统必须会拒绝写入、保留来源、按 Scope 召回、识别时间变化,并让错误记录退出活动集合。等这些基础路径可测试之后,再增加 Reflection、知识图谱或更复杂的自动整理,收益才有稳定的落点。

参考资料