很多 AI Agent 都有“记忆”功能,但它们的记忆经常有两个问题:要么默认会忘,要么虽然能记住东西,却不会主动更新。
静态记忆文件在刚开始很好用。比如你把偏好、工作方式、常用规则写进 MEMORY.md,Agent 后续就能参考这些内容。问题在于,人的状态会变化,关系会变化,项目也会变化。如果六个月前写下“Sarah 是我的直属经理,而且管理方式很强势”,后来你已经换了工作,这条信息还停留在记忆文件里,Agent 就可能继续基于旧事实做判断。
动态记忆要解决的不是“多存一点信息”,而是让 Agent 的记忆具备三个能力:
- 能把对话里的长期事实自动抽取出来;
- 能按实体组织信息,而不是堆进一个大文件;
- 能定期把过时事实降级为历史,并生成当前可用的摘要。
Moltbot 的做法是把记忆拆成三层:知识图谱、每日笔记、隐性知识。再配合周期性事实抽取、每周摘要整理,以及 Supermemory 这样的外部记忆系统,让 Agent 的上下文从静态文件变成持续演化的个人知识库。
flowchart TD
A[用户和 Agent 对话] --> B[每日笔记<br/>memory/YYYY-MM-DD.md]
A --> C[周期性事实提取]
C --> D[知识图谱<br/>/life/areas/]
D --> E[实体原子事实<br/>items.json]
E --> F[每周综合整理]
F --> G[实体动态摘要<br/>summary.md]
A --> H[隐性知识<br/>MEMORY.md]
G --> I[下次对话上下文]
H --> I
静态记忆为什么不够用
一个基础 Agent 通常会依赖几类文件或机制:
| 组件 | 作用 |
|---|---|
AGENTS.md | 定义 Agent 的行为规则、工作原则和工具使用约束 |
MEMORY.md | 保存长期偏好、习惯、经验教训 |
| Heartbeats | 让 Agent 周期性醒来,执行检查或维护动作 |
| Cron jobs | 通过定时任务触发自动化流程 |
这些组件能提供最基本的连续性。Agent 可以记住你喜欢什么格式、常用哪些项目、应该遵守哪些原则,也可以定时检查任务。
但是,静态文件有一个根本缺陷:它们需要人工维护。
如果所有信息都写在一个文件里,会出现几个问题:
| 问题 | 具体表现 |
|---|---|
| 信息过期 | 旧工作、旧关系、旧项目仍被当作当前事实 |
| 上下文膨胀 | 文件越来越大,每次加载都浪费上下文窗口 |
| 难以检索 | 想找某个人、某家公司、某个项目的历史,需要在大文件里翻 |
| 难以纠错 | 新事实和旧事实冲突时,不知道该删除、覆盖还是保留历史 |
| 不可审计 | Agent 到底基于哪些事实做判断,不容易检查 |
动态记忆的核心思路是:不要把“记忆”当成一段文本,而要把它当成一套可维护的数据结构。
三层记忆架构
Moltbot 的记忆可以拆成三层:
Layer 1: 知识图谱 /life/areas/
└── 按实体保存原子事实和动态摘要
Layer 2: 每日笔记 memory/YYYY-MM-DD.md
└── 按日期保存原始事件日志
Layer 3: 隐性知识 MEMORY.md
└── 保存偏好、工作方式和经验教训
这三层分别回答不同问题:
| 层级 | 回答的问题 | 适合保存什么 |
|---|---|---|
| 知识图谱 | “这个人、公司、项目现在是什么状态?” | 人物关系、公司状态、项目进展、重要里程碑 |
| 每日笔记 | “某天发生过什么?” | 原始事件、时间线、当天决策 |
| 隐性知识 | “用户通常怎么工作、怎么偏好沟通?” | 偏好、习惯、原则、经验 |
三层分开之后,Agent 不需要每次把所有历史都塞进上下文。它可以优先加载实体摘要,需要追溯时再读取原子事实或每日笔记。
第一层:用知识图谱组织长期事实
知识图谱层不是复杂的图数据库,而是一套可读的文件夹结构。每个重要实体都有自己的目录,比如人、公司、项目。
/life/areas/
├── people/
│ ├── sarah/
│ │ ├── summary.md
│ │ └── items.json
│ ├── maria/
│ │ ├── summary.md
│ │ └── items.json
│ └── emma/
│ ├── summary.md
│ └── items.json
├── companies/
│ ├── acme-corp/
│ │ ├── summary.md
│ │ └── items.json
│ └── newco/
│ ├── summary.md
│ └── items.json
└── projects/
└── personal-crm/
├── summary.md
└── items.json
这种结构有一个明显好处:实体边界清晰。
当 Agent 需要了解 Sarah,只需要看 /life/areas/people/sarah/;当 Agent 需要了解某家公司,只需要进入对应公司目录。信息不会混在一个巨大的 MEMORY.md 里。
原子事实:不要直接覆盖历史
每个实体目录下的 items.json 用来保存原子事实。所谓原子事实,就是一条尽量独立、可追踪、带时间戳的信息。
{
"id": "sarah-003",
"fact": "Sarah 是 Acme Corp 的直属经理,管理方式偏细,常参与具体执行细节",
"category": "relationship",
"timestamp": "2025-06-15",
"source": "conversation",
"status": "active"
}
当现实发生变化,不应该简单删除旧事实。更稳妥的做法是把旧事实标记为已替代,再写入新事实。
[
{
"id": "sarah-003",
"fact": "Sarah 是 Acme Corp 的直属经理,管理方式偏细,常参与具体执行细节",
"category": "relationship",
"timestamp": "2025-06-15",
"source": "conversation",
"status": "superseded",
"supersededBy": "sarah-007"
},
{
"id": "sarah-007",
"fact": "用户已经离开 Acme Corp,不再向 Sarah 汇报",
"category": "status",
"timestamp": "2026-01-15",
"source": "conversation",
"status": "active"
}
]
这里的关键不是“永远保存所有内容”,而是区分当前事实和历史事实。
active表示当前仍然有效;superseded表示曾经有效,但已经被新事实替代;supersededBy指向替代它的新事实。
这样做之后,Agent 既能知道“现在 Sarah 已经不是直属经理”,也能在需要时追溯“过去曾经共事过”。
动态摘要:让上下文保持精简
items.json 适合保存细粒度事实,但不适合每次对话都完整加载。一个实体长期积累后,可能有几十甚至几百条事实,直接塞进上下文会浪费 token,也会增加噪声。
所以每个实体还需要一个 summary.md,保存当前最有用的快照。
# Sarah
Sarah 曾是用户在 Acme Corp 的直属经理。用户已经在 2026-01 离开 Acme Corp,目前不再向 Sarah 汇报。
历史上,用户曾提到 Sarah 管理方式偏细,常参与执行细节。这条信息属于旧工作上下文,除非讨论 Acme Corp 的过往经历,否则不应作为当前工作关系使用。
摘要不是手写维护,而是由每周整理任务根据活跃事实重写。它的作用是给 Agent 提供“当前可用上下文”,而不是完整历史。
flowchart LR
A[items.json<br/>原子事实] --> B[筛选 active 事实]
B --> C[识别冲突和过期信息]
C --> D[重写 summary.md]
D --> E[对话时优先加载摘要]
第二层:每日笔记保存原始时间线
知识图谱保存长期事实,但不是所有信息都应该立刻进入知识图谱。每日笔记层负责记录当天发生了什么,文件名按日期组织。
memory/
├── 2026-01-27.md
├── 2026-01-28.md
└── 2026-01-29.md
一份每日笔记可以长这样:
# 2026-01-27
- 10:30:购物
- 14:00:医生复查
- 决策:日历事件开始使用 emoji 分类
- 对话:提到 Maria 的公司新招了两名开发者
每日笔记回答的是“什么时候发生了什么”。它更像原始日志,而不是结构化知识库。
后续的事实提取任务会从每日笔记或近期对话中识别长期有效的信息。例如:
| 原始记录 | 是否进入知识图谱 | 原因 |
|---|---|---|
| 10:30 购物 | 否 | 临时事件,长期价值低 |
| 医生复查 | 视情况而定 | 如果和长期健康状态有关,可以提取 |
| 日历事件开始使用 emoji 分类 | 是 | 属于使用偏好或系统约定 |
| Maria 的公司新招了两名开发者 | 是 | 属于公司或项目状态变化 |
每日笔记保留了原始上下文,知识图谱则提炼出长期事实。两者分工明确,可以避免把所有琐事都升级成“记忆”。
第三层:隐性知识保存偏好和经验
MEMORY.md 不适合继续承担所有长期记忆,但它仍然很重要。它应该保存用户的工作方式、偏好、原则和经验教训。
## 工作方式
- 倾向于冲刺式工作:短时间高强度推进,然后安排恢复时间
- 更喜欢简短、明确、可执行的建议
- 联系偏好:电话 > 短信 > 邮件
## 沟通偏好
- 重要事项需要明确下一步动作
- 不喜欢只有抽象建议,没有具体执行方案
## 经验教训
- 不要为一次性提醒创建 cron 任务
- 临时任务应优先写入待办,而不是长期自动化
这类信息不是关于某个外部实体,而是关于“用户如何运作”。它适合被频繁加载,因为它会影响 Agent 的表达方式、任务规划方式和提醒策略。
三层结构可以这样理解:
flowchart TB
A[MEMORY.md<br/>用户偏好和工作方式] --> D[Agent 行为风格]
B[summary.md<br/>实体当前状态] --> E[当前上下文判断]
C[items.json / daily notes<br/>历史事实和时间线] --> F[需要追溯时读取]
D --> G[更贴合用户的回复]
E --> G
F --> G
动态记忆的运行机制
三层文件结构只是基础。真正让记忆“活起来”的,是两个自动化流程:
- 周期性事实提取;
- 每周综合整理。
周期性事实提取
事实提取可以由轻量模型或子代理完成。它不需要每次调用最强模型,因为任务比较明确:扫描近期对话,找出长期有效的信息,然后写入对应实体的 items.json。
可以提取的信息包括:
- 新关系:开始向 James 汇报;
- 状态变化:已经离开 Acme Corp;
- 里程碑:Emma 迈出了第一步;
- 项目变化:Maria 的公司新招了两名开发者;
- 长期偏好:日历事件开始使用 emoji 分类。
不应该提取的信息包括:
- 闲聊;
- 一次性提醒;
- 没有长期价值的临时安排;
- 不确定、缺少上下文的猜测。
一个简化流程如下:
sequenceDiagram
participant U as 用户
participant A as Agent
participant H as Heartbeat
participant S as 子代理
participant K as 知识图谱
U->>A: 日常对话
A->>A: 保存近期对话或每日笔记
H->>S: 周期性触发事实提取
S->>S: 判断哪些信息具有长期价值
S->>K: 写入对应实体 items.json
K-->>A: 下次对话可读取更新后的上下文
每周综合整理
周期性提取会让 items.json 持续增长。如果只追加、不整理,记忆还是会逐渐变乱。因此需要每周做一次综合整理。
整理任务主要做四件事:
- 加载某个实体的新增事实;
- 判断哪些事实仍然有效;
- 将冲突或过期事实标记为
superseded; - 重写实体的
summary.md。
flowchart TD
A[周日 cron 触发] --> B[扫描有新增事实的实体]
B --> C[加载 summary.md]
C --> D[加载 items.json 中的 active 事实]
D --> E[识别状态变化和矛盾事实]
E --> F[旧事实标记为 superseded]
F --> G[重写当前摘要 summary.md]
这样的记忆系统会产生类似飞轮的效果:
flowchart LR
A[更多对话] --> B[提取更多事实]
B --> C[知识图谱增长]
C --> D[摘要更准确]
D --> E[下次回复上下文更好]
E --> A
时间越久,Agent 对用户的理解就越结构化。区别在于,这种理解不是黑盒向量空间里的不可见表示,而是一组人类可读、可搜索、可审计的文件。
和常见记忆方案的对比
| 方案 | 优点 | 问题 | 适合场景 |
|---|---|---|---|
| 向量数据库 / RAG | 适合语义检索,能处理大量文本 | 不容易直接检查 Agent “知道”什么,检索结果也可能遗漏关键事实 | 文档问答、知识库搜索 |
| 单体上下文文件 | 简单,容易上手 | 文件会越来越大,过期信息难处理,每次加载成本高 | 小规模个人偏好 |
| 基础 Clawdbot 记忆 | 有规则、有偏好、有心跳、有定时任务 | 记忆偏静态,需要人工维护 | 轻量 Agent 自动化 |
| 三层动态记忆 | 可读、可搜索、能保留历史、能更新摘要 | 需要设计目录、schema 和定时整理流程 | 长期陪伴型 Agent、个人助理、项目助理 |
| Supermemory 集成 | 自动回忆能力更强,并提供搜索、遗忘等工具 | 依赖外部记忆服务和集成质量 | 希望减少自建记忆系统复杂度的 Agent |
三层文件系统的价值在于可控。你可以打开任意一个实体目录,直接检查事实从哪里来、当前摘要怎么写、哪些旧事实已经失效。
实施步骤
1. 创建目录结构
可以先从人物和公司两个实体类型开始,后续再扩展项目、地点、家庭、健康等领域。
mkdir -p ~/life/areas/people
mkdir -p ~/life/areas/companies
mkdir -p ~/life/areas/projects
mkdir -p ~/clawd/memory
推荐保持目录名稳定、可读,并使用小写英文和连字符:
people/sarah/
companies/acme-corp/
projects/personal-crm/
2. 定义原子事实 schema
items.json 需要统一字段,否则后续整理会很困难。一个可用的 schema 如下:
{
"id": "entity-001",
"fact": "实际事实",
"category": "relationship|milestone|status|preference",
"timestamp": "YYYY-MM-DD",
"source": "conversation|daily-note|manual",
"status": "active|superseded",
"supersededBy": "entity-002"
}
字段含义:
| 字段 | 含义 |
|---|---|
id | 实体内唯一事实 ID |
fact | 用自然语言描述的事实 |
category | 事实类型,例如关系、里程碑、状态、偏好 |
timestamp | 事实记录时间 |
source | 信息来源 |
status | 当前是否有效 |
supersededBy | 如果被替代,指向新事实 ID |
3. 在 AGENTS.md 中加入记忆规则
AGENTS.md 要告诉 Agent 如何使用三层记忆,而不是让它自由发挥。
## 记忆:三层结构
### Layer 1: 知识图谱 `/life/areas/`
实体按类型存放:
- `people/`:人物
- `companies/`:公司
- `projects/`:项目
每个实体目录包含:
1. `summary.md`:当前摘要,优先用于快速上下文
2. `items.json`:原子事实,用于追溯和整理
### 写入规则
- 具有长期价值的事实写入对应实体的 `items.json`
- 不确定的信息不要写成事实,可以先保留在每日笔记
- 不删除旧事实;现实变化时,把旧事实标记为 `superseded`
- 新事实必须包含时间戳和来源
### 读取规则
- 对话时优先读取相关实体的 `summary.md`
- 需要历史细节时,再读取 `items.json`
- 不要把过期事实当作当前事实使用
4. 在 Heartbeat 中加入事实提取任务
Heartbeat 的职责是周期性检查新对话,并调用轻量子代理做事实提取。
## 事实提取
每次心跳执行:
1. 检查上次提取之后的新对话或每日笔记
2. 调用轻量子代理识别持久事实
3. 判断事实属于人物、公司还是项目
4. 写入对应实体的 `items.json`
5. 记录 `lastExtractedTimestamp`
重点提取:
- 关系变化
- 状态变化
- 项目里程碑
- 长期偏好
- 重要决策
跳过:
- 闲聊
- 一次性提醒
- 临时安排
- 没有足够证据的推测
5. 加入每周综合整理任务
每周整理可以用 cron 触发。核心不是 cron 命令本身,而是让 Agent 按固定规则重写摘要。
## 每周记忆审阅
对每个有新增事实的实体执行:
1. 加载 `summary.md`
2. 加载 `items.json`
3. 找出所有 `active` 事实
4. 判断是否存在冲突、过期或被替代的信息
5. 将旧事实标记为 `superseded`
6. 基于当前有效事实重写 `summary.md`
7. 保留历史事实,不直接删除
如果需要通过系统 cron 触发,可以使用类似结构:
# 每周日 03:00 触发记忆整理脚本
0 3 * * 0 /path/to/weekly-memory-review.sh
整理脚本内部可以再调用 Agent,让它根据规则完成摘要重写。
Supermemory 集成:减少工具调用遗漏
三层文件系统解决了“如何组织记忆”的问题,但还有一个常见问题:很多 Agent 依赖工具读取记忆,而模型并不总会主动调用工具。
如果某条记忆必须通过工具搜索才能拿到,Agent 可能在没有检索的情况下直接回答。这样一来,记忆虽然存在,却没有稳定进入推理过程。
Supermemory 的思路是把记忆能力做成更主动的上下文层,并提供额外操作能力:
- 自动回忆相关记忆;
- 手动搜索记忆;
- 手动遗忘某些内容;
- 获取资料;
- 使用
/remember保存信息; - 使用
/recall召回信息。
安装入口:
https://supermemory.ai/docs/integrations/clawdbot
更合理的做法不是把 Supermemory 和三层文件系统视为二选一,而是分工使用:
| 能力 | 三层文件系统 | Supermemory |
|---|---|---|
| 人类可读 | 强 | 取决于服务实现 |
| 可审计 | 强 | 取决于导出和管理能力 |
| 自动召回 | 需要自己实现 | 强 |
| 手动维护 | 可直接编辑文件 | 通过工具或服务接口 |
| 长期结构化建模 | 强 | 更偏通用记忆能力 |
如果需要完全掌控数据结构,三层文件系统更合适;如果希望降低记忆召回的实现成本,Supermemory 可以作为外部记忆层补足。
使用时容易踩的坑
不要把所有信息都升级成长期事实
动态记忆不是“什么都记”。临时购物、一次性会议、随口闲聊如果都写进知识图谱,记忆会很快变脏。
判断一条信息是否值得长期保存,可以看三个标准:
| 标准 | 问题 |
|---|---|
| 是否会影响未来决策 | 以后回答问题、安排任务时会不会用到它 |
| 是否描述稳定状态 | 它是不是一个偏好、关系、身份、项目状态 |
| 是否能归属到实体 | 它能不能放进某个人、公司、项目或用户偏好下 |
不要让摘要变成流水账
summary.md 应该是当前状态快照,不是事实列表的复制品。好的摘要会主动压缩信息,并标注旧上下文的适用范围。
不推荐:
Sarah 在 2025-06-15 被提到是经理。
Sarah 在 2025-07-02 被提到管理很细。
Sarah 在 2026-01-15 不再是经理。
更推荐:
Sarah 曾是用户在 Acme Corp 的直属经理。用户已经离开 Acme Corp,目前不再向 Sarah 汇报。过去关于 Sarah 管理方式的描述只适用于旧工作经历,不应作为当前工作关系使用。
不要删除历史事实
直接删除会让系统失去时间维度。替代标记更安全,因为它保留了事实演变过程。
{
"status": "superseded",
"supersededBy": "new-fact-id"
}
不要把工具检索当成唯一记忆入口
如果某些关键偏好必须每次生效,就应该放在稳定上下文里,例如 MEMORY.md 或实体摘要。工具适合补充检索,不适合承载所有关键记忆。
小结
Moltbot 的动态记忆架构可以概括成一句话:用每日笔记保存原始时间线,用知识图谱保存结构化长期事实,用 MEMORY.md 保存用户偏好和隐性知识,再通过周期性提取与每周整理让记忆持续更新。
这套设计的重点不在于复杂,而在于可维护:
- 文件是人类可读的;
- 事实是带时间戳的;
- 旧信息不会被误当作当前事实;
- 摘要能保持精简;
- Agent 每次对话都能拿到更接近现实的上下文。
当 Agent 需要长期陪伴用户、理解项目、维护关系和偏好时,静态记忆文件很快会到达上限。三层动态记忆加上 Supermemory 这类自动召回能力,可以把“记住信息”升级为“持续维护一个会变化的世界模型”。