「AI Agent」Agent 的记忆机制:四层记忆分类与记忆模块设计
0 前言
本文内容整理自公众号「小林面试笔记」的文章 8. 请你介绍一下 AI Agent 的记忆机制,并说明在实际开发中应该如何设计记忆模块?,用于记录与总结 AI Agent 相关的核心面试知识点。
「AI Agent 的记忆机制分哪几种?实际开发中应该怎么设计记忆模块?」,可以这样作答:
Agent 的记忆机制分为四个层次,从最短暂到最持久:感知记忆是当次调用的原始输入(用户消息、上传的截图),处理完即消失;短期记忆是 context window 里的 messages 列表,维持当前任务的完整状态,任务结束就清空;长期记忆存在向量数据库/关系数据库里,跨任务持久化,支持语义检索;实体记忆是从对话中提炼出来的结构化事实(如「用户偏好 Python」),信息密度最高、可精确查询。其中长期记忆还可以细分为情节记忆(具体任务经历)、语义记忆(提炼出的规律)、程序记忆(可复用的操作 SOP)。
实际设计记忆模块要解决三个工程问题:存什么——只存对下次任务有价值的信息(用户偏好、关键结论、外部知识),过滤推理过程和闲聊噪音;怎么存——需要语义检索的非结构化内容用向量数据库,可精确查询的结构化偏好用关系数据库/Key-Value,主流做法是混合存储;什么时候取——任务开始前做一次主动检索,把用户画像注入 system prompt,执行过程中把「查记忆」封装成 Tool,让 Agent 按需检索。
最后用「读 → 用 → 写」三个阶段闭环:任务开始前读记忆加载背景,执行中靠短期记忆保持连贯,任务结束后把新知识写回持久化存储。Agent 用得越多、积累越厚,这是记忆系统真正的价值。
生产级例子:Claude Code 就是这套记忆设计的现实落地——项目根目录的 CLAUDE.md 相当于「实体记忆 + 长期记忆」,它保存用户偏好、项目约定和规则,每次会话启动时自动加载进 context(主动检索);会话内的对话历史是「短期记忆」,维持多步任务的状态;当用户把「以后都用 TypeScript」这类约定写进 CLAUDE.md 时,就是「任务结束后写记忆」的动作。Cursor 的 .cursor/rules(如 AGENTS.md、*.mdc 规则文件)同样是同一思路:把结构化的项目规范持久化,让 Agent 跨会话保持「记忆」。
1 没有记忆的 Agent 有多不好用
要理解记忆为什么重要,先感受一下「没有记忆」的 Agent 是什么体验。
你今天告诉 Agent「我喜欢代码风格简洁、变量命名用英文、不要过度注释」,它帮你完成了今天的任务。明天你重新打开对话让它写个新功能,它输出的代码风格和昨天说好的完全不一样——中文注释一堆,变量名也很啰嗦。你一脸困惑,但对 Agent 来说,昨天的对话压根不存在,每次对话都是全新的开始,之前达成的所有约定都消失了。
这还只是「偏好记忆」层面的问题。更严重的是「任务状态」问题:Agent 在执行多步任务时,如果没有短期记忆维持状态,它就不知道自己上一步做了什么、当前处于哪个阶段、已经收集了哪些信息。你让它「先查资料,再整理成报告」,没有记忆的话,整理报告那一步根本不知道查到了什么。
一句话总结:记忆,是 Agent 从「单次问答工具」变成「真正助手」的关键分水岭。 有了记忆,它才能积累对你的了解,才能在多步任务中保持连贯,才能跨任务沉淀知识。
2 四种记忆类型:从最短暂到最持久
记忆机制可以类比人类的记忆系统来理解,从最短暂到最持久分为四个层次。要注意的是,这里的「感知 / 短期 / 长期 / 实体」是工程上方便管理记忆的一种划分,借用了认知科学的概念,但和心理学严格的分类不完全一致,目的是帮你建立直觉。
2.1 感知记忆:当次调用的原始输入
最短暂的一层,就是「当前这次调用的原始输入」——用户发来的消息、上传的截图、传入的文档。它的生命周期只有一次调用,处理完就消失,不会主动保留。
类比到人:你刚听到一句话,如果没有主动去记,几秒后就忘了。感知记忆就是这个「刚进来还没处理」的原始感知,它的意义是给模型提供一个「入口」来接收外部信息。
2.2 短期记忆:context window 里的工作台
这是 context window 中的 messages 列表,维持着当前任务执行过程中的完整状态:用户说了什么、模型输出了什么、工具调用返回了什么,全部都在里面。只要任务还在进行,这些信息就一直有效;任务结束(对话关闭),这块记忆就清空了。
把它想象成你的「工作台」:桌上摆着的都是正在处理的东西。工作台有大小限制(token 上限),放满了就得清一清;但它的特点是「随时可见」,不需要翻箱倒柜地「找」,直接读就行。
2.3 长期记忆:存到数据库里的档案室
这是跨任务保留的信息,存在外部数据库里,通常是向量数据库、关系数据库或 Key-Value 存储。任务结束了信息不会消失,下次需要时去检索拿回来用。类比成「档案室」:东西放进去不会丢,但要用的时候需要主动去翻。
长期记忆的关键技术是向量数据库,它支持「语义检索」:你不需要记得存的时候用了什么关键词,只要意思相近就能检索到。比如你存的是「用户不喜欢冗长的注释」,用「代码风格偏好」去查也能找到它。
长期记忆不是铁板一块,还可以细分成三种子类型:
| 子类型 | 存什么 | 用途 |
|---|---|---|
| 情节记忆 | 具体的事件经历,如「上周写爬虫遇到反爬,最后用 Selenium 解决」 | 遇到类似新任务时检索历史相似经历,参考上次的解法,避免重复踩坑 |
| 语义记忆 | 从多次经历中提炼出的规律,如「网站有 JS 动态渲染时 requests 抓不到,优先用 Selenium/Playwright」 | 信息密度更高、更容易命中,直接存结论而不是过程 |
| 程序记忆 | 做某事的操作 SOP,如「部署 Flask 应用:建虚拟环境 → 装依赖 → 配 gunicorn → 配 nginx → 启动」 | 处理重复性任务时直接调出 SOP 执行,快且稳 |
实际项目中三种子类型通常混合使用:情节记忆提供参考案例,语义记忆提供抽象规律,程序记忆提供可复用流程,三者配合才真正好用。
2.4 实体记忆:结构化的事实卡片
这一层比长期记忆更精炼,不存原文,而是把对话中出现的关键实体和事实主动提取出来,存成结构化字段。比如「用户偏好 Python」「客户预算是 5 万」「项目截止日是 3 月底」——这些是从对话里提炼出来的「结论」,而不是原始对话本身。
类比医生病历卡:不是把问诊录音存起来,而是结构化地记录「主诉:头痛三天;诊断:偏头痛;用药:布洛芬」。信息密度高,查询快,不受原始表述方式影响。

