只看单个 agent,记忆好像只是“把用户说过的话保存下来,下一次搜出来”。一旦进入真实产品,边界会迅速变厚: 数据可能来自聊天、文件、网页、企业云盘、代码仓库;处理可能要排队、抽取、切块、建索引;检索结果要按用户、项目、租户隔离; 过期和删除也要能被解释。Cognee 和 Supermemory 的价值,正在于它们把这些工程责任放到了显式平台层。
场景:你要给一个团队知识助手接长期记忆
输入不再只有聊天:
会议记录、设计文档、网页、Google Drive、GitHub issue、客服历史
调用方也不止一个:
聊天 agent、搜索页、工单助手、代码助手、后台同步任务
平台层必须回答:
这份内容属于谁?
处理到哪一步了?
查询时返回画像、证据片段,还是图关系?
用户撤回数据时删到哪里才算删干净?
这就是 Cognee 和 Supermemory 不应只被当成“大一点的 RAG”的原因。它们真正暴露出来的是记忆平台的合约: 数据怎样进入、怎样被加工、怎样按边界召回、怎样让多个调用方安全地复用。
阅读契约。
读完这一篇,应该能回答三件事:Cognee 的 remember() 为什么还能落回
add()、cognify()、improve() 这条知识图谱管线;
Supermemory 的 add、profile、search 和 connectors 为什么更像产品化 context API;
以及在自己的系统里,什么时候该选“知识层”,什么时候该选“上下文平台”。
这篇可以用同一份资料来读:一份“客服升级策略”文档。放进 Cognee 时,问题是怎样把资料加工成可复用知识; 放进 Supermemory 时,问题是怎样让产品通过 API 拿到画像、搜索结果和连接器上下文。下面这张表先把两个生命周期对齐。
| 边界 | Cognee 路线 | Supermemory 路线 |
|---|---|---|
| 写入入口 | add / remember 接收文件、文本或 URL。 |
add 用 content、URL、metadata、containerTag 建立记忆对象。 |
| 处理状态 | cognify 把 dataset 加工成 graph / vector 可检索层。 |
API 暴露 queued、processing、done 等状态,托管管线负责抽取与索引。 |
| 召回输出 | search 更像面向知识层的查询结果。 |
profile 给稳定画像,search 给当前问题证据。 |
| 删除边界 | 重点是自托管数据集和知识加工产物如何治理。 | 重点是产品对象、连接器和 containerTag 范围内的数据如何撤回。 |
证据边界。 本文使用 topoteretes/cognee、 supermemoryai/supermemory 的公开 README、文档和源码。 Cognee 本地 SDK 与开源服务端代码可直接追踪;Supermemory 的托管服务内部抽取策略不可见,本文只按公开文档、SDK 示例和 API schema 描述合约。
一、为什么平台化是最后一站
1.1 前面几层的问题,到平台层会同时出现
把 Cognee 和 Supermemory 放在最后,是因为它们需要前面几层作为铺垫。先看过 Mem0 的写入取舍、Letta 的 agent state、 Graphiti 的时间图、LangMem 的执行路径、TencentDB-Agent-Memory 的上下文卸载,再读这两个项目,才容易看见它们合并了哪些责任: 长期记忆最终要被谁拥有,怎样被处理,又通过什么 API 进入这一轮模型上下文。
到平台层以后,记忆不再只是单个 agent 的能力。一个产品可能同时接入聊天记录、文档、网页、邮件、代码仓库和第三方应用; 同一条资料可能属于用户、团队、项目、数据集或租户;一次查询可能要拿用户画像、相似片段、相关文件、图关系和权限过滤后的结果。 所以 Cognee / Supermemory 的问题不是“有没有长期记忆”,而是“长期记忆怎样成为多人、多源、多调用方都能依赖的基础设施”。
1.2 平台化以后,最难的是边界而不是召回
平台化以后,记忆至少要承担四类公共责任。第一是 scope:同一套服务要区分用户、项目、数据集、租户; 第二是 process:原始内容进入以后,要经历抽取、切块、嵌入、建图或建索引; 第三是 retrieve:调用方不只要文本相似结果,还可能要图关系、用户画像、相关文档和当前可用上下文; 第四是 delete:当用户、项目或数据源撤回内容时,平台要给出可操作的删除边界。
这四类责任正好对应平台常见故障。scope 不清,会把 A 用户的材料带进 B 用户的上下文;process 不清, 调用方不知道内容是待处理、已切块、已嵌入,还是已经进入图;retrieve 不清,搜索结果会混合画像、证据和文档片段; delete 不清,连接器断开以后旧内容还可能继续影响模型。平台化的价值,是把这些责任从应用 prompt 里搬出来。
二、Cognee:先把资料变成可检索、可推理的知识层
Cognee README 给自己的定位是 open-source AI memory platform:接收任意格式数据,构建 self-hosted knowledge graph, 让 agents 跨会话 recall、connect、act with context。README 的介绍还明确提到 vector embeddings、graph reasoning、 ontology generation,说明它的目标超过向量索引:原始资料要被加工成可连接的知识层。 这些定位可以看 README 的 About Cognee。
2.1 用户看到的是 remember / recall,底下仍是管线
Cognee 的 quickstart 现在把 API 简化成四个动作:remember、recall、
forget 和 improve。示例里 remember() 既能永久写入知识图谱,
也能带 session_id 写入 session memory;recall() 则按 query 自动路由。
这一层接口看起来很轻,见 README quickstart。
源码把这个轻接口展开了。remember()
的 docstring 明确区分两条路径:没有 session_id 时是 permanent memory,会跑 add() 加
cognify();有 session_id 时先写 session cache,再在默认 self_improvement=True
时把 session 数据桥接到永久图。永久路径实际执行时,内部的 _run()
先 add(...),再 cognify(...),最后按配置调用 improve(...)。
async def remember(data, dataset_name="main_dataset", session_id=None, self_improvement=True):
if session_id:
# session memory: fast cache, then optional bridge into permanent graph
...
async def _run():
await add(data=data, dataset_name=dataset_name, ...)
cognify_result = await cognify(datasets=[dataset_name], ...)
if self_improvement:
await improve(dataset=dataset_name, user=user)
这段调用链让 Cognee 的产品接口变得容易理解:remember() 是门面,add() 负责接入,
cognify() 负责把资料转成图和向量可检索结构,improve() 负责继续增强。
调用方看到的是一个动词,平台内部保留了明确阶段。
| 用户动作 | 平台内部责任 | 为什么要拆开 |
|---|---|---|
remember(data) |
add 接入原始数据,cognify 生成知识图谱,improve 做后续增强。 |
调用方只关心“记住”,平台负责数据进入后的多阶段处理。 |
remember(data, session_id) |
先写 session cache,再把可沉淀内容桥接到永久图。 | 当前会话要快,长期知识层可以异步变好。 |
recall(query) |
按 scope、query type 和 session 信息路由到 session、graph 或 graph context。 | 同一个问题可能先查短期会话,也可能直接查永久图。 |
2.2 add 和 cognify 把“资料”变成“知识图”
add()
是第一步,负责接收文本、文件、URL、binary streams 等输入,并把它们放进 dataset,供后续处理。
它的 docstring 也把 workflow 写成 data resolution、content extraction、dataset storage、metadata tracking、
permission assignment。所以 Cognee 的边界从 query 之前就开始:平台先拥有一个明确的数据接入层。
第二步是 cognify()。
这个函数把已接入数据转成 structured knowledge graph:文档分类、文本切块、实体抽取、关系检测、图构建和内容摘要都在它的说明里。
这里的价值在于中间层:平台先把原始材料加工成更稳定的结构,后面不同 agent、不同查询策略都可以复用它。
检索端也延续这个思路。search()
的参数里有 query_type、datasets、top_k、node_name、
neighborhood、references 等控制项;它的说明列出 GRAPH_COMPLETION、RAG_COMPLETION、
CHUNKS、CYPHER、CHUNKS_LEXICAL 等搜索类型。
对调用方来说,请求已经从“给我最相似的 10 段文本”变成了“在这个知识层里选一种回答方式”。
await add(data, dataset_name="company_docs")
await cognify(
datasets=["company_docs"],
graph_model=KnowledgeGraph,
chunker=TextChunker,
)
results = await search(
query_text="How should we handle customer escalation?",
query_type=SearchType.GRAPH_COMPLETION,
datasets=["company_docs"],
include_references=True,
)
形状示例:同一份文档在 Cognee 里的生命周期
add / remember:
source = "客服升级策略..."
dataset = "company_docs"
cognify:
dataset 被切分、抽取实体和关系,并生成图 / 向量可检索层
search:
query = "客户投诉升级到谁?"
结果来自处理后的知识层,并可带回 reference
用这条链看 Cognee,就不会把它误读成单纯“上传文件后向量搜索”。add 只是把资料放入 dataset;
cognify 才开始文档分类、切块、实体关系抽取和图构建;search 则让调用方选择图回答、
RAG 回答、chunk 检索或 Cypher 查询等不同视角。
2.3 Cognee 的优势,是把公司知识变成可治理的中间层
Cognee 最适合的场景,是你有一批资料、业务文档、代码、客户历史或专家经验,希望它们经过处理后成为 可重复使用、可追踪、可自托管的知识层。README 的 use cases 也偏向 customer support agent、 SQL copilot、company brain 这类“领域知识要被多个任务复用”的问题。
代价也来自同一个设计。知识层越重,就越要关心处理延迟、数据集权限、图模型、ontology、搜索类型和运维部署。 如果你的需求只是“这个用户喜欢深色模式,下次回答时记得”,直接上完整知识图谱可能过重; 如果你的需求是“多个 agent 要长期复用一组企业知识,并且要解释关系和来源”,Cognee 这条路线就更自然。
2.4 它更像知识加工层,不是轻量偏好存储
用 Cognee 时最好先问一个问题:这份资料是否值得被加工成中间层。值得的情况通常有三个信号: 第一,资料会被多个 agent 或多个流程复用;第二,关系和来源比单段文本更重要;第三,系统需要自托管和可治理的数据处理链。 如果这三个信号都不强,Cognee 的 dataset、cognify、graph search 可能会显得笨重。
反过来说,一旦这些信号成立,Cognee 的优势就不是“多一种搜索方式”,而是让资料先离开临时 prompt,进入可重复加工的知识层。 这层可以后续继续 improve、重新 search、按 dataset 管理,也能让不同 agent 面向同一组公司知识工作。
三、Supermemory:把记忆、画像、搜索和连接器包装成 context API
Supermemory README 的定位更产品化:memory and context layer for AI。它把 memory、user profiles、hybrid search、 connectors、multi-modal extractors 放在同一张功能表里,还明确说可以给 AI products 提供 single API。 这条线的重心从手写图谱管线转向可接入的 API 面:内容进入、上下文生成、用户画像、搜索和同步,都由平台包装出来。 这些材料见 README 开头 与 Build with Supermemory。
3.1 add 会触发记忆抽取
Supermemory 文档把入口说得很直接:把 conversations、documents、files、URLs 发给 Supermemory,系统自动抽取 memories。
Add context 文档
还建议使用 customId 标识 conversation ID 或 document ID,以便更新和去重。
同一页的参数表把 content、customId、containerTag、metadata、
entityContext、dreaming 都列出来;containerTag 用来按用户或项目分组,
也是 user profiles 的必要边界。
公开 API schema 也能看到这一层边界。
MemorySchema
包含 content、metadata、source、status、summary、title、type、url、containerTags、
chunkCount 等字段。这些字段让一份内容在平台里的生命周期变得可见:
它来自哪里、处理到什么状态、属于哪些容器、被切成多少 chunks。
const MemorySchema = z.object({
customId: z.string().nullable().optional(),
content: z.string().nullable().optional(),
metadata: MetadataSchema.nullable().optional(),
source: z.string().nullable().optional(),
status: DocumentSchema.shape.status,
summary: z.string().nullable().optional(),
containerTags: z.array(z.string()).optional(),
chunkCount: z.number().default(0),
});
这个 schema 说明 add 的结果不只是“存了一段文本”。customId 负责和业务系统里的文档或会话对齐;
containerTags 负责用户、项目或空间隔离;status 和 chunkCount 让调用方知道后台处理是否完成。
文档里的 processing pipeline 进一步把这件事展开:添加内容后,Supermemory 会 validate request、store and queue、 extract content、chunk into searchable memories、embed、index。这个顺序见 Processing Pipeline。 对产品开发者来说,这意味着“记忆”已经变成后台处理队列和 API 状态机,离开了 prompt 模板里的临时数组。
Supermemory add pipeline:
validate request
-> store document and queue processing
-> extract content (OCR / transcription / web scraping)
-> chunk into searchable memories
-> embed
-> index
Progress:
GET /v3/documents/{id} -> queued | processing | done
形状示例:同一份文档在 Supermemory 里的状态变化
add:
content = "客服升级策略..."
containerTag = "support-team"
status = "queued"
worker:
status = "processing"
派生的可检索产物正在生成
later search:
status = "done"
profile / search 可返回当前问题需要的背景和证据
3.2 profile 给模型一个稳定底座,search 负责具体问题
Supermemory 的一个清晰产品判断,是把 user profile 从普通搜索里拆出来。 User Profiles 文档 把 profile 分成 static 和 dynamic:static 是长期稳定事实,比如职业、偏好、专长;dynamic 是最近上下文和临时状态。 这样做的好处很实际:模型每轮不用靠三五次搜索拼出用户是谁,先拿到一个宽背景,再用 search 补具体细节。
README 里的 API 示例也是这个形状:client.add({ content, containerTag }) 写入对话,
client.profile({ containerTag, q }) 一次返回 profile.static、
profile.dynamic 和相关 searchResults。
它把“用户是谁”和“这次问题需要什么证据”分开交给调用方,而不是混成一个结果列表。
await client.add({
content: conversation,
customId: "conv_123",
containerTag: "user_123",
});
const { profile, searchResults } = await client.profile({
containerTag: "user_123",
q: "programming style",
});
// profile.static -> 长期稳定事实
// profile.dynamic -> 最近上下文
// searchResults -> 和本轮问题相关的证据
3.3 搜索和连接器让上下文平台接近产品基础设施
搜索端,Searchv4RequestSchema
暴露 containerTag、threshold、filters、include、limit、query、rerank、rewriteQuery 等参数;
返回端的 MemorySearchResult
则包含 memory、similarity、version、parents / children context、documents。这里的 context 不再只是一段文本,
而是带相似分、版本、关系和关联文档的结果对象。
const Searchv4RequestSchema = z.object({
containerTag: z.string().optional(),
threshold: z.number().default(0.6),
filters: SearchFiltersSchema.optional(),
include: z.object({
documents: z.boolean().default(false),
summaries: z.boolean().default(false),
relatedMemories: z.boolean().default(false),
}),
limit: z.number().default(10),
q: z.string().min(1),
rerank: z.boolean().default(false),
rewriteQuery: z.boolean().default(false),
});
const MemorySearchResult = z.object({
memory: z.string(),
similarity: z.number(),
version: z.number().nullable().optional(),
context: z.object({ parents: z.array(...), children: z.array(...) }).optional(),
documents: z.array(MemorySearchDocumentSchema).optional(),
});
因此 Supermemory 的检索合约有两个层次:请求侧用 containerTag、filters 和 threshold 控制边界与召回宽度;
返回侧用 similarity、version、parents / children 和 documents 说明“为什么这条 memory 和问题有关”。
这比普通向量库的 top-k chunk 更接近产品 API。
连接器则把平台边界继续往外推。Supermemory connectors 文档列出 Google Drive、Gmail、Notion、OneDrive、GitHub、 Granola 和 Web Crawler,并说明它们会自动同步外部文档进入知识库。 How Connectors Work 把流程写成创建连接、用户授权、自动建立连接、通过 webhooks 或定时同步持续更新。 到这一步,记忆已经接近产品基础设施:它要面对 OAuth、webhook、文件版本、同步状态和用户空间。
3.4 它更像产品上下文 API,不是只给 agent 用的库
Supermemory 的强项,是把接入成本压到 API 和连接器层。产品可以先把对话、文档、URL 或文件交给平台,
再通过 profile 和 search 得到可用上下文。这样做牺牲了一部分内部可见性:
公开材料能看到请求参数、返回 shape 和处理状态,但托管服务内部怎样抽取、怎样合并、怎样重排,并不都在开源代码里。
因此它适合“我要尽快把产品接上长期上下文”的团队,而不是“我要完全掌控知识图谱每一步加工”的团队。 前者看重 connector、containerTag、profile、search 和 hosted pipeline;后者可能更倾向 Cognee 这类自托管知识层。
四、怎么选:知识层、上下文 API,还是前面几条路线
4.1 先判断系统处在哪个阶段
Cognee 和 Supermemory 都把记忆做得更“平台”,但它们的入口问题不同。Cognee 先问:我怎样把一批资料加工成可复用的知识层? Supermemory 先问:我怎样让产品用一个 API 得到记忆、画像、搜索、连接器和文件处理?这两问都成立,只是面向的系统阶段不同。
| 系统压力 | 更自然的路线 | 判断方式 |
|---|---|---|
| 想在应用和模型之间加一层长期记忆,重点是写入、去重、时间、衰减和检索排序。 | Mem0 | 先看 memory layer 的写入与检索算法。 |
| 记忆本身就是 agent state 的一部分,要和 persona、human profile、tools、messages 一起存在。 | Letta | 先看 agent state 谁拥有、怎样编译进上下文。 |
| 事实会随时间变化,旧事实不能直接删除,还要保留来源和有效期。 | Graphiti | 先看 temporal graph 和 episode provenance。 |
| 记忆写入会影响 agent 当前回答路径,需要决定同步工具还是后台整理。 | LangMem / LangGraph | 先看 hot path、background manager、store、checkpointer。 |
| 公司资料、文档、代码和专家经验要被加工成可复用知识层。 | Cognee | 先看 add、cognify、search、dataset、graph/vector 配置。 |
| 产品想快速接入记忆、画像、搜索、连接器和文件处理。 | Supermemory | 先看 add、profile、search、connectors、containerTag 边界。 |
如果把这个系列压成一句话,就是:不要先问“用哪个向量库”。先问这份历史属于谁,是证据、画像、关系、工作流状态、知识层, 还是当前模型上下文。Cognee 和 Supermemory 把问题推进到了平台层,也提醒我们:长期记忆做大以后,难点常常在数据来源、 处理责任、检索合约和删除边界,而不只是把内容搜出来。