跳到主要内容

智能体记忆 Schema 演进:Protobuf 的困难模式

· 阅读需 12 分钟
Tian Pan
Software Engineer

第一次痛苦的智能体记忆(agent-memory)迁移总是教会我们同一个教训:存在两个模式(schema),而你只迁移了其中一个。存储层没问题 —— 每一行都已重写,每个键(key)都是新的形态,回填(backfill)作业也记录了成功。但智能体还是坏了。它继续向 user.preferences.theme 写入,却检索不到任何内容,然后从上下文中煞有介事地合成一个默认值,就好像这个键从未存在过一样。迁移操作手册显示一切正常。用户却报告记忆过时。

这种不对称是结构性的。一个依赖于重命名列的传统服务会收到硬错误,然后你进行修复。而一个依赖于重命名记忆键的智能体则会遇到软缺失,并围绕它进行胡编乱造。模式存在于两个地方 —— 你的存储和模型的上下文 —— 而你只能通过 SQL 脚本迁移其中的一个。

Protobuf 在二十年前通过规范化“仅限增加”的准则解决了这类问题的一个变体:字段是永恒的,数字是永恒的,网络类型永远不变,删除被弃用(deprecation)所取代。这一准则是智能体记忆的一个良好起点,但有一个额外的约束使其变得更加困难。Protobuf 接收者在设计上会忽略未知字段。智能体则不会。

为什么“记忆存储拥有模式”是你后知后觉才领悟到的深刻见解

大多数团队构建智能体记忆的方式都大同小异:一个键值存储,一个用于语义回想的向量索引,以及一个让模型可以用任何它喜欢的键进行读写的轻量级 SDK。这里没有 DDL,没有迁移表,也没有检入仓库的版本化模式文件。模型和应用程序代码收敛于一组工作的键 —— user.profile.nametasks.open[*].deadlinemeeting_notes.2026Q1 —— 这些键在数周的生产流量中硬化成了一种隐式契约。

这就是一种模式。它只是没有写在任何代码评审能捕捉到的地方。

问题在有人第一次尝试清理它时浮现。一位开发人员注意到 user.profile.nameuser.full_name 存储的是相同的数据,于是选择其中一个并运行了回填。存储层现在有了统一的键。智能体却没有。它仍然同时向两者写入 —— 有时用旧名,有时用新名 —— 因为数月的上下文历史向它展示过这两个键,而系统提示词中的 few-shot 示例向它展示了旧的那个。更糟糕的是,针对旧键的检索现在会失效,因为数据已经存在于新名称下。从用户的角度来看,智能体突然忘记了它曾经知道的一半内容。

团队痛苦地总结出的教训是,智能体使用的键并不是存储层的实现细节。它们是模型提示词的一部分,通过每一次检索到的记忆、每一个 few-shot 示例、每一段被导入回上下文的对话摘要得到强化。迁移存储而不迁移提示词,就像迁移数据库列而不迁移查询它的应用程序一样,是同一种错误 —— 只不过这里的应用程序是一个概率分布,你无法对其进行 grep 搜索。

移植到记忆中的 Protobuf 规则

Protobuf 关于安全模式演进的规则归结为一小组不变性:不要更改字段编号,不要更改网络类型,不要重复使用已退役的编号,永远不要将字段设为必填,并且宁可弃用也不要删除。其基本原则是二进制编码契约是不可变的;你只能添加旧读取器可以忽略的内容。

将这些规则移植到智能体记忆中,规则如下:

  • 键是永恒的。 一旦智能体向 user.preferences.theme 写入过内容,该路径就被预留了。即使你停止向其写入,也不能将其重用于不同的字段。
  • 键的类型是永恒的。 如果 user.preferences.theme 是一个字符串,它就永远是字符串。将其更改为结构化对象会破坏每一个将旧形状返回到上下文的检索,因为模型会根据错误的形状进行模式匹配。
  • 增加,不要修改。 新的首选项形状应存在于一个新键下(user.preferences.theme_v2user.preferences.appearance)。旧键继续存在,可能由翻译层填充。
  • 弃用是一个状态,而非一个事件。 只要存在任何引用该键的上下文示例或摘要,弃用的键在读取时仍需能够解析。这个时间窗口是以月计的,而不是以天计。
  • 删除需要证据。 在你实际删除一个键之前,你需要追踪数据证明模型在所有活跃会话和所有摘要重新生成中都已停止引用它。

这种准则与 Protobuf 有异曲同工之妙,但约束更强,因为接收者 —— 模型 —— 无法就地打补丁。使用 Protobuf,你发布一个新的生成的客户端,旧的字段处理程序就消失了。而对于智能体,每一个将旧键加载到上下文中的对话依然存在,明天的会话可能会加载一段引用它的摘要。你是在针对一群已经记住了旧 API 的受众进行迁移。

架构图上没人画出来的强化向量

当团队绘制 Agent 记忆系统的架构图时,他们通常会画一个存储框、一个指向写入路径的箭头、一个指向检索路径的箭头,以及一个模型框。图中遗漏的是 schema 存在的每一个其他地方。

Schema 还存在于:

  • 系统提示词中的 few-shot 示例:这些示例通常会硬编码键名(key names)以演示读/写 API。
  • 上下文中的对话历史:它会逐字重现过去的工具调用及其参数。
  • 摘要记忆(Summary memory):之前的交互被压缩成散文,其中会指名道姓地提到键名。
  • 反思或自我改进循环:这些循环生成的计划会引用 Agent 预期找到的键。
加载中…
References:Let's stay in touch and Follow me for more thoughts and updates