四层记忆横向对比:
| 类型 | 载体 | 容量 | 生命周期 | 访问方式 |
|---|---|---|---|---|
| 感知记忆 | 当次输入 | 极小 | 单次调用 | 即时访问 |
| 短期记忆 | context window | 受 token 限制 | 一次任务 | 直接读取 |
| 长期记忆 | 向量/关系数据库 | 无限 | 持久 | 语义检索 |
| 实体记忆 | 结构化存储 | 无限 | 持久 | 精确查询 |
3 设计记忆模块的三个核心问题
理解了四种记忆类型,设计记忆模块时还要解决三个工程问题:存什么、怎么存、什么时候取。
3.1 存什么?判断标准是「下次有用吗」
不是所有内容都值得写入长期记忆,存太多反而会引入噪音、拉低检索精准度。判断标准其实很简单:「这条信息,下次任务开始时如果知道,会让 Agent 做得更好吗?」
通常值得存的三类:
- 用户偏好和习惯:语言风格、技术栈偏好、工作习惯;
- 任务执行中的关键结论和决策:比如「调研发现竞品 A 的定价策略是按用量收费」;
- 外部知识:产品文档、FAQ、历史案例。
不值得存的:中间推理过程、工具返回的原始数据(日志太啰嗦)、闲聊内容。这些存进去只会稀释有价值的记忆,让检索信噪比下降。
3.2 怎么存?按信息类型选介质,混合存储是主流
不能一刀切地全部塞进向量数据库,要根据信息类型选合适的存储介质:
- 需要语义检索的内容(文档知识、对话摘要这类非结构化文本)→ 向量数据库,embedding 编码后相似度检索;
- 可精确查询的结构化内容(语言偏好、项目配置等字段)→ 关系数据库或 Key-Value,查询快、不需要语义理解;
- 整段文档/知识库 → 向量数据库,配合 RAG 流程做召回。
混合存储是主流做法:结构化偏好字段用关系数据库精确查,非结构化知识和历史用向量数据库语义检索,两者配合使用。

