你的记忆系统无需决定 Agent 看什么,由 Agent 自己决定。

@S_BatMan
英语1个月前 · 2026年6月02日
906K
219
21
6
128

TL;DR

本文详细介绍了行业从自动上下文注入向基于工具的记忆系统的转变,解释了赋予 Agent 自主检索能力如何解决成本、相关性及调试等问题。

从注入式 RAG 到基于工具的记忆的悄然转变、自动注入的四种失败模式,以及为什么最便宜的修复也是影响最深远的一个。

我研究记忆如何到达模型已经有一段时间了。在开展这项研究之前,我反复遇到的一个假设是,Agent 记忆的难点在于检索质量。普遍的想法是,只要能获取正确的块,剩下的就只是管道问题。

这个假设只说对了一半。检索质量固然重要。但将这些块传递给模型的机制更为关键,而业界已经悄悄地在这一点上反转了立场,只是大多数人没有注意到。成熟的系统都汇聚到了同一个形态上:给 Agent 提供记忆工具,然后由 Agent 自己决定何时以及如何使用它们。中间件不再是一个预测 Agent 需求的角色,而是 Agent 调用的一个服务。

这可不是一个微小的变化。它发生得几乎悄无声息。如果你在 2026 年还在构建注入式的记忆系统,那你是在做无用功。

注入式是什么样子的

早期的 RAG 是注入式的。这个模式简单到可以放在一张幻灯片上:

  1. 对语料库中的每一个文档进行嵌入。
  2. 在每次用户对话轮次中,对查询进行嵌入。
  3. 执行 top-K 近邻搜索。
  4. 将 K 个结果拼接到系统提示中。
  5. 将生成的整个数据块发送给模型。

模型从不询问上下文。中间件决定什么是相关的。模型看到的结果是一个既成事实,被前置在用户的实际问题之前。这就是自动上下文注入。从大约 2023 年到 2024 年,它一直是 RAG 的主流形态,并且现在大多数团队说“我们加了 RAG”而没有进一步说明时,指的仍然是它。

它在某种程度上是有效的。失效的那个点,就是 Agent 需要做一些中间件未能预料到的事情的时候。

具体感受一下其中的区别。假设用户有一个记忆存储,其中包含关于上周某个部署事故的笔记、一个偏好简短回复的长期设定、一份关于认证重构的未完成设计文档,以及昨天站立会议的记录,其中提到认证工作已被降级优先处理。用户问:“认证重构进行到哪了?”

在注入模式下,中间件嵌入查询、搜索、并将 top-K 个块拼接起来。模型拿到的是来自事故复盘报告中关于认证部分回滚的一个块、设计文档的一个块、站立会议中提到降级优先的一个块,以及其他五个恰好与“认证”这个词有不同程度相关性的块。模型读完这八个块。然后回答。用户看到答案。没人看到那八个块。

在工具模式下,Agent 阅读问题,决定需要检查记忆,用自己构建的查询调用搜索工具,获得标识符和预览,阅读预览,决定哪些记录是相关的,然后只获取那些记录。追踪显示每一步。Agent 检索了两条记录,而不是八条。是它自己选择的。成本也反映了这个选择。

区别不在于检索质量。两次追踪中都存在同样的块。区别在于代理权:谁决定了模型看到什么。

注入的四种失败模式

1. 无关块的税收

注入式在每个轮次都会支付检索成本,无论记忆是否相关。如果用户问“现在几点了?”,中间件仍然会嵌入查询、搜索、将 K 个块拼入提示。模型仍然会处理它们。所有这些工作都没有必要。在一个每天处理数千个 Agent 轮次的系统上,这种浪费是真实存在的,而且会不断累积。

2. 错误-K 问题

Top-K 检索返回与查询嵌入最相似的 K 个块。但相似于查询并不等同于相关于任务。中间件无法区分这一点,因为它不理解任务。它理解的是查询字符串。模型可以区分,但当模型看到这些块时,它们已经在提示里了。模型可以忽略它们,但无法取消检索它们。注意力成本已经支付了。

3. 跟进阻塞

注入是一次性操作。中间件每轮注入一次。如果模型读了注入的块,发现还需要其他东西——另一个记忆条目、一份相关文档、一段不在 top-K 里的先前的对话——它没办法获取。检索层已经触发并关闭了。Agent 只能被困在给它提供的东西里。

这是实践中伤害最大的失败模式。Agent 拥有记忆,但却无法触及。

4. 不透明的追踪

