代理记忆需要 OpenTelemetry 的时刻
Agent memory needs its OpenTelemetry moment
目前机器上的内存格式多样,不同编码工具使用的记忆存储格式各异,如 Markdown 文件、Anthropic 的内存工具、GitHub Copilot 等,这些格式之间缺乏通用性,导致信息孤岛现象
统计你机器上的内存格式
列出你的编程工具保存它们所 "记住" 的所有地方。如今的典型设置是:
AGENTS.md或CLAUDE.md在大多数仓库中,以及.cursor/rules/*.mdc在少数仓库中- 一个代理通过 Anthropic 的内存工具将文件写入
/memories目录 - Copilot 在 GitHub 的一面保存每个仓库的事实
- 一个内存 MCP 服务器保存一个 JSONL 知识图谱
这是四种不同的形状,而且 它们都不能读取其他形状。你的 CI 代理学到的教训会停留在它被写入的地方。你的编辑代理无法读取它,下一个你尝试的工具也无法读取它
每种格式在其自身上都是合理的。一起,它们反复重建同一个小的想法:一个代理留给其未来的自己的笔记,存储在某个地址,一段时间内为真。
这个列表还在不断增长。浏览 r/ClaudeAI、r/LocalLLaMA 或 r/cursor,你会发现一系列 "我为我代理构建了一个内存层" 的帖子,每个帖子都有自己的存储、自己的模式和自己 MCP 工具。这是问题的真实证据:人们不断地遇到这个问题,以至于他们开始构建解决方案。但每个新的解决方案都增加了一种其他任何东西都无法读取的格式。问题不在于缺少工具。而在于缺少共识,而这种共识只能来自共同处理该问题的社区
我构建了其中一种工具,LoreKit,它是开源的。这不是一个 LoreKit 已经解决了内存问题的推销。它的格式是几种提议中的一种,它自己也有缺陷。要点是 现在是时候就一个共享形状达成共识,而另一个领域已经展示了如何做到这一点
我们以前见过这种情况
在 2019 年之前,每个可观察性供应商都发送它自己的代理、它自己的仪器库和它自己的数据格式。更换供应商意味着再次为你的代码进行仪器化。两个开源项目,OpenTracing 和 OpenCensus,试图解决这个问题,并且它们之间也相互竞争
在 2019 年它们合并为 OpenTelemetry。重要的是供应商同意停止竞争的东西:
- 数据模型:跨度、指标和日志记录是什么
- 语义约定:共享名称,如
service.name和http.* - 协议:OTLP,发送数据的一种方式
- 参考实现:共享 SDK 和 Collector
供应商继续竞争他们 做 数据的事情:存储、查询、分析。用户只仪器化一次。我在 Dash0 每天都与 OpenTelemetry 合作,这种共识是为什么一个完整的工具生态系统可以读取彼此的数据
代理内存就是 2019 年之前可观察性的地方。时机很好:格式足够年轻可以改变,而且已经有了一个代理标准的中立家园。MCP 和 AGENTS.md 都位于 Linux 基金会的 Agentic AI 基金会之下
形状的巡礼
这些变化很快,所以将细节视为 2026 年底的一个快照
| 家庭 | 示例 | 内存的单位 | 由…管理 | 遗忘 |
|---|---|---|---|---|
| 指令文件 | AGENTS.md、CLAUDE.md、Cursor .mdc 规则 | 整个 Markdown 文件 | 文件路径(加上 globs 对于 Cursor) | 从不。一个人编辑它 |
| 代理管理的文件 | Anthropic 的内存工具 | /memories 下面的一个文件 | 模型选择的路径 | 从不,除非模型删除它 |
| 托管仓库事实 | GitHub Copilot Memory | 一个带有代码引用的事实 | 一个仓库 | 28 天未使用后删除 |
| 上下文块 | 核心内存 | 一个带有字符limit的标记块 | 一个label在代理上 | 绝不。始终在上下文中 |
| 提取的事实 | Mem0 | 服务从消息中提取的事实 | user_id / agent_id / run_id / app_id | 可选的过期日期 |
| 命名空间存储 | LangGraph BaseStore | 一个JSON value字典 | 一个namespace元组 + key | 可选的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导入。
这些主要解决 导出:将一个人的记忆从一个供应商移动到另一个供应商。编码工具还有一个第二、开放的问题: 实时寻址。当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.前文是信封:address和key说明其适用范围,id是其身份标识,lifecycle说明其何时失效,written_by回答其分支问题。其下的Markdown是记忆本身,content_type告诉读者如何处理它。任何工具所需的其他内容都放在attributes中,该命名空间其他工具可以忽略。对于希望将记录通过网络传输的工具来说,相同的记录序列化为JSON同样有效。
围绕该记录,规范将镜像OpenTelemetry的层级:
- 约定:地址层级(
global、project、repo、branch和单一代码库需要的任何层级)的通用名称、类型的通用名称以及属性命名空间(vcs.*、ci.*、agent.*)在一个版本化的注册表中, - 契约:几个具有固定输入和输出的操作(写入、读取、列出、搜索、归档),通过MCP公开。现在许多记忆服务器提供MCP接口,但每个接口都暴露不同的工具,具有不同的含义。
- 符合性测试代替参考实现:循环记录并检查是否有任何内容丢失,检查未知属性是否在重写后幸存,检查过期行为是否符合声明。
留在外部的内容同样重要:存储、排序、嵌入、用户界面。这就是工具应该竞争的地方。而且规范应该存放在一个中立的地方,而不是LoreKit的仓库或任何单一供应商的仓库中。
一个怀疑者的观点
"你构建了一个记忆工具,所以当然你希望标准符合它。" 公平。这就是为什么LoreKit是表格中的一行而不是模板。如果共享规范看起来不同,LoreKit应该无论如何都采用它。
"MCP已经是标准了。" MCP标准化了调用,而不是记录。OpenTelemetry需要一个协议和一个数据模型。记忆也需要两者。
"共享记忆是一个提示注入通道。" 是的。代理读取的任何内容都可以引导它,而共享记忆扩大了谁可以写入它的范围。规范应该使这一点可见:记录每个记忆的写入者,允许签名(Portable Memory已经做到了),并允许记录指向它所依赖的代码,以便读者可以检查该代码是否已更改。没有格式可以防止中毒。
"另一个标准不会修复碎片化。" 这是xkcd 927,也是最强的反对意见。我的回答是OpenTelemetry的:协议的达成是在现有项目合并时,而不是在有人添加另一个项目时。这里的任务是相同的:取现有提案和工具各自做对的,并在它们共享的部分上达成一致。
开放问题
我不知道这些问题的答案,并且宁愿在公开场合解决它们:
- 哪些地址层级? 单一代码库希望在
repo和branch之间需要一个层级。层级应该是固定列表还是约定? - 遗忘应该是默认的吗? Copilot默认遗忘,LoreKit不遗忘,LangGraph在读取时延长寿命。
- 记录应该指向它所依赖的代码吗? 这是防止陈旧记忆的最佳保护,但它将记录与代码主机绑定。
- 谁应该协调? 工作组、基金会,还是人们发送更改的草案规范?
如果你构建了表格中的任何工具,或者撰写了其中的一项提案,我很想比较笔记。LoreKit的架构和磁盘格式在MIT许可证下作为具体输入。要查看真实记录,LoreKit的离线存储将普通Markdown文件写入可打开、grep和diff:
npx @lorekit/cli install将它们与你的其他工具写出的内容进行比较,并告诉我一个共享格式需要什么,而它们目前还没有的。
来源:Hacker News · lorekit.io