ᕕ( ᐛ )ᕗ Jimyag's Blog

Agent Memory 是什么

上一篇 《Loop Engineering 是什么》 讲的是 Agent 公式里的 Loop1 再往前一篇 《Agent 是什么,能干什么》 里,我把 Agent 写成了这个公式:2

1
Agent = LLM + Tools(工具) + State(状态) + Loop(循环控制)

这篇继续讲 State 里最容易被低估的一部分:Agent Memory。讨论起点来自一篇关于 Agent Memory 分层的 X 长文,但下面不会把它当成权威定义,而是结合 Claude Code、Codex、LangChain、Google ADK、LlamaIndex、CrewAI 等官方材料重新整理。3

先给结论:

Agent Memory 不是把聊天记录存起来,也不是把上下文窗口变长。它是 Agent 跨任务、跨会话保存和召回状态的机制,用来回答「过去发生过什么」「哪些结论可靠」「哪些规则必须遵守」「下一次应该从哪里继续」。

如果 Loop 解决的是当前任务里「下一步怎么走」,Memory 解决的是下一次任务开始时「还记不记得上次为什么这么走」。

长上下文不是 Memory

现在很多模型都有很长的 context window。长上下文能让模型在当前任务里一次看到更多代码、日志、文档和对话,这很有用,但它解决的是「这一轮能装下多少」。

Memory 解决的是另一个问题:当前会话结束以后,哪些信息还能影响下一次会话。

可以这样拆:

1
2
3
4
5
6
7
8
Context window:
当前任务的工作台,材料临时摊在上面。

RAG / Search:
外部资料库,需要时按查询召回。

Memory:
跨会话保留的状态层,记录稳定偏好、项目事实、已验证结论、失败经验和下一步。

如果一个 coding agent 只有长上下文,没有 memory,下周重开任务时仍然可能忘记这个项目的测试环境坑、review 习惯、部署边界和上次没完成的验证。它在单次任务里看得很全,但跨任务没有复利。

各家公司和框架怎么做 Memory

不同产品的术语不一样,但分层越来越清楚:有些信息每次启动都要加载,有些只在需要时搜索,有些是系统自动从历史里抽取,有些应该由人写进版本化规则文件。

来源 官方材料里的做法 对 Memory 分层的启发
Claude Code Claude Code 把 CLAUDE.md 和 auto memory 拆开。CLAUDE.md 是人写的持久指令和规则,auto memory 是 Claude 根据修正和偏好自己写下的学习。两者都会在会话开始加载,但 Claude 文档也强调它们只是上下文,不是强制执行层。4 必须遵守的规则不该只放自动记忆。规则文件适合稳定约定,auto memory 适合从交互中学到的偏好和经验。
Codex Codex 的 AGENTS.md 用来给项目提供额外指令和上下文;Memories 关闭默认,需要启用后才会把旧线程里有用的上下文转成本地 memory 文件。Codex 文档明确说团队必须遵守的指导应放进 AGENTS.md 或 checked-in docs,memories 只是本地 recall layer。56 规则层和召回层要分开。团队规则应该版本化,个人/本地记忆可以辅助召回,但不能成为唯一事实源。
OpenAI Agents SDK Sessions 用来自动维护对话历史,避免手动在每一轮传递完整历史;SDK 同时提供 SQLite、加密和自定义 session 实现。7 会话状态和长期记忆不是一回事。Session 更偏当前线程连续性,Memory 更偏跨线程复用。
LangGraph / LangChain 文档把 memory 分成 thread-scoped short-term memory 和跨 session 的 long-term memory。短期 memory 作为 agent state 通过 checkpointer 持久化;长期 memory 可以按 namespace 存储和召回。文档也提醒长消息历史会带来成本、延迟和干扰。8 短期状态、长期记忆和命名空间作用域应该拆开,否则容易把历史噪声全部塞回上下文。
Google ADK ADK 把 Session / State 类比为单次对话中的短期记忆,把 MemoryService 类比为可搜索的长期知识库。MemoryService 支持把 session 加入 memory、增量加入 events、直接写 memory item,以及搜索 memory。9 Memory 可以有明确接口:写入、增量写入、直接写入、搜索。它不是只能靠向量库隐式发生。
LlamaIndex LlamaIndex 把 memory 作为 agentic system 的核心组件,支持 memory.put()memory.get()。它把短期 chat history 和长期 memory block 组合起来,长期 memory block 可以是 static info、fact extraction、vector memory,并用 priority 处理 token 限制。10 Memory 不是单一容器。静态事实、抽取事实、向量召回可以并存,还要有优先级和截断策略。
CrewAI CrewAI 提供统一 Memory API,支持 rememberrecallforget,并用语义相似度、时间新近度和重要性做综合评分。Crew、Agent、Flow 可以共享或使用 scoped memory。11 召回质量不只取决于 embedding,相似度、时间、重要性和 scope 都会影响结果。

这些材料合起来,可以得到一个更稳的判断:

1
2
Agent Memory 不是一个文件,也不是一个向量库。
它是一组围绕状态写入、召回、注入、验证、过期和删除的机制。

Memory 应该分哪几层

我更倾向把 Agent Memory 拆成五层。这样比「把所有历史都 embedding」更容易维护。

1. 规则层:必须遵守的工作约定

这一层是 AGENTS.mdCLAUDE.md、项目 docs、规则文件。

它适合放:

  • 构建、测试、发布命令。
  • 代码风格和目录约定。
  • 不能碰的目录或文件。
  • 安全、权限和生产操作红线。
  • 团队希望所有 agent 和开发者都遵守的流程。

规则层应该版本化、可 review、可 diff。它不适合存每次 debug 的过程,也不适合塞大量历史聊天摘要。

原因很简单:规则层通常会进入启动上下文。越长,token 成本越高,模型越容易忽略真正重要的规则。Claude Code 文档也建议 CLAUDE.md 保持具体、简洁;Codex 文档也说 AGENTS.md 是 durable project guidance,而 memories 是本地 recall layer。46

判断标准可以很朴素:

1
2
以后每次都必须遵守的,放规则层。
只是某次任务的历史细节,不要放规则层。

2. 常驻层:每次都值得付 token 的高密度事实

常驻 memory 是每轮都可能进入上下文的内容。它的成本最高,所以必须克制。

适合放三类东西:

  1. 身份:这个 agent 长期负责什么。
  2. 偏好:用户稳定偏好,例如回答风格、提交习惯、工作方式。
  3. 不变量:环境中长期成立、下次几乎一定有用的事实。

不适合放:

  • 一整段旧对话。
  • 每次任务的流水账。
  • 未验证猜测。
  • 已经过期的环境快照。

常驻层的质量不看「记了多少」,而看信息密度。它应该像索引页,不应该像日志目录。

3. 历史召回层:大部分过去不该常驻,但必须能找到

大多数历史信息不应该每次都注入 prompt,但也不能丢掉。

例如:

  • 某个 bug 的排查过程。
  • 上次 CI 失败的真实原因。
  • 某个设计为什么放弃了另一个方案。
  • 某个 API 行为已经被官方文档或实验验证过。
  • 某个环境坑只在特定条件下出现。

这些信息最适合成为可搜索、可局部读取的历史 memory。

它可以存在很多形态里:

  • session store
  • SQLite
  • markdown topic files
  • daily notes
  • vector store
  • BM25/全文搜索索引
  • trace / artifact store

关键不是具体存在哪里,而是召回时能不能回答三个问题:

  1. 这条记忆来自哪里?
  2. 它解决什么问题?
  3. 当前任务为什么需要它?

如果只返回一段相似文本,但没有来源、时间和适用范围,Memory 就会从帮助变成噪声。

4. 证据和治理层:记住结论,也要记住凭什么

Memory 最危险的地方是把错误长期化。

一次误判写进 memory,下次 agent 会更自信地复用它。一次临时 workaround 写成长期规则,后面所有任务都会被它影响。一次网页里的 prompt injection 如果被保存成「经验」,影响会跨 session 扩散。

所以高质量 memory 不能只写结论,还要写证据。

