我对 Agent Memory 的一些理解:真正难的可能不是“记住”,而是“知道什么值得记”

0 阅读12分钟

最近在学习和梳理 Agent 的过程中,我花了不少时间去想一个问题:

Agent 的记忆到底应该怎么设计?

一开始我的理解其实很直接:

Agent 需要记忆,那就把历史信息存下来。

数据少的时候放文件,数据多了以后放数据库;如果还需要语义检索,就接上 Embedding 和 Vector DB。

这个思路当然没有错。

但越往后梳理,我越觉得,它其实只回答了一个问题:

信息存在哪里?

而没有真正回答:

Agent Memory 应该怎么设计?

对于一个 Agent 来说,真正困难的可能不是怎么把一条信息塞进数据库,而是:

  • 这条信息到底值不值得记?
  • 应该记多久?
  • 它只属于当前任务,还是下次任务依然有效?
  • 下一次执行任务的时候,Agent 怎么知道应该把它想起来?
  • 如果新旧两条记忆发生冲突,又应该相信谁?

沿着这些问题继续往下想,我逐渐形成了一个自己的理解:

Memory 不是 Agent 后面外挂的一个数据库,而是一套围绕知识生命周期建立起来的机制。

数据库只是最后负责承载数据的地方。

真正决定一套 Memory 好不好用的,反而是:

什么值得记,什么时候应该想起来,以及这些记忆以后应该如何影响 Agent。


一、先搞清楚:Memory 和 Storage 不是一回事

很多 Agent 架构图里,我们经常能看到类似这样的结构:

Agent
  ↓
Memory
  ↓
Vector DB

第一次看到的时候,很容易自然地把二者画上等号:

Memory ≈ Vector DB

但后来我觉得,这两个概念其实应该拆开来看。

Vector DB、SQLite、Markdown、Redis……

这些东西首先解决的是:

信息最终保存在哪里。

也就是 Storage。

而 Memory 真正应该解决的是:

什么信息应该进入系统,以及这些信息未来应该怎样重新影响 Agent。

这有点像:

文件系统 ≠ 硬盘

硬盘负责保存数据。

但文件系统还需要解决:

目录怎么组织、文件怎么索引、权限怎么管理、内容怎么更新、数据怎么读取……

所以我们不会因为数据最终落在 SSD 上,就说:

SSD 就是文件系统。

Agent Memory 也是类似的。

image.png


Memory 决定的是「内容与生命周期」

它需要回答:

什么值得记?
什么时候应该召回?
这条记忆属于哪个范围?
它什么时候应该失效?
它怎样影响 Agent?

而 Storage 决定的是「载体」:

存在哪里?
怎么写?
怎么查询?
怎么持久化?

因此如果现在让我从 0 开始考虑 Agent Memory,我不会第一时间问:

用 pgvector 还是 Milvus?

我反而会先问:

Agent 到底需要记住哪些东西?

因为我觉得,这个问题才是整个 Memory 设计真正的起点。


二、第一类 Memory:先解决「这次任务别忘了」

假设一个 Agent 正在完成一次比较复杂的代码修改。

在执行过程中,它可能已经:

  • 阅读了十几个文件;
  • 理清了一部分调用链;
  • 确认某个模块不能直接修改;
  • 尝试过一种方案,但是测试失败;
  • 排除了一个错误方向;
  • 已经修改了两个文件;
  • 还有几个调用方没有检查。

这些信息都需要被记住。

否则 Agent 每完成几步就重新分析一遍,整个任务很容易失去连续性。

我把这一类记忆理解成:

Task Memory。

它关注的不是:

几个月之后我还能不能想起这件事?

而是:

当前这次任务,我进行到哪里了?

例如可以维护一个很简单的运行时状态:

{
  goal: "...",

  findings: [],

  decisions: [],

  filesRead: [],

  filesModified: [],

  errors: [],

  testResults: [],

  nextActions: []
}

这里有一个我觉得很重要的点:

不是所有 Memory 都应该持久化。

比如:

我刚刚读过 user.ts。

对于当前任务来说,这条信息很重要。

但任务结束以后,它可能几乎没有任何长期价值。

因此 Task Memory 最简单的实现,可能就是:

image.png

如果需要任务恢复、Crash Recovery 或者调试,再把当前状态定期 Snapshot 到一个临时 JSON。

不需要一上来就往数据库里塞。

所以我现在比较喜欢用两句话理解 Agent 的两类记忆:

短期记忆解决「这次别忘」。