当记忆被注入时,对话追踪不会显示 Agent 看了什么。它显示的是中间件决定给 Agent 什么。如果 Agent 因为被提供了错误的块而给出了错误答案,调试就意味着要重建中间件检索了什么以及为什么。追踪对于最需要它的人——试图修复系统的开发者来说——是不透明的。

工具模式是什么样子的

基于工具的模式颠倒了这种关系。Agent 被赋予了命名的操作,这些操作可以读取(有时写入)记忆存储。Agent 决定何时调用它们。中间件变成了一个服务,而不是一个守门人。

在我研究的 19 个系统中,成熟的系统都汇聚到了这种形态上。Supermemory、Graymatter、OpenContext、Tolaria、second-brain、MemoryOS、GitNexus、mem9 都将记忆暴露为工具表面,而不是自动注入。那些更接近注入的系统,被业界视为先前的技术状态,而非当前状态。

工具表面在大小和形态上各有不同,而这种差异本身就很有启发性。

小型端:Graymatter

Graymatter 的 MCP 服务器暴露了五个工具。其中三个是核心:RememberRecallmemory_reflect。最后一个最具表现力:它允许 Agent 更新现有事实、忘记现有事实或将事实链接到知识图谱实体。Agent 在会话期间自行维护记忆,而不是由记忆层自行维护。

小就是卖点。README 明确指出:“表面很小,这本身就是卖点。” Agent 作者可以掌握整个记忆 API,而 LLM 则可以在其提示中保存整个工具描述。任何更复杂的东西都会变成需要额外教授的东西。

中型端:Supermemory 和 OpenContext

Supermemory 的 MCP 服务器暴露了四个工具,外加两个资源和一个提示。memory 工具处理保存和删除。recall 工具处理搜索。激进的工具描述值得一提:“不要使用任何其他记忆工具,只用这一个。” 这是对工具描述本身进行提示工程,一个 hack,但是有效的 hack。工具描述本身就是提示,对待系统提示的同样用心也应该用在工具描述上。

OpenContext 注册了九个工具,分为三组:读取、写入和元数据。写入组故意不完整。MCP 服务器可以注册一个空文件,但不能写入其内容。Agent 使用已有的文件编辑工具直接编辑文件。这是 19 个系统中,有意拆分读写路径的最清晰例子,让记忆层负责发现和解析,同时让 Agent 自己的工具负责变更。

OpenContext 还在工具表面本身编码了成本治理。没有 oc_index_build MCP 工具,因为构建索引会调用付费的嵌入 API。索引完全由 CLI 驱动。Agent 在安装时读取的技能文本也强化了这一点:“除非用户明确批准,否则不要运行它。” 政策放在工具表面,而不是放在带外文档中。

窄设计端:Tolaria

Tolaria 的立场值得引用:“Agent 拥有完全的系统 shell 访问权限。这些 MCP 工具提供了原生工具无法替代的 Tolaria 特定能力。” 六个工具,全部是 vault 感知的读取和 UI 导向操作。Agent 通过其原生文件系统工具拥有写入路径。Tolaria 拥有 vault 感知的读取路径和 UI 表面。这种不对称是故意的,也是保持工具表面让 LLM 可理解的关键。

激进端:second-brain

这是光谱上最极端的点。Agent 没有得到预制的召回动词。它得到的是数据库本身:一组对 SQLite 记忆存储的只读 SELECT 和 PRAGMA 工具,表级作用域在 SQLite C-API 授权器钩子处强制执行。Agent 编写 SQL。如果需要不同的连接、不同的过滤、不同的投影,它就写一个不同的查询。

second-brain 还为常见情况提供了预制的召回工具:hybrid_searchlexical_searchsemantic_search。这些与原始 SQL 工具并存。Agent 可以在够用时使用便捷动词,不够用时降级到 SQL。工具表面不必是二选一。它可以同时提供两者,让 Agent 选择。

MemoryOS:三个工具,隐藏的层级

MemoryOS 将其三层层级存储封装在三个工具后面:add_memoryretrieve_memoryget_user_profile。Agent 不需要知道短期、中期和长期这三个层级。它调用 retrieve_memory(query),系统就会返回拥有数据的层级中的最佳匹配。层级的复杂性保留在记忆引擎内部。工具表面保持小巧。

内部模型可以尽可能复杂——热门门控提升、对话链重建、并行两阶段检索——所有这些复杂性都不会泄露到 Agent 的工具描述中。如果引擎想在后台重组其层级,Agent 不必知道。

mem9:相同的表面,多种封装

