01 · 基础与边界
记忆是什么,不是什么
Agent 要跨会话、跨任务保持连续性,而 context window 做不到——它每次会话清空、容量有界、被动堆积。这一章先划清记忆到底是什么、不是什么:它和 context window 的关系、和 RAG 的关系,以及记忆内部分成哪几类。把这条边界钉住,后面四章讲的写入、治理、分层、选型才有地基。
本章建立的认知框架
- context window 是 agent 的工作记忆(working memory)——一块易失、有界、会话间清空的暂存区,不是知识的归宿。
- RAG 和 agent memory 的分界线不是向量检索,而是那条由 agent 自己掌控的写入路径:RAG 只读、无状态;memory 是写入→治理→读取的闭环。
- 记忆按 CoALA 分四类(working / episodic / semantic / procedural),再叠一条正交的表示轴(文本 vs 参数)——四类不是四个数据库,working memory 就是 context window 本身。
1.1为什么需要记忆
Context window 是 agent 的工作记忆——被动接收、容量有界、每次会话从零开始;它能装下"此刻在想什么",却装不下"这个用户三周前告诉过我什么"。
一个 agent 要在真实业务里有用,得跨越三种"间隔"保持连续:跨会话(今天的对话接得上上周的)、跨任务(debug 任务里学到的项目约定,能用在下一个 feature 任务)、跨用户身份(记住"这个客户的部署是 MySQL 不是 Postgres")。context window 在每一种间隔处都断开:会话一结束,窗口里的 token 全部丢弃,下一次启动是一张白纸。
底层机制(比文档深一层):context window 的本质是一次 LLM 前向推理的输入缓冲区。模型本身是无状态函数——给定一段 token 序列,输出下一个 token 的分布;它不保留任何调用间的状态。所谓"对话记忆"完全是应用层每轮把历史重新拼进输入制造出来的错觉。窗口容量(比如 200K token)是这个缓冲区的物理上界;填满之后要么截断、要么报错。于是窗口有三个出厂属性:易失(推理结束即弃)、有界(token 数封顶)、会话间清空(无跨会话的持久层)。这三条决定了它只能当工作记忆,当不了长期记忆。
"把窗口做到 1M token,不就等于有记忆了吗?"——这是最常见的误判。更大的窗口只是把易失缓冲区加宽,并没有给它加上跨会话的持久层,也没有给 agent 一条"决定记什么、改什么、忘什么"的控制路径。第 4 章会引用 BEAM(ICLR 2026)的实证:把同样的信息塞进长上下文 vs 放进结构化记忆,随着 token 规模增大,两者的差距变大而非缩小——长上下文不是记忆的替代品。这条会在 1.2 节讲透。
没有记忆的三个后果
把记忆从 agent 上拿掉,会稳定地出现三种退化,每一种都直接对应一个业务痛点:
- 每次会话重新解释一切。用户每次都要把背景("我的栈是 A、约束是 B、上次结论是 C")重新喂一遍;agent 无法承接昨天的进度。开发成本和用户负担都线性堆高。
- 没有个性化。agent 学不会"这个用户偏好 Python、对花生过敏、习惯简短回答"。每个用户拿到的都是同一张出厂面孔,调教过的偏好下次归零。
- 无法从过去的失败中学习。"上次试 X 方案踩了空,这次换 Y"——这种经验需要把失败轨迹存下来、下次检索回来。没有 episodic memory,agent 会在同一个坑里反复跌倒。
一个客服 agent 接入了 RAG,能检索完整的产品手册和退款政策文档。某用户三周前在对话里说过"我用的是企业版套餐"。今天他问"我这个套餐能退吗?"——agent 答得上来吗?为什么?
展开答案
答不上来。RAG 能检索文档(退款政策怎么写),但"这个用户用企业版"是三周前对话里产生的会话事实,从来没被写进任何可检索的存储——RAG 没有写入路径,不会把用户说过的话沉淀下来。除非系统在那次对话时主动把"用户=企业版"作为一条记忆写入,否则今天检索手册时它根本不在候选集里。这正是 RAG 和 memory 的分界:缺的不是检索能力,是写入路径。下一节展开。
1.2记忆 / 上下文 / RAG 的边界
三者的真正分界线只有一条:有没有一条由 agent 自己掌控的写入路径。context window 只读不写也不持久;RAG 只读外部知识、无状态;只有 agent memory 同时拥有写入、治理、读取,构成闭环。
这三个词在工程对话里经常被当成可互换的"给模型更多信息的办法",于是出现两类错误决策:以为"上长上下文"就解决了记忆需求,或以为"接了 RAG"就等于 agent 有记忆。两者都会在跨会话个性化、从失败中学习这类需求上直接失效。把边界讲清楚,选型时才知道手上的方案缺的是哪一块。这一节是整章——也是整篇教程——的核心。
三者逐一拆开
context window = 仅工作记忆。它是被动的:应用喂什么它装什么,自己不决定去留。它是易失的:推理结束即清。它是会话间清空的:没有跨会话的持久层。它回答的问题是"此刻输入里有什么"。
RAG = 只读、无状态的检索。给定同一个 query,RAG 总是去同一个(基本不变的)文档库里捞最相似的片段,结果与对话历史无关——它不知道、也不在乎这个用户之前说过什么。关键在于:RAG 没有写入路径。它不会因为 agent 在对话中学到了新事实就把这条事实沉淀进库里;语料的更新是离线的、批量的,由数据管道而非 agent 在交互中驱动。RAG 回答的问题是"文档里写了什么"。
agent memory = 写入→治理→读取的完整闭环,且与 agent 的感知/行动耦合。它独有的那条边是写入路径:agent 自己决定哪些交互值得记下来、哪条旧记忆该被新事实覆盖或删除(即自编辑 self-editing)。记下来的东西跨会话持久,并随时间演化(旧事实失效、被更正、被合并)。它回答的问题是"agent 学到了什么"。
底层机制(比文档深一层):把 RAG 和 memory 摆在同一张流程图上,读取那一段几乎一模一样——都是"embedding → 向量检索 → 把命中片段拼进 context"。所以 RAG 是 agent memory「读取」步骤的一个子集。真正缺的两块在读取之前和之外:① 一条写入路径,把交互中产生的新事实主动沉淀进存储;② 一个治理层,负责去重、冲突消解、遗忘,让存储不会随时间腐烂成一堆互相矛盾的陈旧条目。Letta 团队的措辞最精炼:RAG 是 reactive retrieval(被动检索),agent memory 是 agent-managed editable state(agent 托管的可编辑状态)。差别不在向量检索本身,而在那条"谁能写、谁来治理"的路径——这是本章的门槛所在,记牢它,后面所有架构和选型都从这条线长出来。
| 维度 | context window | RAG | agent memory |
|---|---|---|---|
| 本质 | 易失输入缓冲区 | 只读检索管道 | 写入→治理→读取闭环 |
| 状态 | 会话内·会话间清空 | 无状态(query 无关历史) | 跨会话持久·随时间演化 |
| 写入路径 | 无(被动喂入) | 无(语料离线更新) | 有 · agent 自己掌控(自编辑) |
| 治理层 | 无 | 无 | 有(去重·冲突消解·遗忘) |
| 回答的问题 | 此刻输入里有什么 | 文档里写了什么 | agent 学到了什么 |
把 agent 类比成一个程序员:context window 是他此刻脑子里的工作记忆——手头正在想的几行代码,下班即忘。RAG 是公司的 wiki/官方文档——随时能查,但 wiki 不会因为他今天调试出一个结论就自动更新。agent memory 是他自己的工程笔记本——他主动决定记下"这个客户用 MySQL""上次那个方案行不通",过段时间还会回头划掉过时的条目。
失效边界:这个类比会在"治理"上误导。真人的笔记本靠人脑隐式去重和判断新旧;agent memory 的治理是显式工程步骤——要专门写抽取、冲突消解、遗忘策略,没有这层,笔记本会迅速烂成一堆自相矛盾的便利贴。这正是第 2 章五个环节要解决的问题。
场景走查:同一句话,三套系统各做什么
用户在对话里说:"我上周把数据库从 Postgres 迁到了 MySQL。"看三套系统各自的反应:
- 纯 context window:这句话留在当前窗口里,本轮对话能用上。会话一结束,丢弃。下次他再来,agent 不知道有过迁移这回事。
- 纯 RAG:这句话什么也没触发——RAG 只在被 query 时去文档库检索,它没有"把用户刚说的话存下来"的入口。产品手册里若写着"默认 Postgres",下次检索还会把过时信息捞回来。
- agent memory:写入路径被触发——agent 把"用户的数据库 = MySQL(更新于本周)"作为一条记忆写入,并在治理时覆盖掉旧的"= Postgres"(这正是第 2 章 recency-wins 冲突消解)。三周后他问"我的库支持这个特性吗",检索回来的是 MySQL,不是 Postgres。
1.3四类记忆(CoALA)
CoALA 框架把 agent 记忆分成四类——working、episodic、semantic、procedural——按"信息以什么形态、为什么目的存在"来切;其中 working memory 不是一个独立的库,它就是 context window 本身。
"记忆"是个太粗的词。一个 agent 要记的东西性质差别很大:当前推理的草稿、过去的具体经历、抽象的事实、可复用的技能——它们的存储介质、保留时长、检索方式、治理策略全都不同。CoALA(Cognitive Architectures for Language Agents,arXiv 2309.02427)借认知科学的分类把它们拆开,给后面"每类怎么存、怎么取、怎么忘"提供了挂钩。不分类,就会把"用户的姓名"和"上次失败的轨迹"塞进同一个桶,用同一套 TTL 和检索逻辑——必然两头不讨好。
四类逐一定义 + agent 实例
① Working memory(工作记忆)
当前决策循环里的活跃信息——"此刻装进 context window 的东西"。
实例:最近几轮对话 + 一次 ReAct 循环里的中间推理草稿(thought / action / observation)。一个正在执行多步任务的 agent,把"当前子目标、刚调用的工具返回了什么、下一步打算干嘛"全放在这里。
working memory 不是第四个数据库,它就是 context window 本身。工程师最常见的误解,是把这四类想象成四个并排的存储引擎、各配一张表。实际上只有后三类(episodic / semantic / procedural)是外部持久存储;working memory 是那块易失的、当前推理用的窗口——也就是 1.1 节讲的输入缓冲区。后三类记忆被检索出来后,正是被装进 working memory(context window)才能被模型用上。记牢这条,第 3 章"分层上下文"才不会读拧。
② Episodic memory(情景记忆)
具体过往经历的记录——发生过的事,带时间和情境。
实例:工具调用历史、对话轮次、观察结果这类可检索的轨迹。最典型的是"上次试 X 方案失败了"——把那条完整的失败经历(当时的输入、采取的动作、得到的报错)存下来,下次遇到相似情境检索回来,避免重蹈覆辙。episodic memory 是 agent "从过去失败中学习"的物理载体。
③ Semantic memory(语义记忆)
抽象的、去情境化的事实与知识——剥离了"何时何地学到"的纯结论。
实例:存下的用户事实——"偏好 Python""对花生过敏""数据库是 MySQL"。注意它和 episodic 的区别:episodic 记的是"在 5 月 12 日的对话里,用户说他对花生过敏"(带情境的事件);semantic 记的是"用户对花生过敏"(抽掉情境的事实)。第 2 章的写入抽取,很大程度就是把 episodic 的原始轨迹蒸馏成 semantic 的原子事实。
④ Procedural memory(程序记忆)
可复用的技能与做法——"怎么做"而非"是什么"。
实例:学到的工具定义、存下来的可复用计划(plan)。但这里有个最容易被漏掉的部分:
procedural memory 包含 LLM 的权重本身。模型在预训练/微调里学到的"怎么写 SQL、怎么调用 API、怎么做多步推理",是隐式编码在权重里的程序记忆——它不在任何外部存储里,却实实在在是 agent "会做事"的来源。所以 procedural memory = 隐式(LLM 权重)+ 显式(agent 代码 / 工具定义 / 存下的计划),不只是"存下来的技能清单"。这条直接引出 1.4 节的表示轴:权重里的记忆是参数化的,外部存的是文本的。
一个编程 agent 在帮你修 bug 时,记住了三件事:(a) 当前这个函数报了 NullPointerException,(b) 这个项目统一用 4 空格缩进、不用 tab,(c) 三天前它试过用反射绕过这个问题、结果引入了性能回归。把这三件事分别归到 CoALA 的哪一类?
展开答案
(a) working memory——当前决策循环正在处理的活跃信息,就在 context window 里,任务一结束就该清掉。
(b) semantic memory——一条去情境化的项目事实("本项目用 4 空格"),跨任务复用,不关心是哪次学到的。
(c) episodic memory——一条带时间和情境的具体经历("三天前试反射 → 性能回归"),用来"从过去失败学习"。
顺带:agent 本身"会读 stack trace、会改代码"的能力属于 procedural memory(主要在 LLM 权重里,隐式)。一道题里就能同时踩到四类——它们性质不同,所以该用不同的存储和保留策略,这正是分类的意义。
1.4表示轴:文本 vs 参数
CoALA 的四类是按"记什么"切的;表示轴是另一条正交的维度,按"记在哪种介质里"切——记忆要么是外部存储里的文本(textual / non-parametric),要么是被微调进模型权重的参数(parametric)。
四类记忆回答"这条信息是什么性质",但没回答"它物理上存在哪、长什么样"。同一条 semantic 事实,可以是向量库里的一行文本,也可以是被微调进权重的一个隐式倾向;同一类 procedural 技能,可以是一段存下来的 plan(文本),也可以是模型权重里学到的能力(参数)。这条轴和四类正交——把它单独拎出来,才能解释为什么"文件即记忆"和"微调即记忆"是两条根本不同的技术路线,各有各的代价。
底层机制(比文档深一层):两种表示的代价结构完全相反。文本记忆存在外部(文件、向量库、知识图谱),是显式的——可读、可审计、可逐条增删改,但每次用上都要把它塞进 context window,于是受 token 上限硬约束:记得越多,单次推理能调进来的越少,且要靠检索来选。参数记忆把信息微调进权重,是隐式的——容量上几乎"无限长"(不占 context),调用时也不花 token,但它有损(信息被压进权重,无法逐条取出或精确删除)、不可解释、更新代价高(要重新训练)。一句话:文本记忆贵在运行时 token、强在可控;参数记忆贵在训练、强在容量与零 token 调用。生产系统里绝大多数 agent memory 走文本路线——正因为可审计、可逐条治理,而这恰是第 2 章治理层的前提。
文本记忆像翻字典——每个词条明明白白写在纸上,能查、能划掉、能改,但查的时候得把书翻开占着手(占 context)。参数记忆像母语直觉——你说中文不用查任何表,张口就来(零 token),但你也说不清某个语感"存"在脑子哪一格,更没法精确删掉某一条。
失效边界:这个类比会让人以为两者非此即彼。实际生产 agent 常常同时用——参数记忆(模型权重)提供基础能力,文本记忆(外部存储)提供可治理的个性化事实。本教程聚焦后者:因为可写、可治理、可审计的那条路,才是 1.2 节定义的"agent memory"的主战场。
自测
- 同事说:"我把窗口升到 1M token 了,等于给 agent 加了记忆。" 用一句话指出他混淆了什么,并说出 agent memory 比"更大的 context"多出来的那一条边是什么。
参考答案
他把"工作记忆的容量"当成了"记忆"。更大的窗口只是把易失缓冲区加宽,仍然会话间清空、被动喂入。agent memory 多出来的那条边是由 agent 自己掌控的写入路径(自编辑)+ 一个治理层——让信息能跨会话持久并演化。容量大小和这条边是两回事。
- RAG 和 agent memory 在"读取"步骤上几乎一样,为什么不能说"接了 RAG 就等于有记忆"?
参考答案
因为 RAG 只是 agent memory「读取」步骤的子集,缺两块:① 写入路径——RAG 不会把交互中产生的新事实主动沉淀进库(语料是离线批量更新);② 治理层——RAG 不做去重、冲突消解、遗忘。所以 RAG 回答"文档里写了什么",而 memory 回答"agent 学到了什么"。差别不在向量检索,在那条写入+治理的路径。
- 把下面三条信息分别归到 CoALA 四类,并指出哪一条"根本不在外部数据库里":(a) 最近三轮对话;(b) 用户"对花生过敏"这条事实;(c) 模型"会写 SQL"的能力。
参考答案
(a) working memory——就是 context window 本身,易失。
(b) semantic memory——去情境化的事实,外部存储里的一条文本。
(c) procedural memory,且隐式编码在 LLM 权重里——这就是"根本不在外部数据库里"的那条,对应表示轴的参数(parametric)一侧。 - "四类记忆"和"文本 vs 参数表示轴"是什么关系?举一个落在不同表示侧的同类记忆例子。
参考答案
两者正交:四类按"记什么"分,表示轴按"记在哪种介质"分。例:procedural memory(同一类)既可以是外部存下来的一段可复用 plan(文本侧),也可以是微调进模型权重的一项能力(参数侧)。任何一类记忆都能落在表示轴的任一侧。
给"写入路径"画一条最小的工程边界
1.2 节说写入路径是 memory 独有的那条边。现在反向逼问:假设给一个纯 RAG 系统加一个旁路——每轮对话结束后,用一次 LLM 调用把"用户说过的新事实"抽出来、追加写进同一个向量库。这样它就变成 agent memory 了吗? 列出它仍然缺什么才算真正的闭环。
参考来源
- Sumers, Yao, Narasimhan, Griffiths. Cognitive Architectures for Language Agents (CoALA). arXiv:2309.02427, 2023-09 ——四类记忆(working/episodic/semantic/procedural)的来源框架。
- Packer et al. MemGPT: Towards LLMs as Operating Systems. arXiv:2310.08560, 2023-10 ——把 context 当易失"内存"、外部存储当"磁盘"的视角,第 3 章详解。
- Zhang et al. A Survey on the Memory Mechanism of Large Language Model based Agents. arXiv:2404.13501, 2024-04 ——记忆机制综述,含文本 vs 参数表示轴的系统梳理。