3.3 什么时候取?主动检索 + 按需检索
这个问题有两种策略,实践中通常结合使用:
- 主动检索:任务开始前,用当前任务的描述去检索相关记忆,把结果注入 system prompt 作为背景知识。Agent 一开始就带着「历史记忆」进入任务,不需要用户每次重新交代背景。
- 被动触发(按需检索):Agent 在推理过程中,判断当前步骤需要某类特定知识时主动发起检索。具体做法是把「查记忆」封装成一个 Tool,让 Agent 自己决定什么时候调。这种方式更灵活,但依赖模型的判断能力。
实践上两者结合效果最好:session 开始时做一次主动检索,把用户偏好和背景记忆加载进 system prompt;执行过程中,遇到需要专业知识或历史数据的步骤,再让 Agent 按需检索。
4 Context Window 管理:工作台满了怎么办
短期记忆存在 context window 里,而 context window 有 token 上限。复杂多步任务中,对话历史越来越长、工具返回结果越来越多,很快会把 context window 塞满——满了之后新内容进不去,或者被迫截断早期历史,Agent 就会「失忆」。

解决方案从简单到复杂有好几种思路。
方案一:滑动窗口。 只保留最近 N 轮对话,更早的历史直接丢弃。实现简单,代价是早期重要信息可能被丢掉——比如用户第一轮就说「所有代码用 TypeScript」,到了第十轮这条信息被滑出窗口,Agent 又开始写 JavaScript。
方案二:摘要压缩。 历史长度接近上限时,用 LLM 把早期对话压缩成一段摘要替换掉冗长历史。比如把前面十轮对话压缩成「用户要求用 TypeScript 编写一个 REST API,已完成数据库设计和路由定义,当前正在实现用户认证模块」,token 占用从几千降到几百。代价是压缩过程会丢失细节,且需要额外的 LLM 调用来做摘要。
方案三:卸载到长期记忆。 把不常用但重要的信息「卸载」到长期记忆里——执行过程中产生的中间结果,当前步骤不需要但后面可能用到的,先存进向量数据库、从 context window 移除,等后面某步需要时再检索回来。相当于给工作台配了个「抽屉」,桌面放不下的先收进去,要用时再拿出来。
值得了解的三个记忆框架
这三类传统方案已经能解决大部分场景,但最近两年出现了一些更系统化的开源框架。
- Mem0:社区最活跃的 Agent 记忆框架之一(GitHub 超 5 万星)。核心思路是把记忆管理做成独立服务层,你只需调用
memory.add()存、memory.search()查,底层 embedding、去重、冲突消解全帮你做了。支持按 user_id 做记忆隔离,同时支持向量存储和图存储。 - Letta(前身是 MemGPT):设计灵感来自操作系统的内存管理,把 Agent 记忆分成三个层级——Core Memory(始终留在 context window 的核心信息,相当于主存)、Recall Memory(最近的对话历史,相当于缓存)、Archival Memory(长期归档知识,相当于磁盘)。最有意思的是让 Agent 自己通过工具调用管理这三层记忆,比固定规则更灵活,但更依赖模型判断力。
- Zep(及开源组件 Graphiti):引入「时间感知」概念,给每条记忆标注「有效时间窗口」,比如「用户预算是 5 万」可能三个月后就过期了。通过时序知识图谱管理记忆生命周期,自动识别过时记忆,在长期运行的 Agent 系统中很实用。
5 知识图谱:让记忆之间产生关联
向量数据库做语义检索,本质上是「一条一条」地存记忆、取记忆,每条记忆之间相互独立、没有关联。但很多时候,信息之间的关系和信息本身一样重要。
比如你存了「用户 A 是公司 B 的 CTO」和「公司 B 的主营业务是云计算」,如果两条记忆之间没有关联,问「用户 A 所在公司做什么业务」时,纯向量检索可能检索不到——因为这两条记忆的文本相似度并不高。
知识图谱就是解决这个问题的。它用「实体 → 关系 → 实体」的三元组结构存信息:「用户 A → 担任 CTO → 公司 B」「公司 B → 主营业务 → 云计算」「公司 B → 成立于 → 2015 年」。实体之间通过明确的关系连接,形成一张网状知识网络。
查询时可以沿着关系链条做多跳推理——问「用户 A 所在公司做什么业务」:从「用户 A」沿「担任 CTO」找到「公司 B」,再沿「主营业务」找到「云计算」,两跳拿到答案。这种沿关系链跳转查询的能力是向量检索做不到的,因为向量检索只能找语义相近的内容,而「用户 A」和「云计算」在语义上根本不相近。