mem9 发布了一个 REST API,并通过多个 Agent 框架的插件来呈现它。插件形态五花八门——Claude Code 插件是通过 curl 调用 REST API 的 bash 钩子,Codex 插件是带有客户端对话解析的 Node 钩子——但底层的 Agent 表面是相同的五六个操作:storesearchgetupdateremove,外加一个用于整个对话交接的 ingest

相同的工具表面驱动着非常不同的 Agent 集成,因为表面本身足够小,可以用多种方式封装。Claude Code 的 shell 钩子只有 80 行,因为没什么可封装的。记忆逻辑留在服务器端。插件保持精简。

反转:oh-my-kiro

一个系统以一种值得理解的方式反转了这种模式。oh-my-kiro 不赋予 Agent 记忆工具。相反,它插在 Agent 现有的工具调用之间。当 Agent 调用文件编辑工具时,oh-my-kiro 的钩子系统拦截这次调用,提取相关上下文,并将其存储在记忆层中。Agent 从不显式请求记忆。记忆层从 Agent 的行为中学习。

这并非注入。中间件不是在预测 Agent 的需求并前置它。它是在观察 Agent 的行为并记录下来。注入是推送。oh-my-kiro 的钩子是通过观察的拉取。两者各有其用,一个成熟的 Agent 系统很可能将两者结合:工具用于主动回忆,钩子用于被动捕获。

最高杠杆率的优化

在基于工具的系统里,有一种模式几乎零成本即可采用:自我引导的工具响应。

每个工具响应的末尾都附带一个关于下一步做什么的提示。GitNexus 明确地做到了这一点:每个工具响应都包含一个 Next: 行,建议最可能的后续调用。Agent 通过使用来学习 API,而非通过文档。追踪变得自我文档化。阅读追踪的开发者不仅能看出 Agent 调用了什么,还能看出系统建议 Agent 下一步调用什么。

GitNexus 拥有按流程分组的七个或更多工具:混合搜索、360 度符号上下文、影响分析,甚至还有一个用于图查询的 Cypher 逃生口。这么大的表面很容易让从未见过的 LLM 不知所措。Next: 提示正是让它变得可导航的关键。Agent 调用一个工具,读取响应,响应告诉它下一步要考虑什么。无需文档。

成本是每个工具响应一行。收益是 Agent 不再猜测 API 形状,而是开始遵循系统自身对下一步的理解。

两步节奏

基于工具的记忆的自然结构契合是两步检索。搜索返回标识符和简短预览。当需要时,一个单独的 GetByID 调用获取完整记录。mem9 的 MemoryRepo 接口就是围绕这种模式构建的。MemoryOS 将其封装在单个 retrieve_memory 调用的背后,但内部实现是一样的:先搜索,再获取。

数字清晰地说明了这一点。十个匹配,每个 1500 token,就是 15000 token 被注入到上下文中,无论 Agent 是否使用它们。两步检索返回十个标识符和简短预览,总共大约 450 token,然后只获取 Agent 实际需要的记录。在一个会话的 20 次召回步骤中,这个差异累积下来可以节省大约 200,000 token。

无需对记忆存储进行架构更改。无需额外的 LLM 调用。没有信息丢失。这是一个检索接口的决策。

这种转变意味着什么

如果你的记忆系统仍然在自动注入,你可能正在过度工作。你在没有 Agent 输入的情况下预测它的需求。你在每个轮次都支付检索成本,无论记忆是否相关。你在阻止 Agent 跟进部分结果。你在让你的追踪对自身调试变得不透明。你在帮 Agent 做它自己的工作。

Agent 应该自己询问。给它工具,并信任它去使用它们。让工具的响应引导下一次调用。让先搜索再读取的分裂成为默认节奏。然后让开,让追踪在你事后告诉你 Agent 实际需要什么——这本来就是你一直应该问的问题。

可耻的不是你构建了注入式记忆。每个人都这么做过。可耻的是在业界已经展示了更好的替代方案之后,你仍然在那样构建它,也许到那时,找到能提供最佳结果的中庸之道就会自然浮现。

一键保存

使用 YouMind AI 深度阅读爆款文章

保存原文、追问细节、总结观点,并在一个 AI 工作空间里把爆款文章沉淀成可复用笔记。

了解 YouMind
写给创作者

把你的 Markdown 变成干净的 𝕏 文章

图片上传、表格、代码块,往 𝕏 上手动重排太痛苦。YouMind 把整篇 Markdown 一键转成干净、可直接发布的 𝕏 文章草稿。

试试 Markdown 转 𝕏

更多可拆解样本

近期爆款文章

探索更多爆款文章