一个 bug memory 至少应该包含:

  • 问题描述。
  • 影响范围。
  • 根因证据。
  • 修复方式。
  • 验证命令或验证结果。
  • 相关 commit / PR / issue。
  • 仍未解决的问题。
  • 这条 memory 什么时候可能过期。

一个权限或生产操作 memory 至少应该包含:

  • 谁授权。
  • 允许做什么。
  • 不允许做什么。
  • 适用环境。
  • 到期条件。
  • 需要升级确认的边界。

这类 memory 更像小型 postmortem 或状态记录,而不是普通笔记。它承担的是治理作用:让 agent 知道哪些事情可以自动做,哪些必须停下来问人。

5. 经验沉淀层:从 recall 变成 skill

Memory 只负责「想起来」还不够。真正有复利的是把重复有效的路径沉淀成可复用流程。

例如一个 agent 多次成功完成同一类任务:

1
查失败 CI -> 拉日志 -> 定位失败测试 -> 做最小修复 -> 跑 targeted test -> 更新 PR

这条经验如果只存在历史记录里,下次仍然要靠召回和临场组织。更好的做法是把它变成 Skill、runbook、script 或 workflow。

可以这样区分:

1
2
3
4
5
Memory:
记住过去发生了什么,以及为什么那样判断。

Skill:
把重复成功的方法整理成下次可直接执行的流程。

所以 Memory 的终点不是「保存更多」,而是减少重复踩坑,把有效经验升格成默认能力。

Memory 和 RAG 有什么区别

RAG 解决的是「从外部知识库找资料」。Agent Memory 解决的是「这个 agent 或这个用户过去发生过什么,以及哪些状态要延续」。

两者会重叠,但边界不同。

RAG 更适合:

  • 产品文档。
  • API 文档。
  • 论文。
  • 公司知识库。
  • 代码搜索。
  • 外部事实查询。

Memory 更适合:

  • 用户偏好。
  • 项目约定。
  • 已踩过的坑。
  • 任务进度。
  • 上次验证结论。
  • 权限边界。
  • 长期工作习惯。

如果把 Memory 全部做成 RAG,就容易漏掉状态、权限、过期和删除。如果把 RAG 全部塞进 Memory,又会污染个人和项目状态。

一个实用原则是:

1
2
外部世界的通用资料,走 RAG。
这个 agent / 用户 / 项目长期积累出来的状态,进 Memory。

Memory 和 Loop 是一对

Loop Engineering 关注的是一次任务内的推进:

1
观察 -> 行动 -> 验证 -> 继续或停止

Agent Memory 关注的是多次任务之间的延续:

1
保存 -> 整理 -> 召回 -> 注入 -> 更新或删除

一个长期运行的 Agent 同时需要两者。

没有 Loop,Agent 只能回答一次,不能根据工具结果持续推进。

没有 Memory,Agent 每次启动都像新来的,不能继承上次已经验证过的结论。

两者组合起来,Agent 才从「会调用工具的聊天界面」变成「能持续参与项目的软件执行体」。

这里要区分两种状态:

1
2
3
4
5
6
7
Loop State:
当前任务这一轮必须记住的工作状态。
例如已经完成什么、失败过什么、下一步要验证什么。

Agent Memory:
跨会话仍然值得保留的长期状态。
例如稳定项目约定、已验证环境坑、用户偏好、风险边界和可复用流程。

Loop State 不应该自动等于长期 Memory。很多状态只在当前任务里有用,任务结束就可以丢掉。只有那些下次忘了会重复踩坑、重复浪费时间,或者会影响权限和风险判断的信息,才值得进入 Memory。

什么时候该写进 Memory

不是所有东西都该记。一个实用判断是看四个问题:

  1. 下次是否大概率还会用到?
  2. 如果忘了,是否会重复犯错或浪费时间?
  3. 这条信息是否足够稳定?
  4. 它的来源和适用范围是否清楚?

适合写入 memory:

  • 用户稳定偏好。
  • 项目长期约定。
  • 反复出现的错误模式。
  • 已验证的环境坑。
  • 已完成但后续需要接上的任务状态。
  • 高风险操作边界。
  • 可以沉淀成 Skill 的重复流程。

不适合写入 memory:

  • 一次性闲聊。
  • 未验证猜测。
  • 临时 token、密码、密钥。
  • 很快过期的运行状态。
  • 大段原始日志。
  • 不知道来源的总结。

如果只是当前任务需要,放上下文。
如果未来还会需要,但不该每次加载,放历史召回。
如果每次都必须遵守,放规则文件。
如果已经变成可重复流程,做成 Skill。

Memory 系统需要哪些治理能力

Agent Memory 一旦跨 session 生效,就不是简单缓存。它会影响未来行为,所以至少要考虑这些能力:

  1. 来源:这条 memory 来自哪个 thread、文件、网页、commit 或用户输入。
  2. 时间:什么时候创建,什么时候更新。
  3. 作用域:属于用户、项目、agent、组织,还是某个 session。
  4. 类型:事实、偏好、规则、推断、任务状态、风险边界。
  5. 置信度:是已验证结论,还是暂时假设。
  6. 过期性:什么时候需要重新验证。
  7. 删除:用户能否查看、修改、删除。
  8. 审计:高风险 memory 是否有人工确认。

这些问题不是向量库能单独解决的。Embedding 只能帮助相似召回,不能告诉你这条信息是否过期、是否被授权、是否应该影响当前任务。

常见误解

误解一:Memory 就是保存聊天记录

聊天记录只是原材料。Memory 应该从聊天记录里提取稳定、有来源、可复用的信息。否则只是把历史噪声换了个地方存。

误解二:Memory 越多越好

Memory 越多,召回噪声越大,治理成本越高。高质量 memory 应该短、准、可追溯。

误解三:向量库就是 Memory

向量库是召回手段,不是 memory 架构。真正的 memory 还要处理作用域、来源、权限、过期、删除和注入策略。

误解四:自动 memory 可以替代规则文件

不能。团队规则、生产红线、构建命令、审计要求应该放进版本化文件或配置。自动 memory 只能辅助召回,不应该成为唯一约束。

误解五:反思一定会让 agent 变强

反思也可能把错误经验永久化。自动总结、自动抽取、自动生成 Skill 都需要验证机制。否则 agent 会把偶然成功当成稳定方法。

一个简单落地模型

如果要给自己的项目设计 Agent Memory,我会从这个最小结构开始:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
AGENTS.md
  必须遵守的项目规则、命令、边界。

memory/index.md
  高密度索引,只放长期有用的主题入口。

memory/topics/*.md
  具体主题记忆:背景、证据、结论、验证方式、过期条件。

memory/sessions/
  原始或半结构化 session 摘要,可搜索,不常驻。

.agents/skills/
  从 memory 中沉淀出来的可复用流程。

每条 topic memory 尽量按这个模板写:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
# <主题>

## 结论

这条 memory 现在支持什么判断。

## 证据

- 来源链接、commit、issue、命令输出或官方文档。

## 适用范围

在哪个项目、环境、时间范围内成立。

## 下次怎么用

Agent 看到相关任务时应该做什么。

## 过期条件

哪些变化发生后必须重新验证。

这个模型不复杂,但有两个好处:

  1. 人能读、能 review、能删。
  2. Agent 能按需召回,而不是每次背完整历史。

总结

Agent Memory 是 Agent 的状态层。它不只是「记住用户说过什么」,而是把跨会话工作所需的信息分层管理:

  • 规则层:每次都必须遵守。
  • 常驻层:每次都值得带上的高密度事实。
  • 历史召回层:需要时能找到过去证据。
  • 证据和治理层:知道结论从哪里来、是否还可靠。
  • 经验沉淀层:把重复有效的方法变成 Skill 或流程。

它和 Loop Engineering 刚好互补:

1
2
Loop 让 Agent 在当前任务里持续推进。
Memory 让 Agent 在下一次任务里站在上一次的结果上继续。

长上下文让 Agent 看得更多,Memory 让 Agent 不必每次从零开始。

#AI Agent #Agent Memory #LLM #Claude Code #Codex #LangGraph #工程实践