Supermemory 是一个 agent memory 服务。你把对话、文档、各种内容扔给它,它帮你提取事实、维护关系、处理冲突,搜索的时候返回和当前上下文最相关的记忆。定位是给 AI agent 做长期记忆的基础设施。
最近在 X 上频繁看到 Supermemory。一方面是越来越多开发者开始用它的 plugin 给 OpenClaw、Claude Code 这些 coding agent 加 memory layer,另一方面是 Supermemory 的 CEO Dhravya Shah 前两天发了一篇 article,讲他们用多 agent 编排在 LongMemEval 上打到了 ~99%,拿了 2.5M views。虽然他自己在推文里承认 "this was a stunt",那个 99% 的方案是实验性的(用 8 个 specialist agent 并行回答然后投票),不是他们的 production engine。但这篇文章确实引起了很多关注,也让我好奇 Supermemory 的 production 架构到底是怎么设计的。
之前写了 OpenClaw 的记忆系统,OpenClaw 走的是 Markdown-first 的路线:长期记忆存在文件里,搜索索引只是派生层,dreaming 把短期信号逐步提升为长期记忆。整个系统围绕文件展开,透明、可编辑、完全本地。
Supermemory 走了一条完全不同的路。它把记忆建模成一张图,每条记忆是一个节点,节点之间有版本关系和语义关系。OpenClaw 认为记忆是文本,Supermemory 认为记忆是事实的图谱。
这篇文章拆解 Supermemory production 系统的架构设计。素材来自两部分:它的 research paper 和它的 开源代码。后面会提到,这两部分之间有一些有意思的落差。
核心抽象:Document 和 Memory
Supermemory 最重要的一个设计决策是把输入和理解分成两层。
Document 是你扔给它的原始内容。PDF、网页、对话记录、文本片段。它是 stateless 的,一篇关于 Python 编程的文档对谁都一样,不会因为用户不同而改变。
Memory 是系统从 Document 中提取出来的原子化事实。"Alex 在 Stripe 做 PM"、"用户偏好深色模式"、"项目 deadline 是下周五"。Memory 是 stateful 的,绑定到具体的用户或实体,会随时间演变。
用一个不太精确但直觉上好理解的类比:Document 是书,Memory 是读完之后脑子里留下的东西。
这个分层解决的是标准 RAG 的一个根本问题。传统 RAG 直接在原始 chunk 上做搜索,但 chunk 从原始文档里拔出来之后,代词指代不清、上下文丢失,信噪比低。Supermemory 先把 document chunk 提炼成原子事实,搜索在这些高信噪比的 memory 上进行,命中后再把原始 chunk 注入结果来补充细节。
Memory 层做精准召回(高信噪比,一条记忆就是一个事实),Chunk 层补充细节(完整上下文,适合 LLM 做细粒度推理)。这个两层搜索的设计解决了"memory 太抽象丢细节"和"chunk 太嘈杂召回差"的两难。
Relational Versioning:记忆之间的关系
如果只做到 Document → Memory 的提取,那 Supermemory 就是一个稍微精细一点的 RAG。更大的区别是它在 memory 之间建立的关系。
三种关系类型:
-
updates。新事实推翻旧事实。你上个月说"我最喜欢蓝色",这个月说"我现在喜欢绿色了"。系统不会让两条矛盾的 memory 同时存在,而是建立一个 update 关系:新 memory 标记
isLatest=true,旧的标记isLatest=false。搜索默认只返回最新版本,但历史版本沿着版本链可以追溯。 -
extends。新事实补充旧事实,不矛盾。"Alex 在 Stripe 做 PM" 后来又知道了 "Alex 负责支付基础设施,带 5 人团队",第二条 extends 第一条。两条都有效,搜索时能拿到更丰富的上下文。
-
derives。系统从多条 memory 推断出新事实。"Alex 是 Stripe 的 PM" + "Alex 经常讨论支付 API 和反欺诈" → 系统推断 "Alex 大概负责 Stripe 的核心支付产品"。这条 derived memory 标记
isInference=true。
这是 Supermemory 和 OpenClaw 最根本的差异。OpenClaw 的记忆是扁平的 Markdown 文本,MEMORY.md 里一行一条,没有结构化的关系。你告诉 agent 你换工作了,它得靠自己的判断力去修改 MEMORY.md 里的旧信息。Supermemory 把这个问题内化到了数据模型里:新旧信息的关系不是文本编辑,而是图上的一条边。
和 GraphRAG 的区别
看到"graph"这个词,我最开始联想到的是前两年微软做的 GraphRAG。两者都认为 flat vector search 不够用,都在 vector 之上加了一层图结构,但图的设计其实完全不同。
GraphRAG 建的是传统的 entity-relationship 知识图谱。三元组结构:entity → relation → entity。从文档里提取出 "Microsoft → headquartered_in → Redmond" 这类关系,然后做 community detection 把紧密关联的 entity 聚类,再对每个 community 做层级摘要。它解决的是"对一个大语料做全局性问答"的问题,比如"这批文档的主要主题是什么"。
Supermemory 建的不是 entity graph,而是 versioned fact graph。节点是原子化事实,边是版本关系。Supermemory 自己的文档里有一句话直接点明了这个区别:"Unlike traditional knowledge graphs with entity-relation-entity triples, Supermemory's graph is facts built on top of other facts." GraphRAG 的图是静态快照,不处理知识冲突,也没有时间维度。Supermemory 的图是动态演进的,每条 fact 有版本链,旧事实可以被新事实 update,过期的事实会被自动遗忘。
从它开源代码里的 Zod schema 能看到完整的数据结构:
// packages/validation/schemas.ts
MemoryEntrySchema = z.object({
id: z.string(),
memory: z.string(), // 原子事实
version: z.number().default(1),
isLatest: z.boolean().default(true),
parentMemoryId: z.string().nullable(), // 版本链上一个节点
rootMemoryId: z.string().nullable(), // 版本链根节点
memoryRelations: z.record( // {memoryId: relation}
MemoryRelationEnum // "updates" | "extends" | "derives"
).default({}),
isInference: z.boolean().default(false),
isForgotten: z.boolean().default(false),
forgetAfter: z.coerce.date().nullable(),
// ...
})版本链用 parentMemoryId / rootMemoryId 形成链表。关系用 memoryRelations 做邻接表。搜索返回结果时,会附带 context.parents 和 context.children,让 LLM 能看到一条 memory 的完整演变历史。
自动遗忘
Memory 不只是会积累,也会过期。Supermemory 有两种遗忘机制。
时间过期。"我明天要考试",考试过了这条 memory 就没多大意义了。schema 里有一个 forgetAfter 字段,后端的 LLM 在提取 memory 时自动判断要不要设过期时间。后台 cron job 定期扫描过期的 memory,标记 isForgotten=true。
矛盾消解。通过 update 关系自动处理。"我喜欢绿色" 被 "我现在最喜欢蓝色了" update 之后,搜索只返回最新版本。旧 memory 不是删了,而是 isLatest=false,需要的时候还能追溯。
这解决了 OpenClaw dreaming 没有覆盖的一个问题。OpenClaw 的 dreaming 做的是 promotion:什么值得从短期记忆提升到长期记忆。但它不处理反方向的问题,即旧记忆过时了怎么办。Supermemory 用 update 关系 + forgetAfter 两个机制同时解决了知识冲突和时间过期。
User Profiles:预聚合的记忆
Profile 是一个工程优化。系统从所有 memory 中自动维护一个 per-user 的摘要,分两层:
- Static:长期稳定的事实。名字、职业、核心偏好。
- Dynamic:近期状态。当前项目、最近讨论的话题。
这个 profile 在每次对话开始时作为 default context 注入 LLM,不需要做搜索就能让 LLM 知道用户是谁。响应时间大约 50-100ms,因为它是预计算好的,不是实时搜索拼出来的。
这相当于把最高频召回的 memory 预热成一个 cache 层。大部分对话开头 LLM 需要知道的基础信息("用户是做什么的"、"用户最近在忙什么")都在 profile 里,不用每次都发起一次完整的 memory search。
Temporal Grounding:更精细的时间戳
Supermemory 的 research paper 重点宣传了一个叫 "Temporal Grounding" 的特性:每条 memory 有两个时间戳,documentDate(对话发生时间)和 eventDate(事件实际发生时间)。论文里画了图,写了专门的章节,把它列为 "core differentiator"。
但我翻遍了开源代码里的 Zod schema,没有找到 documentDate 和 eventDate 这两个字段。实际的时间模型是:
createdAt/updatedAt:标准的数据库时间戳forgetAfter:过期时间addedAt:memory 关联到 document 的时间
这意味着什么?有两种可能。一种是 temporal grounding 确实存在,但实现在闭源的后端代码里,开源的 schema 只是客户端验证用的子集,不包含所有字段。另一种可能是 temporal grounding 更多是 LLM 在提取 memory 时通过 prompt engineering 实现的,不是一个独立的结构化字段,而是 memory 文本本身就包含了时间信息(比如 "Alex 在 2026 年 3 月搬到了 Seattle")。
不管哪种情况,论文里描述的"双层时间戳"和实际代码之间有明显的 gap。这不影响对整体架构的判断,但可能会影响 benchmark 结果的置信度。
Benchmark:怎么看那些数字
Supermemory 在 LongMemEval_s 上的表现确实很强,尤其是在 multi-session(71.43% vs Zep 57.9%)和 temporal-reasoning(76.69% vs Zep 62.4%)两个 category 上。这两个恰好是 relational versioning 和时序理解直接解决的问题。
| Category | Supermemory | Zep | Full Context | Delta vs Zep |
|---|---|---|---|---|
| single-session-user | 97.14% | 92.9% | 81.4% | +4.6% |
| single-session-assistant | 96.43% | 80.4% | 94.6% | +19.9% |
| single-session-preference | 70.00% | 56.7% | 20.0% | +23.5% |
| knowledge-update | 88.46% | 83.3% | 78.2% | +6.2% |
| temporal-reasoning | 76.69% | 62.4% | 45.1% | +22.9% |
| multi-session | 71.43% | 57.9% | 44.3% | +23.4% |
但有几点得注意。
第一,他们选择 session-by-session 而不是 round-by-round 的 ingestion 方式,和 LongMemEval 原论文的评估方法不同。这对做了 session-level 记忆提取的系统有利。第二,Zep 的数据直接引用自 Zep 自己的论文,不是在完全相同的条件下复现的。第三,500 道题的 benchmark 在统计上不算特别大,单个 category 的 delta 可能有噪音。
这不是说他们的结果有问题。relational versioning + 图结构在 knowledge-update 和 multi-session 场景上应该确实比扁平存储强,这个方向上的优势是符合直觉的。只是 benchmark 数字本身的精确对比要打个折。
和 OpenClaw 放在一起看
| 维度 | Supermemory | OpenClaw |
|---|---|---|
| 记忆本体 | 知识图谱(节点 + 关系) | 扁平 Markdown 文本 |
| 知识冲突 | updates 关系自动处理 | 靠 agent 自己编辑文件 |
| 自动遗忘 | forgetAfter + 矛盾消解 | 无(dreaming 只做 promotion) |
| 搜索 | Memory-first → Chunk 补充 | Hybrid(vector + BM25)直接搜 chunk |
| User Profile | 自动维护 static/dynamic | 无 |
| 部署 | 云端 SaaS | 完全本地 |
| 透明性 | 黑盒 API | 打开文件就能看 |
| 真相源 | 云端 memory graph | 你的文件系统 |
OpenClaw 信任文件系统和用户。MEMORY.md 你随时能打开看,能直接编辑。记忆的最终裁判是人。整个系统的复杂度是有上限的,因为 truth 始终锚定在可读可改的文本文件上。
Supermemory 信任算法和图结构。关系检测、冲突消解、自动遗忘,这些都交给系统自动处理。结果可能更准确(benchmark 数据确实更好),但你没办法打开一个文件看到所有记忆,也没办法直接改一行文字来纠正一条记忆。
最值得借鉴的一个 idea
抛开产品形态不谈,Supermemory 架构里最值得带走的一个思路是:把记忆之间的关系显式建模。
大部分记忆系统(包括 OpenClaw、Mem0、大多数 RAG 方案)把记忆当成独立的条目。每条记忆自己存在,搜索时按相似度排序返回。但现实中的记忆不是独立的,它们之间有版本关系(旧事实被新事实取代)、补充关系(一条信息给另一条增加细节)、推理关系(多条信息组合产生新理解)。
Supermemory 用三种边(updates / extends / derives)把这些关系编码进了数据模型。这让系统能回答一类其他方案回答不了的问题:"Alex 现在在哪工作?"(需要知道哪个版本是最新的)、"Alex 的职业经历是什么?"(需要沿版本链追溯)、"Alex 这份工作具体做什么?"(需要找到 extends 关系的补充信息)。
这个思路不需要 Supermemory 的整套基础设施也能用。哪怕是在 Markdown 文件里,也可以用 frontmatter 或者 link 来标记一条 note supersedes 另一条。关键不是具体的技术实现,而是记忆不是孤立的点,而是有关系的图这个认知。
References: