puppyone vs Mem0 / Letta:runtime 记忆 vs 长程的、文件形态的 Agent 上下文

2026年4月23日puppyone team

TL;DR

  • Mem0 / Letta 解决 runtime 记忆。 一段对话里、一个 Agent 进程里,让 LLM 记住之前说了什么、抽出来的事实、用户偏好。它们是挂在聊天循环上的"embedding + 摘要"层。
  • puppyone 解决长程的、组织级的、文件形态的上下文。 跨会话、跨 Agent、跨同事、跨产品。它是一个版本化的文件系统,不是一个记忆缓存。
  • "Memory" 这个词在两边各干各的事 —— 指的是不同的东西。Mem0/Letta 给一个 Agent 更好的短到中期工作记忆。puppyone 给多个 Agent 一个共享的、持久的、版本化的工作空间。
  • 大多数生产部署两者都要:Agent 循环里跑 Mem0/Letta(让 LLM 不忘你刚说过的话),底下垫着 puppyone(让计划、报告、ingest 的数据、输出永远活着,并且对其他每个 Agent 可见)。

老实话

这是房间里"memory"这个词最容易误导人的对比页。

Mem0 / Letta 说"memory"的时候,意思是:这个循环里的 LLM 应该记住之前发生的事。用户三轮前告诉 Agent 自己吃素 —— 下一轮不应该推荐牛排。跨对话,Agent 应该记住"这个用户喜欢简洁回答"。这真的有用,是难题,Mem0 和 Letta 做得好。

puppyone 说"context"的时候,意思是:Agent(任何 Agent,不只是这一个)应该有一个持久、有 scope、版本化的工作空间。不是"你三轮前说了什么",而是"规格写了什么、昨天那个研究 Agent 写了什么、客户 onboarding 文档当前 canonical 版本是什么、Cursor 在 14:32 commit 了什么"。这是不同层的不同问题。

可以只用 Mem0 不用 puppyone。可以只用 puppyone 不用 Mem0。生产里大部分两个都用,因为它们解决不同的失败。

并排对比