实践上,知识图谱通常是和向量数据库配合使用:对话过程中用 LLM 自动提取实体和关系存入知识图谱;检索时先用向量检索拿一批候选记忆,再用知识图谱补充关联信息,合并后注入 context。向量库负责模糊语义检索(「之前那个项目」),知识图谱负责精确关系推理(「查某个用户的所有相关公司和角色」),两者互补。
6 记忆整合:从碎片到知识
Agent 用久了,长期记忆里会积累大量碎片化信息:同一个主题可能存了十几条不同时间的记忆,有些重复、有些过时、有些互相矛盾。不整理的话,检索噪音越来越大,有用的记忆被淹没在碎片里。
记忆整合就是定期对长期记忆做「清理和升华」,包含三个关键环节。
1. 去重。 把语义相近的多条记忆合并成一条更完整的版本。「用户喜欢简洁的代码」「用户说过代码要精简」「用户要求不要冗余代码」其实是同一个意思,合并成「用户偏好简洁精练的代码风格,反对冗余」就够了。
2. 冲突消解。 两条记忆互相矛盾时(「用户偏好 Python」和后来说的「最近转用 Go 了」),保留时间更新的那条、标记旧的为过期。这里时间戳至关重要——没有时间戳就无法判断哪条是最新的。
3. 抽象提炼。 最有价值的一环,本质上是把情节记忆转化为语义记忆的过程。三条独立的情节记忆——「写爬虫时 requests 被反爬拦住,换 Selenium 才行」「抓电商价格时页面是 JS 渲染的,requests 拿到空页面,最后用 Playwright 解决」「采集论坛帖子时同样遇到动态加载」——放在一起会蒸馏出一条共同规律:「当目标网站有动态渲染时,基于 HTTP 的请求库往往拿不到完整内容,需要用浏览器自动化工具来处理」。这条规律比任何一条情节记忆都更通用、更浓缩、更容易被检索命中。

整合的节奏也很重要:每次任务结束后做一次轻量级去重和更新即可,每隔一段时间(每天或每周)再做一次深度整理提炼,把累积的情节记忆批量转化为语义记忆。有些框架(如 Mem0)已内置这种后台异步整合逻辑,无需手动触发。这样长期记忆会越来越精炼、越来越有价值,而不是越积越乱。
7 完整闭环:「读 → 用 → 写」
把四层记忆和三个核心问题串起来,看一次完整任务里它们如何协作。整个过程可以用「读 → 用 → 写」三个阶段描述。
第一阶段:任务开始前,先「读」记忆。 用户发来新请求,Agent 先「翻档案」:从实体记忆里取出用户的结构化偏好(语言偏好、风格要求、过往决策),再用任务描述作为查询词去长期记忆里做一次语义检索,拿回最相关的历史背景。两者拼进 system prompt 开头,Agent 进入任务时已带着完整的「用户画像」,不需要用户重复交代背景。
第二阶段:任务执行中,持续「用」记忆。 短期记忆(messages 列表)全程工作:用户的每条消息、模型的每次输出、工具调用的每个结果都追加进 messages,每次调用 LLM 都带上完整历史,Agent 始终知道自己做到哪一步。某个步骤需要特定专业知识时,把「查记忆」封装成 Tool 临时检索,用完即走,不必永久保留在 messages 中。
第三阶段:任务结束后,主动「写」记忆。 把本次任务产生的新知识写回持久化存储:用户表达了新偏好(「以后写函数都要加类型注解」)就更新实体记忆对应字段;任务产生了有价值的结论(「竞品 A 的定价是按用量收费」)就把摘要写入长期记忆,embedding 后存入向量数据库。最后短期记忆清空,工作台恢复干净,等待下一个任务。

「读 → 用 → 写」形成完整闭环:每次任务开始时把历史积累读进来,执行中靠短期记忆保持连贯,结束后把新知识写回去沉淀。Agent 用得越多、积累越厚,越来越「了解」用户,这才是记忆系统真正的价值。
8 要点回顾
回答 Agent 记忆机制这道题,要答出三个层次才完整:
| 层次 | 要点 |
|---|---|
| 记忆分四层 | 感知记忆(当次输入)、短期记忆(context window 的 messages)、长期记忆(向量/关系数据库,含情节/语义/程序三种子类型)、实体记忆(结构化事实) |
| 三个工程核心问题 | 存什么(只存对下次任务有价值的信息)、怎么存(非结构化用向量库、结构化用关系库、混合存储是主流)、什么时候取(任务前主动检索 + 执行中按需检索) |
| 读-用-写闭环 | 任务开始前读记忆加载背景,执行中靠短期记忆保持连贯,结束后把新知识写回沉淀 |
再补充三个进阶加分项:Context Window 管理(滑动窗口 / 摘要压缩 / 卸载到长期记忆)、知识图谱(三元组 + 多跳推理,与向量检索互补)、记忆整合(去重 / 冲突消解 / 抽象提炼)。把这三个层次加上进阶点答全,再加上 Claude Code 的 CLAUDE.md、Cursor 的 .cursor/rules 这类生产级例子,这道题就回答得很漂亮了。
参考
- 8. 请你介绍一下 AI Agent 的记忆机制,并说明在实际开发中应该如何设计记忆模块? | 小林面试笔记
- 7. 复杂任务怎么做的任务拆分?为什么要拆分?效果如何提升? | 小林面试笔记(前一篇:任务拆分)
本文图片均来源于公众号「小林面试笔记」,版权归原作者所有。