智能体记忆系统
一、Memory 在 Agent 里到底解决了什么问题?
如果只看一次调用,LLM 是强大的函数:输入上下文,输出文本。但它是严格的“无记忆”:每次调用之间没有内在状态,所有“记忆”都靠你在 prompt 里重复塞进去。你可以通过加长上下文模拟记忆,但这只是人为堆砌,并不是真正的记忆系统。
智能体的问题恰好相反: 它的存在不是一次调用,而是一段时间内的行为轨迹。 它要:
- 跑几十轮以上的推理循环;
- 处理长时间任务(小时、天、甚至更久);
- 跨多个会话理解同一个用户;
- 避免重复犯同样的错误;
- 在新的事件发生时,带着旧的信息继续决策。
这些都要求它拥有某种“时间结构”: 过去发生的事情不会在每次推理后蒸发,而是沉淀、折叠、裁剪、复用,成为当前决策的背景。
这就是 Part 15 的核心观点: Memory 不是“多一个向量库”,而是让 Agent 从“瞬间反应”变成“时间上的存在”。
二、Memory 不是一个地方,而是一套层级结构
如果只是说“记忆”,容易想到一个统一的“大的记忆库”。但对 Agent 来说,更合理的视角是:不同时间尺度、不同粒度的记忆在承担完全不同的角色。
最靠近当前循环的,是类似“工作记忆”的东西: 上一轮调用了什么工具、得到了什么 Observation、当前任务状态是什么、用户刚刚说了什么。这部分信息在每一轮推理中都高度相关,但生命周期有限,用完就可以丢弃。
再往外一层,是“任务级记忆”: 整个 Mission 过程中发生了什么、走过哪些分支、哪些尝试失败过、哪些工具表现不稳定、用户在这一任务中表达过哪些偏好。这些不是为了下一次 token 输出,而是为了整个任务在几十轮循环中保持方向一致,不至于每次都重新探索相同的错误路径。
再往远一点,是“跨任务记忆”: 这个用户一贯在意什么? 他喜欢简短答案还是详细展开? 他在哪些问题上曾经表达过强烈偏好或禁忌? 系统在某类任务上曾经踩过哪些坑?
这些信息不属于某一个对话,而属于“这个智能体和这个用户的关系史”、“这个系统在这个问题域上的经验史”。它们像人类的“长期记忆”:不是每次都拿出来,但在关键时刻会影响决策偏好。
最外围的,是“稳定知识”(知识库): 领域规则、产品结构、政策与规范、业务 DSL、工具说明…… 这些东西不是记忆某次事件,而是构成这个世界的“骨架”。它们像是 Agent 所在世界的“物理定律”和“制度安排”。
Part 15 要表达的是: 如果你把这几层全部都叫 memory,并丢进一个向量库里,你就等于没有设计。 真正的 Memory 是一个时间分层结构,每一层负责不同尺度的“时间事实”。
三、真正难的是“写什么进去”和“什么时候忘掉”
很多实现里,memory 变成一个“全部塞进去、用 embedding 去检索”的大池子。结果很快出现三个问题:存储爆炸、检索噪声、上下文污染。 真正有价值的 memory 不是“能存”,而是“敢删”“会压缩”。
写入这一侧,最关键的问题是“什么值得被记住”。 不是所有事件、所有对话、所有 Observation 都有长期意义。你需要某种“显著性机制”: 某次用户明确表达偏好; 某次工具发生危险错误并被人工干预; 某个流程产生了反复出现的坑点; 某种错误被判断为“以后要主动规避”。
这些才应该被提炼为更长期的记忆片段,而不是原始日志逐行塞入向量库。这种提炼本身就是推理工作:智能体或 orchestrator 要对事件进行“抽象”,把它从“当时发生的细节”转换成“以后决策可用的规则或事实”。
忘却则是另一个同等重要的机制。 如果没有遗忘,memory 很快变成垃圾堆;如果遗忘不慎,又可能丢失关键经验。这就需要一种“时间 + 频次 + 重要性”的权衡机制:冷数据逐渐被压缩为粗略摘要,高频但已被更高层规则覆盖的细节可以被丢掉,敏感或过时的信息则必须有策略性地删除或标记失效。
Part 15 的一个隐含观点是: Memory 系统如果没有“选择”和“遗忘”,本质上只是历史日志,不是智能记忆。
四、Memory 和 Context 的关系:谁是实时,谁是累积?
上下文 engineering 和 Memory 经常被混用,但它们解决的是两个不同的问题:
Memory 关心的是:如何让过去以某种结构存在下来; Context 关心的是:这一时刻要从所有可能的信息里选出“适合给模型看的那一小部分”。
你可以把 Memory 看成“原材料仓库”, Context 则是“当前这顿菜的食材组合”。
从 Memory 中检索和选择,是一个两步走的过程: 先从不同层级 Memory 里找出“可能相关”的片段,再由 orchestrator 按当前任务需求,构造一份紧凑、语义连贯、信息量适中的上下文。这中间可以有过滤、重写、摘要、排序、去重甚至对比。
Part 15 要你意识到:Memory 和 Context 不应该是同一个东西。 如果你把 Memory 直接塞进 prompt,就等于没有 Context 工程; 如果你每次上下文都从零开始构造,又等于没有 Memory。
Memory 是“给 Context 提供素材的时间维度系统”, Context 是“让模型在当下有效思考的感知窗口”。
五、Memory 与其他核心模块的关系
Part 15 其实不是孤立章节,它和之前那些核心部分是互相嵌套的。
和 Part 3 的循环(Think → Act → Observe)相比,Memory 是让这个循环“带着历史跑”的机制。每次 Observe 的结果,不是只写在日志里,而是有选择地写入 Memory;下一次 Think 之前,会从 Memory 里取出必要的东西加入上下文。循环本身因此从“近视”变成了“带历史视野”的循环。
和 Part 5 的架构三件套相比,Memory 站在 Model 和 Orchestrator 之间。如果说 Model 是瞬间推理器,那么 Memory 就是用来让 Orchestrator 在时间上为 Model 构造“长期感知”的系统。模型不记得任何事情,是 orchestrator 通过 Memory,不断给它“塞回人生经验”。
和 Part 6 的 Orchestration 比,Memory 是一个关键的“子系统”。编排层的很多决策——比如现在要不要调用某个工具、要不要重复某个尝试、要不要调用人类协助——都需要依赖过去的经验。没有 Memory,orchestrator 就没有“长期偏好”和“实践中的教训”,只能永远在当前状态里做局部贪婪选择。
和 Part 9 的 Agent Ops 相比,Memory 是评估和优化的素材库。每一次任务轨迹,都会沉淀成某种可再现的 memory;评估系统会在这些 memory 之上分析模式、构造评估集、训练评审 Agent。系统“如何学会变得更好”,其实就是“如何在 Memory 上运行 Ops”。
甚至连安全(Part 13)也严重依赖 Memory: 你要知道这个 Agent 曾经做过哪些危险行为,哪些用户有敏感历史,哪些流程曾经触发过风控,才有可能在将来的决策中主动规避同类风险。如果安全系统没有记忆,每次都是“第一天上班”,那它无法形成真正的防御深度。
六、从工程上看,Memory 是一个“设计空间”,而不是一个组件
Part 15 不是在教你“用某个库”,而是在提醒: Memory 是整个 Agent 系统里最接近“人格”的部分。
你如何设计 Memory:
决定了智能体是“短视”还是“长线思维”; 决定了它是“机械重复犯错”,还是“从错误中改进”; 决定了它是“每次和用户见面都像新人”,还是“真正建立关系”; 决定了它是“被历史拖垮”,还是“从历史中抽象出稳定规则”。
你可以用最简单的方式实现 Memory: 一个 KV 存储,加一个向量库,加一些时间戳。 你也可以把 Memory 设计成一个“会随时间精炼的知识层”: 每次任务结束都生成一片小的经验碎片,这些碎片被系统不断聚类、归纳、重写,最后变成“系统行为准则”和“领域经验库”。
这中间有巨大的设计空间,也很可能成为未来不同 Agent 系统之间真正的差异化所在。
七、一句话回看 Part 15 的核心
如果用一句话把这一章收紧:
Memory 让 Agent 不再只活在一个调用里,而是可以活在时间里。 它不是存储,而是“时间上的结构化心智”。
理解这一点,你就不会再把“加个向量库”当成 Memory,而会开始从“时间”和“行为史”的角度来思考:你的智能体究竟要记住什么、忘掉什么、如何在记忆上生长出真正的智能。
如果你愿意,我们之后可以专门做一版: “如何给一个真实 Agent 设计 Memory 子系统”的实战稿, 从 schema、存储、检索策略、压缩策略、清理策略一路拆下去。
那就开干,直接上「怎么给一个真实 Agent 设计 Memory 子系统」的实战版。
一、先把边界画清楚:Memory 不是日志,也不是向量库
给一个真实 Agent 设计 Memory 子系统,第一步其实不是选数据库,而是想清楚:你到底要让这个 Agent「在时间维度上活成什么样」。
如果 Memory 只是简单把所有对话、所有工具调用、所有 Observation 全部丢进日志,再加一层 embedding 检索,那本质上只是一个“可搜索的历史记录系统”,跟真正的智能记忆差得很远。真正的 Memory 子系统要回答的是三件事:
这台 Agent 需要跨多久的时间保持连续性; 它在多长的时间尺度上会复用过去经验; 它需要在什么层次上抽象这些经验,避免被原始细节拖垮。
一旦这三个问题清楚了,后面的 schema、存储和策略才有意义。
二、先划分记忆层级,再设计数据结构
比较稳妥的做法,是先在设计层面把记忆按时间和粒度分成几层,然后为每一层定义单独的 schema,而不是用一个万能“memory”表解决所有问题。
短期记忆通常是围绕某一次 Mission 或 Session 的上下文状态,它不需要跨任务,只要保证当前循环和当前对话的连续性。它的数据结构很像一个「任务状态快照」,例如:
{
"mission_id": "M-2025-0001",
"step": 12,
"actions": [
{
"tool": "lookup_order",
"input": { "id": "123" },
"result_ref": "obs-001"
},
{
"tool": "track_shipment",
"input": { "tracking": "XYZ" },
"result_ref": "obs-002"
}
],
"current_hypothesis": "Order exists, shipment delayed at customs.",
"pending_questions": ["Need confirmation of customer's preferred resolution."]
}
中期记忆围绕整个任务生命周期,它不关心每个 token,而是关心“这单活到底是怎么完成的”。这里更像一个「任务轨迹」的抽象版,会把几十轮循环折叠成一个较短的 story,包括关键决策、重大错误、人工介入点和最终结论。它的 schema 可以接近:
{
"mission_id": "M-2025-0001",
"summary": "Resolved delayed shipment issue by contacting carrier and issuing partial refund.",
"key_events": [
{ "type": "error", "code": "TOOL_TIMEOUT", "at_step": 5 },
{ "type": "human_handoff", "reason": "Customer anger high", "at_step": 7 },
{ "type": "policy_applied", "policy_id": "refund-2024-v2" }
],
"lessons": [
"For shipments delayed >7 days, proactively check carrier-side notice before contacting customer."
]
}
长期记忆已经不再关心单一 Mission,而是跨任务的模式,比如用户偏好、常见坑、常见成功策略。它的结构更接近「经验条目」而不是事件日志。例如针对某个用户:
{
"memory_id": "user-pref-001",
"scope": "user",
"user_id": "U-8899",
"description": "User prefers concise answers with clear action items.",
"evidence": [
{
"mission_id": "M-2025-0003",
"snippet": "Please just give me the steps."
},
{
"mission_id": "M-2025-0042",
"snippet": "Too long; summarize in bullets."
}
],
"last_updated": "2025-11-10T12:00:00Z"
}
再往外,就是稳定知识库了,这一层其实已经不算 Memory,而是知识管理,应该有完全独立的 schema 和生命周期。
当你用这种方式拆完,你会发现每一层要存的东西完全不同,访问模式也完全不同,自然不可能用一张一样的表搞定。
三、存储层的划分:别用一个数据库硬抗所有需求
有了层级和 schema,存储选择就变得清晰很多。短期记忆几乎总是和 Session 绑定,读写频繁,生命周期短,而且通常不需要复杂查询,选一个低延迟的 KV 存储或者内存+持久化缓存就够了,比如 Redis 类。关键是:一旦 Mission 结束,这部分内容可以按策略整体丢弃或者只保留部分用于中期记忆总结。
中期记忆和长期记忆则更适合放到关系型或文档型数据库里,因为它们需要跨任务检索、查询、过滤和版本化。同时,你可能会希望对“lessons”或者“summary”字段做 embedding,方便以语义检索对应经验,但原始存储最好保持结构化,而不是只靠向量库。
向量检索适合做“把相关记忆找回来”这一步,而不是做 Memory 的唯一载体。更健康的结构是:存储用关系型/文档库,语义索引用向量索引,两者之间通过主键或 memory_id 关联。这样你在选记忆的时候可以兼顾语义相关度和显式元数据(时间、用户、任务类型等)。
四、写入策略:不是所有东西都配做记忆
接下来最重要的问题就是:Agent 在运行过程中,哪些东西会被写入 Memory?
对短期记忆可以粗放一点,基本每轮循环的 action 和 observation 都可以按一定深度记录,因为它本身就是为当前任务服务的缓存。但到了中期记忆层,你就不能再简单把所有细节原样塞进来,而是应该在 Mission 结束时触发一个“事后反思过程”,由模型或专用的总结 Agent 生成一个任务级 summary 和少量 key lessons,再写入中期存储。
中长期记忆的写入最好是“触发式”的,而不是“全量式”的。比如只有在以下场景才产生一条新的长期记忆: 同类型错误连续出现多次; 用户明确表达偏好、禁忌或强烈情绪; 人工介入留下重要决策; 策略层发生了关键升级或替换。
你可以把中长期记忆看成是一组“抽象的教训”和“风格偏好”,而不是完整历史。换句话说,所有进入长期记忆的东西,都应该是某种“可以在以后改变决策权重”的信息,而不是纯细节。
五、读取策略:如何从 Memory 反哺当前推理
读取 Memory 时,最危险的一种做法,就是“一股脑把所有相关东西都塞进 prompt”。这会让上下文变成垃圾场。健康的策略应该是这样的:先通过 metadata 过滤,再用语义检索缩小范围,最后再在 orchestrator 那层进行二次筛选和改写。
例如,当前 Mission 若属某类任务,你可以先在中期和长期记忆层按 mission_type 做一次过滤,只留下同类任务产生的经验;然后再用 embedding 检索最近若干条与当前问题语义相关的经验;再由一个小模型对这些候选记忆进行重写和归纳,把它们压缩成一段简短的“前情提示”,最后再拼进本轮 LLM 的上下文。
真正需要塞进 prompt 的,不是那一条条原始记忆,而是对它们的再抽象。例如,将三条经验:
“用户不喜欢太多细节”; “之前对这个用户的长篇解释引起过不满”; “该用户偏好清单式输出”。
压成一句对 Agent 的指示:
“对于这个用户,请优先采用简短、结构化、步骤化的回答风格,避免冗长解释。”
Memory 的存在感,对模型来说最终就是这一句话;而底层那几条原始记忆只作为证据保留在数据库里。
六、遗忘与压缩:让智能体不被自己的过去拖死
随着时间推移,Memory 的体量必然膨胀。如果没有合理的遗忘和压缩机制,成本是一个问题,噪声和错误传播更是一个问题。设计 Memory 子系统时,可以把遗忘当成一等公民,而不是事后加的清理脚本。
短期记忆的遗忘策略简单:Mission 结束后,大部分都可以丢弃,只有那些被“选中”进入中期总结的部分才继续存在。中期记忆则可以按时间和价值进行稀释,例如只保留最近 N 天的全部任务 summary,再往前按周、按月进行合并,只留下代表性的几个典型任务。
长期记忆更适合做“层层抽象”。当同一模式在多条长期记忆中反复出现时,你可以触发一个“二次总结过程”,由一个专门的 meta-agent 把它们收束成一条更抽象的规则,然后把旧的散碎条目标记为已合并或降低权重。在极端情况下,甚至可以为这些高频经验写入策略系统,而不再仅仅作为记忆存在。
这个过程听起来有点像人类的学习:一开始记具体的案例,后来记的是“规律”。越往后,记忆越稀疏,但越结构化。Agent 的 Memory 子系统如果能做到这一点,你就会发现长期记忆不会把系统拖慢,反而会让它的行为越来越有“风格”和“惯性”。
七、和安全、评估、个性化的联动
最后,如果 Memory 子系统只是服务于“给模型多喂点上下文”,那这套设计还有一半价值没用起来。真正成熟的 Memory 应该和安全模块、评估模块、个性化模块强绑定。
安全模块可以基于长期记忆识别高风险模式,比如某类输入曾经触发过高危工具调用,某个用户多次尝试越界操作,某些路径曾经导致严重错误。安全策略可以直接引用这些记忆,让系统在同类场景下主动提高警惕,而不是每次都从零开始推理风险。
评估模块可以把 Memory 作为“训练 Agent 的材料库”,例如从历史任务中抽取失败案例,构建评估集;从多次类似任务的不同轨迹中抽取变体,对比不同策略的效果。这样你的 Agent Ops 不再只是统计指标,而是一个在 Memory 上做诊断的分析系统。
个性化模块更是直接依赖长期记忆:用户偏好、语气风格、容忍度、对解释深度的需求、对操作速度的敏感性,这些都是需要长期观察才能抽象出来的东西。一旦 Memory 子系统足够稳固,个性化只是“读取并应用偏好”的问题,而不是给每个会话拼命调 prompt。
八、落地视角:如果今天要开工,应该先做哪三件事
如果现在真的要给一个 Agent 上 Memory 子系统,我会建议先做三件事情,而不是先搭一堆技术栈。
第一,把你现在的任务流画成时间轴,标出哪里需要跨轮次记忆,哪里需要跨任务记忆,哪里需要跨用户记忆。没有这三层区分,后面的设计一定会乱。
第二,为这三层各写一个最小可用的 schema,哪怕一开始字段很少,先让系统有地方“写和读”,然后再迭代复杂度,而不是生来就搞一张巨表。
第三,为“写入”和“读取”各实现一条最简单但完整的路径: 写入时至少经过一轮总结或筛选,不要直接原样塞; 读取时至少经过一次筛选和改写,不要把原始 memory 直接拼 prompt。
等这三个最小闭环跑起来,你再去慢慢加 embedding、加聚类、加压缩、加抽象。Memory 子系统是一个适合慢慢养的东西,但前提是第一天起,它就被当作“时间结构”,而不是“垃圾堆”。
如果你愿意,下一步我们可以直接选一个具体 Agent(比如客服、运营、代码助手、科研 Agent 中任选一个),把这套 Memory 方案具体化成表结构、伪代码和一次完整的读写示例。