Agent memory 需要自己的 OpenTelemetry 时刻
Agent memory needs its OpenTelemetry moment
当前编码工具的 Agent 记忆分散在 AGENTS.md、CLAUDE.md、Cursor 规则、Anthropic memory tool、GitHub Copilot Memory 和 memory MCP server 等多种互不兼容的格式中,一个工具学到的经验无法被另一个工具读取。
数一数你机器上有多少种记忆格式
列出你的编码工具保存它们所“记住”的内容的每一个地方。如今一个典型的配置是:
- 大多数仓库里有一个
AGENTS.md或CLAUDE.md,少数几个里有.cursor/rules/*.mdc - 一个 agent 通过 Anthropic 的 memory tool 把文件写入
/memories目录 - Copilot 在 GitHub 一侧保存关于每个仓库的事实
- 一个 memory MCP server 保存一个 JSONL 知识图谱
这是四种不同的形态,而且它们没有一个能读取其他格式。你的 CI agent 学到的一条经验,会留在写下它的那个工具里。你的编辑器 agent 读不到它,你下一个尝试的工具也读不到。
每种格式单独来看都合理。合在一起,它们一次又一次地重建同一个小想法:一个 agent 留给未来自己的笔记,存放在某个地址上,在一段时间内有效。
而且这个列表还在不断变长。逛逛 r/ClaudeAI、r/LocalLLaMA 或 r/cursor,你会看到源源不断的“我为我的 agent 构建了一个记忆层”的帖子,每个都有自己的存储、自己的 schema 和自己的 MCP 工具。这有力地证明问题确实存在:人们反复被它困扰,以至于要动手造点东西。但每一个新方案都多增加了一种其他东西读不了的格式。问题不在于缺工具,而在于缺一个共识,而共识只能来自社区的共同协作。
我参与构建了这类工具中的一个,LoreKit,它是开源的。这不是在推销说 LoreKit 已经解决了记忆问题。它的格式只是若干提案之一,本身也有不足。重点在于,现在正是就一种共享形态达成共识的时刻,而且另一个领域已经展示了该怎么做。
我们以前见过这一幕
2019 年之前,每个可观测性厂商都发布自己的 agent、自己的埋点库和自己的数据格式。更换厂商意味着要重新为代码做埋点。两个开源项目 OpenTracing 和 OpenCensus 试图解决这个问题,但它们彼此也在竞争。
2019 年,它们合并成了 OpenTelemetry。真正重要的是厂商们同意不再竞争的那些东西:
- 一个数据模型:span、metric 和 log record 分别是什么。
- 语义约定:像
service.name和http.*这样的共享名称。 - 一个协议:OTLP,一种发送数据的方式。
- 参考实现:共享的 SDK 和 Collector。
厂商们继续在它们用数据做什么上竞争:存储、查询、分析。用户只需埋点一次。我每天在 Dash0 和 OpenTelemetry 打交道,正是这个共识让整个工具生态能够读取彼此的数据。
Agent 记忆正处在可观测性在 2019 年之前的位置。时机很好:这些格式还很年轻,来得及改变,而且已经有一个中立的归宿来承载 agent 标准。MCP 和 AGENTS.md 都隶属于 Linux 基金会的 Agentic AI Foundation。
形态巡览
这些变化很快,所以请把细节当作 2026 年末的一个快照。
| 家族 | 示例 | 记忆单元 | 寻址方式 | 遗忘方式 |
|---|---|---|---|---|
| 指令文件 | AGENTS.md、CLAUDE.md、Cursor .mdc 规则 | 一个完整的 Markdown 文件 | 文件路径(Cursor 还要加上 globs) | 从不。由人来编辑 |
| Agent 管理的文件 | Anthropic 的 memory tool | /memories 下的一个文件 | 模型选择的路径 | 从不,除非模型删除它 |
| 托管的仓库事实 | GitHub Copilot Memory | 带代码引用的事实 | 一个仓库 | 闲置 28 天后删除 |
| 上下文块 | Letta 核心记忆 | 一个带有字符 limit 的带标签区块 | 代理上的一个 label | 从不。始终在上下文中 |
| 提取的事实 | Mem0 | 服务从消息中提取的事实 | user_id / agent_id / run_id / app_id | 可选的过期日期 |
| 命名空间存储 | LangGraph BaseStore | 一个 JSON value 字典 | 一个 key 元组 + namespace | 可选的 TTL,在读取该项时重置(默认情况下) |
| 知识图谱 | MCP 参考记忆服务器 | 实体、关系、观察 | 实体名称 | 从不 |
| 时间图谱 | Graphiti / Zep | 图边上的一条事实 | 实体 + 边 | 事实被作废而非删除,基于两条时间线 |
| 寻址记录 | LoreKit | 带有作用域、键和生命周期的记录 | 一个作用域字符串 + key | 从不,除非设置了 TTL |
其中一些做对了一些事情,共享规范应当保留。Copilot Memory 将可对照代码核验的引用与默认遗忘相结合,尽管它被锁定在一个产品内。LangGraph 展示了核心可以有多小:put(namespace, key, value)。Graphiti 正确地建模了时间,为事实何时为真和何时被记录分别设置了时间线。而 AGENTS.md 表明,位于已知路径的普通文件可以成为一种标准。
已经存在的提案
已经有人开始着手这件事。MacPaw Research 的 Portable Memory 是一个 .mem 包,具有字节可复现的序列化、删除墓碑和可选签名;其作者表示它尚未被广泛采用。Open Memory Protocol 是 2026 年 4 月的一份草案,用于以带清单的 ZIP 形式在平台之间迁移对话及从中衍生的记忆。Cognee 的 COGX 格式可从 Mem0、Letta 和 Zep 导入。
这些主要解决的是导出:将一个人的记忆从供应商 A 迁移到供应商 B。编码工具还有第二个未解决的问题:实时寻址。当一个 CI 任务、一个编辑器代理和一个审查机器人同时在同一仓库中工作时,它们如何读写同一个位置并就其含义达成一致?一个完整的规范需要两者兼备。
剥去品牌包装,每种格式对同样四个问题的回答各不相同:记忆在何处为真、其身份是什么(第二次写入是更新它还是复制它?)、它说了什么,以及它何时不再为真。没有人否认这些很重要。工具们只是在答案上存在分歧,OpenTelemetry 最初也是如此。
有一个真正的分叉点:谁来写入记忆。在指令文件中,是人。在记忆工具、Letta 和 LoreKit 中,是模型。在 Mem0 和 Graphiti 中,由服务从对话中提取事实。规范不需要选择其中一个。它需要记录是哪一个,以便读者知道该在多大程度上信任所读到的内容。
以下大致是一条记录作为文件可能的样子。它说明了数据模型;字段名并非提案:
---
spec: agent-memory/0.1
id: 8f0c2a6e-4b1d-4c7a-9e2f-3a5b6c7d8e9f
address: { level: repo, value: github.com/acme/checkout }
key: tests-need-local-postgres
kind: lesson
written_by: { type: agent, name: claude-code }
content_type: text/markdown
lifecycle: { expires_at: null, extended_by: write }
attributes: { vcs.pr: 482, ci.run_url: "https://ci.example/runs/123" }
---
Integration tests fail with `ECONNREFUSED 127.0.0.1:5432` unless Postgres
is already running. Start it before `pnpm test`:
docker compose up -d db
The test setup does not start it for you.frontmatter 是信封:address 和 key 说明它在何处为真,id 是它的身份,lifecycle 说明它何时失效,written_by 回答分叉问题。其下的 Markdown 就是记忆本身,content_type 告诉读者如何对待它。工具需要的其他内容都放在 attributes 中,位于其他工具可以忽略的命名空间下。同一条记录同样可以很好地序列化为 JSON,供想要通过网络传输它的工具使用。
围绕这条记录,规范会镜像 OpenTelemetry 的分层:
- 约定:地址层级(
global、project、repo、branch,以及 monorepo 所需的任何层级)、种类和属性命名空间(vcs.*、ci.*、agent.*)的共享名称,放在一个带版本的注册表中。 - 一份契约:若干操作(写入、读取、列出、搜索、归档),具有固定的输入和输出,通过 MCP 暴露。许多记忆服务器现在提供 MCP 接口,但每个都暴露不同的工具,含义也各不相同。
- 一致性测试取代参考实现:对一条记录做往返测试并检查没有丢失任何内容,检查未知属性在重写后仍然保留,检查过期行为符合声明。
哪些内容留在外面同样重要:存储、排序、嵌入、用户界面。那才是工具应该竞争的地方。规范应该放在某个中立的地方,而不是 LoreKit 的仓库或任何单一供应商的仓库中。
怀疑者会说什么
“你做了一个记忆工具,所以你当然想要一个按它的样子塑造的标准。” 有道理。这正是 LoreKit 在表中只是一行、而不是模板的原因。如果共享规范看起来不同,LoreKit 也应该照样采纳它。
“MCP 已经是标准了。” MCP 标准化的是调用,不是记录。OpenTelemetry 既需要协议,也需要数据模型。记忆两者都需要。
“共享记忆是提示注入的通道。” 是的。智能体读取的任何内容都可能操纵它,而共享记忆扩大了可以写入它的人群。规范应该让这一点可见:记录每条记忆是谁写的,允许签名(Portable Memory 已经这样做了),并让记录指向它所依赖的代码,以便读者可以检查该代码是否发生了变化。没有任何格式能让投毒变得不可能。
“又一个标准不会解决碎片化。” 那就是 xkcd 927,而且这是最有力的反对意见。我的回答是 OpenTelemetry 式的:共识是在现有项目合并时达成的,而不是在有人又添加一个项目时达成的。这里的工作也是一样:吸收现有提案和工具各自做对的地方,并就它们共享的部分达成一致。
开放问题
我不知道这些问题的答案,而且我更愿意公开地把它们弄清楚:
- 哪些地址层级? Monorepo 想要一个介于
repo和branch之间的层级。层级应该是一个固定列表还是约定? - 遗忘应该是默认行为吗? Copilot 默认遗忘,LoreKit 不遗忘,而 LangGraph 在读取时延长寿命。
- 记录应该指向它所依赖的代码吗? 这是防止记忆过时的最佳保护,但它把记录绑定到了代码托管方。
- 谁应该来协调? 一个工作组、一个基金会,还是一份人们向其提交变更的规范草案?
如果你构建了表中的任何工具,或者写了其中一份提案,我想和你交流一下。LoreKit 的 schema 和磁盘格式以 MIT 许可证发布,作为一个具体的输入。要查看真实记录,LoreKit 的离线存储会写出纯 Markdown 文件,你可以打开、grep 和 diff:
npx @lorekit/cli install将它们与其他工具所写的内容进行比较,并告诉我一个共享格式需要具备哪些它们目前都还没有的东西。
来源:Hacker News · lorekit.io