维度Mem0 / Lettapuppyone
"memory" 指什么循环内 / 跨对话 LLM 该回想的内容Agent 和人共同操作的整个共享工作空间
生命周期短到中(轮、session、有时几周)长(月、年;除非回滚否则永久)
基本单位记忆条目 / 事实 / 摘要 / embedding文件,带完整内容和历史
主要用户一个应用聊天循环里的一个 Agent跨产品跨时间的多个 Agent + 人
存储形状向量库 + 结构化记忆 schema文件系统(markdown / JSON / CSV / 任何东西)
原生接口SDK 调用(memory.addmemory.searchmemory.updateBash、MCP、REST、sandbox 挂载
多 Agent 协作per-agent 记忆;要共享需要显式设计原生 —— 同一个工作空间,per-agent 路径 scope
审计 / 版本控制限于记忆 CRUD 日志按 Agent 身份的 Git 风格 commit、完整 diff、回滚
SaaS 接入不是它的活 —— 你喂它对话轮内置:Notion、Slack、Gmail、Postgres 等连接器
范围在聊天循环之内整个 Agent 栈之上
真正擅长"别忘了用户告诉过你什么""成为每个 Agent 都从中读、向里写的持久底座"

什么时候该用 Mem0 / Letta(而不是 puppyone)

要解决的问题是 Agent 内的对话连续性的时候,用 Mem0 或 Letta:

  • 跨会话需要记住用户偏好的聊天机器人。
  • 不应该重复问你已经告诉过它的事的个人助理。
  • 长对话里你想让抽出来的事实在 context window 压力下还活着。
  • 关于用户的、活在Agent 循环里的记忆 —— 偏好、历史、学到的模式。

这是真实的难题。puppyone 不为这个建。我们没有 LLM-aware 的抽取流水线,不会自动总结对话轮,也不会按终端用户做记忆 scope。Mem0 和 Letta 这块做得好,去用。

什么时候该用 puppyone(而不是 Mem0 / Letta)

要解决的问题是多 Agent 多人共享、持久、文件形态的上下文的时候,用 puppyone:

  • 多 Agent 工作流,researcher → planner → executor 都需要读写同一个工作空间。
  • 长跑 Agent 产文件(报告、计划、转换数据),需要跨 session、跨重启、跨 Agent 替换还活着。
  • 一组人 + Agent 在协作,每个人都要看到"这份规格的最新版是什么、什么时候改的、谁改的"。
  • 应该作为文件让每个 Agent 用、不该每个对话重新抓的 SaaS 数据(Slack / Notion / Postgres)。
  • 任何想要在存储层就有 per-agent 权限和审计的地方 —— Mem0/Letta 不天生支持"这个 Agent 能读 /research 但不能读 /finance"。

如果你一直在把每个项目产物塞进一个向量化的记忆库、看着它膨胀成搜不动的摘要堆 —— 你在用记忆层干上下文的活。形状不对。

什么时候两个一起用(非常常见)

真正的生产 Agent 栈里:

  1. Mem0 / Letta 活在每个 Agent 的运行循环里。 它处理"这场对话进行了 80 轮,LLM 还该回想什么"的问题。用户偏好、对话内事实、最近意图 —— 全在 Mem0/Letta。
  2. puppyone 活在它们底下作为工作空间。 规格、ingest 的 SaaS 数据、生成报告、计划、多步输出、研究产物 —— 全部以版本化文件存在。
  3. Agent 通过 MCP / Bash / REST 从 puppyone 读 "关于世界 / 项目 / 工作空间真实的事情",从 Mem0/Letta 读"这场对话确立了什么"。
  4. Agent 把持久产物写回 puppyone(让下一个 Agent / 下一次 session / 下一个同事看得见),把对话线程状态留给 Mem0/Letta。
  5. Mem0/Letta 的记忆条目本身可以持久化到 puppyone,如果你想跨栈做版本化和审计 —— 一些团队为合规这么做。

干净的分工:Mem0/Letta = "循环内 LLM 该记住的事"puppyone = "循环外世界长什么样"

"可是 Letta 有文件,Mem0 有结构化存储,那不就是 puppyone 吗?"

不太一样,差异重要:

  • Letta 有 core_memory 概念和可编辑的 scratchpad —— 那是一个 Agent 进程内的工作记忆原语,不是跨多个 Agent 多个工具(Cursor、n8n、你的自建代码)跨时间共享的工作空间。
  • Mem0 的"memory"是抽出来事实的结构化数据库 —— 围绕 memory.search 返回相关条目建,不是围绕 cat /specs/architecture.md 返回一份规格的 canonical 内容建。
  • 它们都不是围绕:per-agent 路径 scope、存储层写即 commitmaterialise 成文件的 SaaS 连接器、或者同一个工作空间同时被 MCP 兼容的 IDE、用 REST 的 n8n flow、用 Bash 的 sandbox Agent、Python 脚本一起操作 —— 这些建的。

你完全可以让 Letta 或 Mem0 作为 写入 puppyone 的一方 —— Agent 用 Letta 管自己的工作记忆,再把重要产物(最终报告、转换数据集、决策)以文件形式 commit 到 puppyone,给栈里其他人。

"向量数据库呢?那不也是记忆?"

向量库(Pinecone / Zilliz / FAISS / pgvector)是检索原语。Mem0/Letta 在它们之上建记忆抽象。puppyone 在另一层:文件的 canonical 存储,embedding 是派生索引,想放哪里都行。

我们另外有一篇 puppyone vs 向量数据库 详聊这个。短版:向量找文档;puppyone 存文档。

实际怎么集成

不存在迁移。Mem0 / Letta 留在你 Agent 代码里。

  1. 保留你已有的记忆层。 在用 Mem0 或 Letta 的话,原地不动。
  2. 持久产物从记忆条目里搬到 puppyone 文件。 计划、报告、结构化输出、决策 —— 任何六个月后还想读的东西 —— 都是文件,不是记忆条目。
  3. 通过 MCP / SDK 把 puppyone 接进 Agent。 现在 Agent 两边都有:Mem0/Letta 管"我们说过什么" + puppyone 管"我们做了什么、什么是真的"。
  4. 多 Agent 写入时给 per-agent Access Point —— researcher 写 /research,planner 写 /plans,executor 写 /output。Mem0/Letta 仍然管各自 Agent 的工作记忆。
  5. 可选:把 Mem0/Letta 记忆快照导出到 puppyone 做审计 / 调试 —— 当你想问"这个 Agent 做那个决策时它的记忆长什么样"很有用。

一个月后边界会很清楚:易逝的对话状态在 Mem0/Letta;持久、共享、版本化的文件在 puppyone。

FAQ

puppyone 替代 Mem0 或 Letta 吗? 不。我们不做对话事实抽取或循环内的记忆管理。Mem0 和 Letta 做这个做得好。我们坐在底下,撑着长程共享上下文。

puppyone 能作为 Letta 或 Mem0 的存储后端吗? 可以把记忆快照持久化到 puppyone 做审计和版本历史,可以。我们不是它们内部存储的 drop-in 替代。

puppyone 为什么不做自动记忆抽取? 因为那是 per-agent / per-application 的事,最好在 Agent 循环里做。我们想做底座,不想做大脑。加抽取要么会偏向我们抽什么(迎合一个 Agent 的需求),要么让我们作为通用底座变差。

我 Agent 已经有 Mem0 了,为什么还要 puppyone? 因为 Mem0 装的是 LLM 该记住的内容。它不装 Agent 该跟着走的规格、Agent 该读的代码库、Agent 昨天写完今天同事要看的报告、应该变成文件的 Slack 线程。这些是 puppyone 的活。

puppyone 有语义搜索吗? puppyone 是文件底座;embedding + 语义搜索是上面一层,我们把"在 puppyone 内容上接一个向量库(或 pgvector)"做得很简单。我们不内置向量库,因为大多数团队要么已经有一个,要么想自己选。

再说一遍 TL;DR

Mem0 / Letta = Agent 循环里的记忆。puppyone = Agent 操作的世界。别把一个塞到另一个该在的位置。生产里大多数两者都跑,"我们刚说了什么"和"什么是真的"之间留一道清楚的线。

给你的 Agent 两边都给:循环里的工作记忆 + 循环外的持久工作空间。Get started