长期记忆解决「下次别重新学」。

这两个问题虽然都叫 Memory,但背后的生命周期其实完全不同。


三、什么东西才值得进入长期 Memory?

接下来才是我觉得最有意思的问题:

到底什么东西值得长期保存?

假设 Agent 完成一次任务以后产生了 100 条信息。

显然不能全部留下来。

例如下面这些信息:

我刚刚读过 user.ts

getUser 函数定义在 user.ts

这个文件里面有三个函数

它们虽然都是真的,但我觉得通常没有什么长期保存的必要。

因为 Agent 下一次重新打开 Repository,很容易再次获得这些信息。

换句话说:

如果某条信息可以通过当前环境低成本重新推导出来,就没必要急着把它写进长期 Memory。

真正值得保存的,往往是另一类东西。

例如:

Vue template 中禁止使用 optional chaining

某类非交易链路必须走 invoke

payment-sdk 只能调用,不能直接修改

code=117 在当前业务中代表用户主动取消

这些信息和前面最大的区别是什么?

它们背后往往包含了一些代码本身无法完整表达的上下文

例如:

历史事故
业务约束
团队约定
架构边界
兼容性问题
特殊运行规则

Agent 如果不知道这些事情,哪怕代码能力再强,也可能在下一次任务中重新踩坑。

所以目前我对 Long-term Memory 的理解是:

那些无法通过当前环境低成本重新推导出来,并且未来任务仍然可能复用的知识。

这里其实可以得到一个很实用的判断标准:

越容易重新推导的信息,长期记忆价值越低

例如:

getUser 在哪个文件?

搜索一次代码就知道了。

长期保存价值比较低。


越依赖隐性上下文的信息,长期记忆价值越高

例如:

为什么 payment-sdk 不能直接改?

这背后可能涉及团队边界和历史架构决策。

如果不记录下来,下次 Agent 很可能根本不知道这条约束存在。

因此我会把长期记忆的价值粗略理解成:

                重新获取成本高
                     ▲
                     │
                     │   更值得
                     │   长期保存
                     │
                     │
                     │
                     │
                     └──────────────▶
                          跨任务复用价值

简单来说:

越难重新获得,同时未来又越可能再次使用的信息,越值得进入长期 Memory。

image.png


四、Memory 最重要的可能不是「写入」,而是 Memory Gate

继续往下想,很快就会遇到一个更麻烦的问题。

Agent 每次任务都会发现很多东西。

如果没有任何筛选机制,Memory 最后可能会变成这样:

Memory
├── 有用知识
├── 当前任务临时状态
├── 一次偶然现象
├── Agent 的猜测
├── 已经过期的结论
├── 重复信息
└── 错误经验

Memory 越来越大。

但 Agent 不一定越来越聪明。

甚至可能刚好相反。

因为一旦一条错误知识进入长期 Memory,它以后就可能不断影响 Agent 的判断。

例如一次线上问题排查过程中:

重启服务之后,问题消失了。

这是一条真实的 Observation。

但是如果 Agent直接把它总结成:

遇到这个问题时应该重启服务。

事情就开始危险了。

因为:

现象相关 ≠ 根因成立

一次结果并不能证明真正的因果关系。

所以我觉得长期 Memory 前面必须存在一道门。

我把它理解成:

Memory Gate。

image.png

Agent 在执行任务时可以产生很多 Observation。

但是 Observation 不应该直接进入 Long-term Memory。

它应该先成为:

Memory Candidate

然后经过 Memory Gate 判断:

这东西到底有没有资格成为长期知识?


Memory Gate 可以判断什么?

第一版其实不需要特别复杂。

我觉得至少可以看几个维度。

1. Reusability

未来还会不会再次使用?

如果这个知识只对当前一次任务成立,就不应该进入长期 Memory。


2. Scope

它到底影响多大的范围?

可能只是:

一个函数

也可能属于:

Repository
Team
Global

Scope 不一样,未来召回的策略也应该不同。


3. Confidence

这个结论到底有多确定?

它是:

Agent 猜的

还是:

通过代码验证

甚至:

通过测试 + 文档 + 人工确认

两者显然不能拥有相同权重。


4. Verified

有没有真正验证过?

我觉得这一点尤其重要。

Agent 可以产生假设。

但:

假设不应该轻易升级成长期知识。


5. Stability

这个知识稳定吗?

例如:

某个临时灰度开关现在是 true

可能明天就变了。

但:

