定义

将 Agent 记忆拆分为 L1 持久画像(用户是谁)、L2 程序性记忆(标准做法)和 L3 历史检索(过去做了什么)三层,防止记忆腐化并按需加载以控制 token 成本。

三层结构

层级回答什么存储位置更新频率加载时机
L1 持久画像用户是谁单文件(user.md)半年/一年改一次需要理解用户背景时
L2 程序性记忆这种事的标准做法超薄索引 + 按主题切碎的小文件踩坑后沉淀启动时只读索引,命中再加载
L3 历史检索过去做过什么按天分日志 + 语义检索引擎每次对话自动写入只在主动查询时加载

记忆腐化

记忆腐化(Memory Corruption)来自 NousResearch 开源的 hermes-agent 项目:当"我是谁""我该怎么做""昨天发生了啥"全混在一个文件里时,时间一长三种东西互相污染——昨天的临时决定被当成长期判断,半年前的画像被今天的情绪覆盖,过去踩坑的细节被改写得面目全非。

三层分离的核心纪律:混淆 = 记忆腐化。每次写入记忆前先判断属于哪一层,分错了宁可不写。

加载策略

关键不是"记了什么",而是"什么时候读什么":

  • L1: 仅在需要确认用户偏好、语气、忌讳时读取
  • L2 索引: 每次对话启动时读取(仅几 KB),命中钩子后再加载对应小文件
  • L3: 默认不读,仅在用户主动查询历史时检索

按需加载将每次对话启动的 token 成本从 3 万降到不到 3000。

语义去重

L2 的 memory_update.py 在写入前做语义比对:

  • 发现同义条目 → 跳过不写
  • 发现补充细节 → merge 进现有条目
  • 只有真正新的判断 → 追加

防止 L2 在长期使用后充满同义重复的废条目。

"吃一堑长一智"闭环

三层记忆的最高价值体现在跨对话经验复用:

  1. 第一次踩坑 → 花数小时修复 → 写入 L2 程序性记忆
  2. 三周后新对话 → Agent 启动时读 L2 索引 → 命中钩子 → 加载小文件
  3. Agent 自动绕开同一个坑 → 无需用户提醒

关键数据点

  • 单文件 memory.md(3000+ 行)→ 三层分离后,对话启动从 3 万 token 降到不到 3000 token
  • L2 索引仅几 KB,包含"标题 + 一句话钩子"格式
  • L3 语义检索使用 OpenViking(字节跳动火山引擎 2026 年 1 月开源的上下文数据库)
  • 作者实测 L2 下挂着 38 个经验教训小文件,每条背后都是一段实际踩坑

对话结束协议(5 步交班)

每次对话结束时 Agent 自动执行:

  1. A. 经验沉淀 — 可复用经验/决策/偏好 → 写 L2
  2. B. 事实流水 — 完成任务/决策/待跟进 → 写 L3 日志
  3. C. 知识编译(distill) — 高密度产出 → 编译为独立笔记
  4. D. 文件统计 — 笔记增删移动 → 刷新 Vault 总览
  5. E. Self-check — 下一个 session 能否从已有记录拿到所有信息?

前提与局限性

  • 三层划分高度贴合个人开发者 + Obsidian Vault 场景;企业级多人/多角色/权限分层场景需要扩展
  • 语义去重依赖 LLM 判断,误合并(不同经验判为同义)比漏写更危险
  • L1 持久画像假设用户特征稳定,但人的偏好和角色会演化,需要定期审视
  • token 数据(3 万→3000)来自单人实践,缺乏控制组

关联概念