先分层,再设计——个人助手的记忆系统设计框架
大模型变聪明的速度,比它变「懂我」的速度快得多。它可以一次读完十万行代码、把一个陌生模块讲得头头是道;但换台机器,或者隔两周再来,它对我一无所知:我喜欢什么写法、我踩过哪个坑、我强调过什么不能做——全部归零。
我们习惯把这件事叫「没有记忆」。但真去给自己的助手补记忆时会发现,难的既不是存储,也不是检索,而是回答一个问题:到底该记什么。
因为「记忆」这个词把太多不同的东西装进了同一个口袋:我的偏好像是记忆,项目里的命名约定也是记忆,上周排查某个报错的过程还是记忆。可这三样东西多久变一次、记错了会有多麻烦、什么时候该出现在对话里,完全不一样。
更麻烦的是,连「记下来的东西该怎么用」这件事,现成的答案都是彼此矛盾的:有人把记忆压到几千字符,每次开始新对话时整块塞给模型;有人一条都不塞,等模型自己想起来去查。研究界也没给出统一答案——现在最主流的几个「记忆考试」,考的其实是「能不能回答一段长对话里问过的事」,而不是「能不能用记住的东西把活干对」。
问题因此不在「存了多少」,而在「存的是什么、以及它什么时候该出现」。既然现成的答案互相矛盾,值得先把这个坐标系立起来。这篇文章有两个判断:
- 「记忆」是个统称,至少包含五个层级——而且它们该不该常驻,答案分成三种。所以「该常驻还是该去查」这个争论,本身问错了问题。
- 记忆系统的质量上限由写入路径决定,不是由检索决定。 检索只能把已经写对的东西找回来。
一、把「记忆」拆成五个层级
绝大多数关于记忆的设计混乱,源头是把五件不同的事都叫「记忆」。它们多久变一次、有多确定、搞砸了会怎样,完全不是一回事:
| 层 | 装什么 | 多久变一次 | 有多确定 | 主要会怎么坏 | 该常驻还是该去查 |
|---|---|---|---|---|---|
| L1 身份与偏好 | 我是谁、说话习惯、技术栈偏好 | 几个月–几年 | 人明说的就高,系统猜的就低 | 过时了、或者被猜错了还固化下来 | 常在场(但要小) |
| L2 约束与纪律 | 禁令、「必须遵守」的规矩 | 几乎不变 | 必须是人说的,不能靠猜 | 漏用 | 无条件在场 |
| L3 事实与教训 | 环境怪癖、工具坑、项目约定 | 几周–几个月 | 中,而且会随环境变 | 重复、过时、搜不到 | 去查 |
| L4 事件流 | 会话历史、当时为什么这么决定 | 只增不减 | 高(是记录),但会过时 | 被淹没、搜不到 | 去查(优先按时间点找) |
| L5 流程 | 可以复用的步骤、技能 | 几个月 | 中,用过几次才知道准不准 | 越堆越多、互相抢位置 | 先列目录,用到再加载 |
先记住一个例子,后面几节还会回到它。
我跟助手说过不止一次:我电脑上只装了 pnpm,别用 npm。
(pnpm 和 npm 是两个功能差不多的工具,用来装代码依赖——混着用会把项目搞乱。)就这么一句话,其实躺在五个层上:
- 「我习惯用 pnpm」——L1 身份与偏好
- 「别用 npm」——L2 约束与纪律
- 「这台机器的 Node 版本旧,装新版会报错」——L3 事实与教训
- 「上次试 npm,锁文件被改了,回滚了半天」——L4 事件流
- 「这个项目的发布流程」——L5 流程
五条都和 npm 有关,但它们该被对待的方式完全不同。这就是这篇文章要讲的事。
区分这五层的,不是「存了什么」,而是三件事:它多久变一次、你有多确定它是对的、它坏起来有多麻烦——表里中间那三列说的就是这三件事,而它们决定了最右边那一列。
这也是为什么「记忆能力」这个说法帮不上忙:「能力」是对结果的期待,而上面这三件事是能直接观察、能直接调的。
从这张表能读出两条方向相反的规律:
- 变得越快、越不确定的东西,越不能常驻。(L3、L4)这是成本律:摆在常驻位置上的东西,每聊一轮都要重新付一次钱。
- 越接近「禁令」的东西,越必须常驻。(L2)这是可靠性律:禁令漏用一次就是事故。
这两条在同一层上会打架,所以:
不存在「最优的常驻方案」,只存在分层。
这也是为什么业界在「该塞进去还是该去查」上永远吵不出结论——Hermes Agent 选了「固定约 3,600 字符 + 冻结快照」,而另一派的做法彻底相反:一条都不塞,全靠去查。作为整体形态,两者都不是错的,只是同一根成本曲线上的两个不同位置。
顺带说一下范围。L5 那一层(技能与流程)我之前已经写过:《从对话到 Skills》讲的是它的抽象演进,《知识复利:让 AI 维护一个会自己生长的知识库》讲的是知识库怎么自己生长。这篇只处理剩下的四层——尤其是最容易被忽略的那个问题:存进去的东西怎么不烂掉。
换个角度看,这五层还能归成三类:
- 配置(L1、L2):人的状态——我是谁、什么不能做
- 记录(L3、L4):对世界的观察——发生过什么
- 流程(L5):做法本身——一件事该怎么做
分成这三类不是为了整齐,而是因为谁有权写它们,完全不一样:约束不该由被约束的那个人自己写,而记录应该尽量自动抓。这一条会在第四节直接推出一条结论。
二、五问:拿到任何实现都能问的问题
不管看的是别人的产品还是自己的系统,对每一层都该问这五个问题。空的格子就是设计缺失:
| # | 问题 | 为什么要问 |
|---|---|---|
| Q1 | 谁在什么时候写? | 决定这东西长得多快。「每轮后台自己偷偷存一次」和「用户在界面上点了保存才写」,是两个完全不同的系统 |
| Q2 | 同一件事被写第二遍时,凭什么认出「这是同一条」? | 决定重复率。没有这个判据,库里必然越积越多近义条目 |
| Q3 | 靠什么把它找回来? 按字面 / 按意思 / 按关系 / 按时间 | 决定「运气最差时能找回多少」,也反过来决定 Q2 那边的压力有多大 |
| Q4 | 它怎么失效? 删掉 / 标记作废 / 慢慢降权 / 永不处理 | 决定这东西半年后还能不能用,也是最常被整节漏掉的一格 |
| Q5 | 每次要花多少成本带着它? 常驻 vs 用到再取,谁付这笔钱 | 决定「记得越多模型越笨」会不会发生 |
Q2 和 Q3 之间那条箭头,是后面要展开的关键因果链。
三、成本花在哪儿:五种给记忆安排位置的方式
第一节那个「常驻还是去查」的二分,拆开就是下面这五种:
| 形态 | 怎么做的 | 成本花在哪儿 |
|---|---|---|
| 冻结快照 | 随系统提示在对话开始时整块塞进去一次,之后不再变,会话结束就重来 | 每轮固定一笔 |
| 独立预算块 | 系统单独划出来的一小块预算,独立于会话存在,可以随时增删 | 每轮一小笔固定开销 |
| 目录 + 按需 | 只把名字和一句话说明放进去 | 每轮一笔中等开销(条目越多越贵) |
| 纯检索 | 完全不塞,全靠模型自己想起来去查 | 查一次要等一会儿,而且可能压根想不起来查 |
| 不做记忆(对照基线) | 没有记忆 | 0(但每次都得重新交代背景) |
前两种都是「永远在场」,区别在那笔预算由谁控制:冻结快照是系统提示的一部分,会话一开始就定型,中途改不动;独立预算块是另一笔独立的小额度,能随时增删。
Hermes Agent 的官方文档给了一组很诚实的一手数字:MEMORY.md 上限 2,200 字符(约 800 tokens),USER.md 上限 1,375 字符(约 500 tokens),加起来约 1,300 tokens 的固定开销;技能库分三级逐步展开,第一级(只列名字和一句话说明)大约 3k tokens。
换句话说,常驻是有价格的,价格就是上下文额度——这个视角我在《把上下文当成一等资源》里展开过。区别在于:上下文是一次性的,而记忆是每次开新对话都要重新付的那一笔。
其中有一个细节我一开始读反了,值得单说。Hermes 的做法是冻结的——对话中途新写进去的记忆,这一轮对话的系统提示里不会出现。文档把原因写得很直白:这个快照在对话开始时抓一次,中途绝不改动,这是故意的,为的是保住模型的「前缀缓存」,省掉重复计算。(原文见文末附录。)
这不是实现偷懒,是一个成本上的取舍。但它带来两个可预期的后果:写进去的东西不会当场出现在系统提示里;而且系统提示里只要有一条错事实,这一轮对话里就没有机会自我纠正。
不过这里要补一个限定,否则容易读过头。Hermes 的文档紧接着还有一句:磁盘上的记忆是立刻写入的,agent 调工具时读到的也始终是最新值——看不见的只是「系统提示里那一份」。所以准确的说法是:冻结快照没有自动纠错,纠错要靠 agent 自己想起来去查。
推论是:冻结快照要求上游的写入质量足够高,因为它少了自动纠错那一环。而纯检索恰好相反——每次都能读到最新值,但每次都指望模型自己想起来去查。两种形态的坏法正好错开,不是互相竞争。
还有一个必须对照的基线:不做记忆。记忆不是免费的,它要一次性建设,之后还要一直交维护税(合并、作废、评测、隐私审计),而且它会主动造成伤害——过时的事实被当成当前事实、错误推断被固化下来反复使用、上下文被无关条目污染。如果一个场景里「重新交代背景」的成本低于「维护记忆」的成本,就不该做记忆。
四、写入路径才是主战场
如果一个记忆系统的质量差,先怀疑写入路径;只有当写入质量可验证时,才有资格谈检索能力不足。
回到 pnpm 那个例子:助手第一次知道「我不用 npm」,可能是从我说的一句话里学到的。可如果第二次、第三次它还要再问一遍,问题就不在检索——是那句话压根没被写对。
消解重复有四条路,每条都有价格:
| 方式 | 怎么做的 | 代价 | 会怎么坏 |
|---|---|---|---|
| 写之前查重(但不改) | 写之前先看看有没有;被推翻的旧条目留着 | 每次写入多查一次 + 多抽一次 | 新旧两条并存 → 查的时候可能返回已经过时的那条,冲突只能甩给上层应用去处理 |
| 写的时候判定(自动改写) | 先抽出候选,和已有的比,自动把旧的作废 | 每次写入多跑一次模型,贵到需要专门优化 | 判错了会悄悄累积;错误合并会丢信息,而且不可逆 |
| 写满了才合并 | 满了才触发,让模型自己合并腾地方 | 偶发、突然、很贵 | 平时完全不约束增长——没写满之前一直只增不减 |
| 靠提示词里的纪律 | 在 prompt 里规定「写之前先搜」 | ≈0 | 会自己失效(下面细说) |
这四条路最后都会落到一个数字上:重复率。而任何「重复率」数字,先问它的口径。 用单一相似度阈值判定重复时有个陷阱:A 和 B 像、B 和 C 像,程序就会把 A 和 C 并进同一簇,哪怕它俩毫无关系。于是同一份数据,阈值松一点可以报出「一半都是重复」,紧一点又会说「几乎没有重复」。这不是数据的性质,是方法的性质——任何报告重复率的系统,都得说明它用了什么聚类方法、这个方法会在哪里失效。
两条代价是有原始证据的:Zep 的官方博客说每次写入都做图构建会消耗推理成本,他们「在过去六个月把图构建的 LLM 推理成本降低了 40%」;Mem0 的官方文档则把「去掉重复事实」列成抽取流水线里单独的一步(Deduplication and embedding: redundant facts are removed),并说明一旦关掉推断(infer=False),存进去的就是原样内容,同一件事会存好几份。
把「抽事实 + 做判定」放在写入这一步,付出的不是 token,而是写入延迟——而写入延迟用户是直接能感觉到的。
为什么「写之前先搜一下」不能当主机制
这是整篇文章里我最想强调的一条,它有完整的因果链:
1 | 记忆库里的重复条目 |
你想用「写之前先搜一下」来防止重复——可搜不搜得到,正是你不放心的那个环节。这是个死循环。 检索能力不够的时候,这条纪律不是报错,而是「搜了一下没找到,那就新增一条」,看起来完全正常。它是悄悄失效的。
所以:提示纪律只能当兜底。凡是能用机制挡住的,永远比靠自觉可靠。
在这一条上要诚实一点:并不是所有系统都没做检查。Mem0 的官方文档里,「写之前先看看有没有」是流程的第一步(Context lookup),代价也摆在明处——每次写入多一次查重和抽取,也就是前面说的那笔写入延迟。所以真正的分野不是「有没有查」,而是「查重这件事由谁付账」: 靠提示词纪律,账只会在重复率上慢慢还;靠结构性查重,账当场付清。前者便宜但不可靠,后者可靠但不免费。
这两件事不矛盾:Mem0 查的是「别再存一份一模一样的」,不是「把旧的改掉」。 它的自动路径是叠加式的——官方原话是「可以存下新事实而不悄悄改写旧的那条」,更正和删除要靠显式 API。二手综述经常把它说成「写入时判定 ADD/UPDATE/DELETE/NOOP」那一路,方向正好说反。
有意思的是,三家互不相干的实现在「谁不能写」上收敛了
翻文档时我发现一个信号:几个独立实现都有某种「结构上就写不进去」的存储。
| 实现 | 机制 |
|---|---|
| Hermes | 技能写入先暂存,人审过了才生效(skills.write_approval) |
| Letta | 只读 memory block(system_config 由外部 API 更新,agent 只能读) |
| Mem0 | 标了 immutable 的条目不能就地更新,只能删掉重建 |
不同设计在同一个点上收敛,是这个模式确实必要的强证据。由此得到一条分层原则:
越是「我是谁」「不许做什么」这类东西(L1、L2),越该用机制去挡——不可写、人来审、永远在场;
越是「发生过什么」这类东西(L3、L4),越该自动化——写入时判定、合并、检索。
反过来就是两类典型浪费:把 L3 事实的收集做成人来审(浪费人的注意力)、把 L2 约束交给「记得去查」(这是设计缺陷,不是实现缺陷)。
五、检索的上限,会反向决定写入质量
这一节不是要翻前面的案。检索弱不会让写好的东西变差,它只是逼你把本来该在检索端做的事挪到写入端——两条路总得走一条。
检索能力是分级的,没有哪一级是普遍最优的:
| 级别 | 能找回来 | 找不回来 |
|---|---|---|
| 按字面(子串 / BM25) | 用词一样或者大体重合的 | 换了语言、换了近义词、说法更抽象了 |
| 按意思(向量) | 近义的说法、跨语言的说法 | 精确的标识符、冷门专名、否定和例外 |
| 按关系 / 按时间(图、时序) | 跳几层的关系、时间上的推理、「当时是不是这样」 | 得先有抽取质量,schema 也得设计对 |
| 人直接指定 | 100% | 前提是人得知道库里有什么 |
用 pnpm 那个例子看一眼就明白:你搜的是「依赖管理工具」,库里那条写的是「pnpm」——按字面找,这两个词一个字都不重合。 于是系统认为你没记过这件事,转身又问了你一遍。
如果索引是按 3 个字符的滑动窗口切的(trigram),它有个容易被忽略的硬边界:1–2 个字的查询根本匹配不上——而中文里最常用的搜索词,恰恰就是两个字。
按字面找还有两个结构性缺口:
- 跨语言断裂:同一件事用中英各记一遍,两种说法各只能命中一半。这不是模型的问题,是索引的问题。
- 搜什么词是模型猜的:一条都搜不到时它不会报错,模型只会认为「没有这条记忆」,然后可能再写一条。
第二条,正是前面那个死循环的另一面——检索弱 → 搜不到已有的近义条目 → 判定「不存在」→ 新增一条 → 重复越积越多,而写入纪律就在这个环节悄悄失效。
**设计推论:**如果只能用弱检索,就把语义能力挪到写入那一边——在条目里显式写上同义词、别名、容易拼错的写法(提高字面命中率);强制统一语言,禁止同一件事中英各记一条;写入时就把「这条属于哪个对象/主题」结构化,而不是留给检索去猜。
原则:把能力放在更强的那一端。 检索弱,就让写入端多干活。
六、生命周期:最容易整节被忘掉的一个环节
多数系统的策略是「永不删除」。而永不删除会悄悄毁掉检索质量:库里被陈旧条目一点点填满,能找回的比例随条目总数增加而下降。 只要一直写、却从来不淘汰,这个结果就是确定的。
有四件事必须分开,它们经常被混成一句「清理」:
- 降权:不删,只是把优先级调低。触发条件是长期没人用。要保住的是「可以反悔」。
- 作废:标一句「曾经为真,现在不成立了」。触发条件是事实被推翻。必须保住的是这段历史,以及它为什么被推翻。
- 遗忘:真的删掉。触发条件是隐私、合规、或者明确记错了。必须一并覆盖镜像、索引、备份、快照——否则等于没删。
- 升级:从「用到才查」提到「永远在场」,或者从一条事实升成一套流程。触发条件是反复被用到。要守住的是预算上限。
回到 pnpm:「我现在改用 pnpm 了」这条事实成立之后,「以前用 npm」也不该被删掉——它正是「为什么别让我再碰 npm」的答案。
作废 ≠ 删除。 一条事实不作数了,别急着删——删掉它,会让助手在未来重新犯同一个错,因为它看不到「这条路走不通」。正确的做法是留着它、标上「已作废」,等每次要用的时候再判断它还算不算数。两个原始实例,说的是同一件事:
- Zep:原文大意是「一条被作废的事实会连同它的完整历史留在图里,而不是被删掉」,而且那条边上的记录只增不覆盖(第一次抽取 + 后续确认 + 推翻)。
- Mem0:用
expiration_date表达过期——过期条目从search和get_all里藏起来了,但按 ID 仍然取得到,数据并没有被删。
那条被忽略的「升级」铁轨
这里有个坏习惯值得单拎出来:信号记下来了,却没人用它。 记录每条记忆被用过几次、最后一次是什么时候,成本很低,所以不少实现都做了;但这些数据最后往往只被拿来生成一份「最常被用到 / 从来没人用」的清单给人看——没有自动降权、没有淘汰、也没有升级。数据记了,决策没有发生。
而升级恰恰是少见的能同时做到「准」和「省」的机制:
1 | 经常被用到 + 很确定 → 升级为常驻(放进 L1/L2 的固定预算) |
没有这条铁轨,「常驻还是去查」就只能二选一,而两个极端都有已知的翻车方式。
七、行为层:何时记、何时用、何时忘、何时问
前面的都是机制。但「像不像一个合格的助手」,机制只决定一部分。
什么时候该记——三个条件同时满足才值得写:重复出现(第二次出现才记,第一次往往只是个例——比如我第一次说「我不喜欢这个写法」可能只是随口一句,第二次说才值得写下来)、会改变以后的做法(不是「有意思」,是「会影响我下次怎么做」)、跨对话还有效。不该记的:能从代码仓库里推出来的(会腐坏,源头一改,记忆就变成误导)、有更权威来源而且会变的(文档、API 签名)、跟隐私有关但没有明确用途的。
什么时候该用——L2 约束无条件在场,不能靠去查;L3 事实在用之前查一下。还有一条容易被忽略:记忆是背景资料,不是命令。 必须做来源标注和围栏(「以下不是新的用户输入」),否则记忆会变成提示注入的载体,也会让模型把「曾经看到过的事」当成「必须执行的指令」。
什么时候该忘——被推翻就标作废;有过期语义的按时间降权;被更权威的来源取代就降级成历史。(为什么是标作废而不是删,第六节说过。)
什么时候该问——可以拍成一个 2×2:
| 影响小 | 影响大 | |
|---|---|---|
| 没把握 | 先做,事后说一声 | 问 |
| 有把握 | 直接做 | 直接做 |
但有一条铁律:永远不要为了「记录」而打断用户。 记忆的价值来自减少打扰,一个总在确认「要不要记住这个」的助手是净负值。
最后是这篇文章里我最想记住的一句话:
助手感不来自「记得多」,而来自「该在的时候在」。
由此得到一个不对称的优先级:漏用一次禁令的伤害,通常大于多记十条无用事实。 所以资源该优先投给 L1/L2 的「保证在场」(预算、可靠性、不可写性、人审),而不是投给 L3 的容量和找回率。这也解释了为什么纯检索式系统会给人「它好像忘了我是谁」的感觉——它把最重要的 L2,交给了最不可靠的那条路径。
八、反例:每条原则的过度应用
一个只有正向原则的框架会诱发过度工程。每条原则都配一个反向代价:
| 原则 | 用过头会怎样 |
|---|---|
| 分层 | 五层变十五层,维护成本超过收益 |
| 写入时判定 | 每次写入多一次模型调用;合并错了没有回滚接口,两条并成一条就拆不开了 |
| 常驻注入 | 预算吃掉上下文,模型变笨;而且错事实当场改不掉 |
| 纯检索 | L2 漏用;一条都搜不到时悄无声息 |
| 全自动化 | 模型自我授权:把猜到的偏好写成必须遵守的规矩 |
| 人审 | 注意力被低频事实耗尽;而且审错了层(去审 L3 事实) |
| 永不删除 | 检索空间被陈旧条目填满;隐私与合规风险 |
| 做记忆这件事本身 | 维护税超过「重新交代背景」的成本 |
九、怎么用:拿这五问套一遍
这套框架的用法不是「照着搭」,是「拿去审」。找任意一个想做记忆的系统——别人的产品、自己上一版的设计、或者一个还没动手的想法——对每一层把 Q1–Q5 问一遍,然后看哪些格子是空的。
三个最容易空的地方,也最值得优先填:
- Q2「凭什么认出是同一条」:没有它,重复率就是一个随机数。
- Q4 失效策略:没有它,系统会缓慢地变成一堆陈年噪音。
- L2 那一整行:如果 L2 的 Q5 写的是「去查」,那它的可靠性上限就被检索能力锁死了——而这是一条不该被依赖的路径。
再补三个必答问题:
- 哪一层是机制保证的,哪一层只靠自觉?
- 使用信号被记下来了吗?被用上了吗?
- 「遗忘」覆盖了镜像、索引、备份吗?
怎么知道自己做对了
现在主流的几个「记忆考试」——LoCoMo、LongMemEval、BEAM——都是拿一段很长的多轮对话去问系统:关于这段对话,你能不能回答出问题。它们测的是「能不能把说过的事回忆出来」,不是「能不能用记住的东西把活干对」,这是两件事,别拿前者的分数当后者的保证。
更根本的原因是:记忆质量取决于你的写入分布(你记什么、怎么措辞、用什么语言)和你的查询分布(你会问什么、模型会猜什么词)——这两件事没人能替你估。所以探针只能自己搭,好在不用复杂:按五层各造一批查询(每层至少 10 条;L5 只列目录,不算在这篇的范围内),标清楚每条「期望命中哪一条记忆」以及「是不是必须命中」,然后分层设及格线——L2 约束要求 100% 在场,达不到就是设计失败,不是调参数的问题;L3 事实能找回多少可以宽松一点,但要盯住有多少条压根一次都没被找回来。
最后一件事:先证明记忆有必要。 拿「不做记忆、每次重新交代」当基线——如果维护税高于重新交代的成本,停下来比做下去更划算。
十、还没想清楚的
诚实列一下这个框架没解决的问题,免得它显得比实际更完整:
- 偏好的「把握」怎么量化? 「用户说过」和「系统观察到」的确定程度不一样,这个差别怎么进入决策。
- 主动性的时机判据:什么时候该主动用记忆,而不等被问?这和「什么时候该问」是同一枚硬币,但缺少可操作的标准。
- 记忆污染的下游检测:一条错误记忆可能在很久以后才造成危害,怎么尽早发现。
- 跨设备 / 跨 agent 的记忆一致性:同一件事多端写入的冲突怎么消解。
- 作废的传染性:A 被推翻了,依赖 A 的 B、C 要不要一起作废。
- 记忆的害处怎么度量。 「记忆是有用的」在几乎所有讨论里都是默认前提,这套框架里的每条取舍也都建立在「利大于弊」上——但它带来的坏处(污染、把错误固化、上下文被无关条目占掉)一直没有人正经测过。
来源
- Hermes Agent — Persistent Memory:
MEMORY.md2,200 字符 /USER.md1,375 字符、冻结快照及其实验性质的理由、超限写入返回错误而不自动压缩Frozen snapshot pattern: the system prompt injection is captured once at session start and never changes mid-session. This is intentional — it preserves the LLM’s prefix cache for performance.
- Hermes Agent — Skills System:三级渐进披露、
skills.write_approval - Mem0 — How Mem0 works / Add Memory:叠加式写入、
infer=False会落重复 - Mem0 — Update Memory:
immutable条目需删后重建 - Letta — Memory blocks / Shared memory / Memory Blocks 博客:块常驻上下文、共享块、只读块、sleep-time agents
- Zep — How Zep tracks provenance in agent memory:双时间戳、失效事实保留完整历史、图构建推理成本优化 40%
An invalidated fact stays in the graph with its full history rather than being deleted.
- MERIT 论文:「记忆被默认是有用的;它带来的坏处没人测」的出处