这个 Repository 禁止直接修改 payment-sdk

可能半年以后还成立。

这两类信息的生命周期显然不同。


6. Cost

如果忘记了,下次重新获取的成本高不高?

例如:

某函数在第 120 行

重新搜索成本很低。

而:

这个业务规则是因为 2025 年发生过一次线上事故才建立的

重新获取的成本可能很高。

后者显然更值得保存。


所以最终 Memory Gate 的输出可能不只是:

{
  "remember": true
}

而可以逐渐变成:

{
  "shouldRemember": true,

  "scope": "repository",

  "confidence": 0.92,

  "verified": true,

  "lifetime": "long_term",

  "reason": "该规则无法直接从代码推导,并且可能影响后续任务"
}

这样做以后,我觉得 Memory 才真正开始从:

保存历史信息

转向:

筛选未来真正有价值的知识。

而这可能才是 Agent Memory 最重要的一步。

因为一套 Memory 系统真正应该追求的,并不是:

什么都记住。

而是:

让不确定的信息留在「经验」,让确定且有价值的信息进入「记忆」。


五、记住之后,更重要的是“该想起来的时候能想起来”

Memory Gate 解决的是“什么值得记”,但信息存下来以后,还有另一个问题:

下一次任务开始时,Agent 怎么知道该把哪条 Memory 找回来?

显然不能把所有长期记忆都塞进 Context。

如果项目里已经有几百上千条 Memory,每次全量注入只会带来更多噪声。

所以 Memory 做大以后,重点会从“存储”转向“召回”。

例如当前任务是修改 credit/passwordless,那真正应该出现的,可能只有:

非交易链路必须走 invoke

payment-sdk 不能直接修改

code=117 表示用户主动取消

而不是整个项目的所有历史经验。

所以一个比较自然的过程是:

Current Task
    ↓
理解任务主题
    ↓
召回相关 Memory
    ↓
过滤 / 排序
    ↓
注入 Context

这时候再看 Vector DB,我觉得它的位置就很清楚了:

Vector DB 不是 Memory 本身,它只是 Memory Retrieval 的一种实现方式。

数据少的时候,Markdown + Tag + Keyword Search 可能就够了。

只有当 Memory 真的多到传统检索不够用时,再考虑 Embedding、Vector DB 或 Rerank。

所以 Memory 做得好不好,并不是看:

存了多少条。

而是看:

真正需要某条经验的时候,它有没有出现。


六、Memory 最终不一定还是 Memory

这是我觉得整套设计里最有意思的一点。

假设 Agent 第一次踩到一个坑:

Vue template 中不能使用 optional chaining

第一次出现时,把它记录进 Memory 很合理。

下一次再修改类似代码时,Memory 提醒 Agent:

这里要注意这个问题。

但如果同一个问题已经出现了很多次呢?

这时候还要每次都:

召回 Memory
    ↓
LLM 阅读
    ↓
LLM 判断
    ↓
希望它不要再犯

其实就有点浪费了。

因为当一条经验被反复验证以后,它已经不再只是“经验”,而更接近一条确定性的规则。

这时候就可以继续升级:

image.png

第一次踩坑时:

先记录经验。

反复出现以后:

用 Hook 自动提醒或检查。

当规则已经足够确定:

直接交给 Lint、CI 或 Static Rule。

这背后其实是一个很简单的原则:

让不确定的问题留给 LLM,让已经确定的问题逐渐交给确定性的程序。

所以 Memory 不一定是知识沉淀的终点。

有些 Memory 最好的结果,反而是最后“消失”了。

因为它已经变成了系统本身的一部分。


写在最后

回头看,我一开始理解 Agent Memory 时,关注的是:

信息应该存在哪里?

但继续往下梳理之后,我觉得真正重要的是:

什么值得记,什么时候应该想起来,以及什么时候已经不应该再依赖“记忆”。

Task Memory 解决“这次别忘”。

Long-term Memory 解决“下次别重新学”。

Memory Gate 负责避免什么都往里面塞。

Retrieval 负责让真正有用的经验在正确的时候出现。

而当一条经验被反复验证以后,它还可以继续从:

Memory → Hook → Rule → Automation

往前演进。

所以现在如果让我用一句话概括 Agent Memory,我会更倾向于:

好的 Memory,不是让 Agent 记住越来越多,而是让真正有价值的经验,在需要的时候重新影响它。

而那些已经足够确定的经验,最终不应该永远只是“记忆”。

它们应该成为系统能力。