生成模型:Claude Opus 4.6 (anthropic/claude-opus-4-6) Token 消耗:输入 ~300k tokens,输出 ~7k tokens(本节)
LLM 本身没有持久记忆——每次对话都是从零开始。用户昨天告诉 Agent 的偏好、上周讨论的项目决策、上个月记录的待办事项,在新对话中全部消失。OpenClaw 的记忆系统解决了这个问题:让 Agent 可以跨会话记住和检索重要信息。
本节分析记忆系统的设计哲学、文件布局和核心管理器。
20.1.1 "纯 Markdown 即记忆"的设计哲学
许多 AI Agent 框架将记忆存储在向量数据库(如 Pinecone、Weaviate)或关系型数据库中。OpenClaw 选择了一条不同的路径:记忆的"源"是纯 Markdown 文件。
~/.openclaw/
├── MEMORY.md ← 长期记忆(手动维护或 Agent 写入)
├── memory/
│ ├── 2026-01-15.md ← 日志式记忆(按日期自动生成)
│ ├── 2026-01-16.md
│ └── project-notes.md ← 自定义记忆文件
这个设计有几个深层考量:
换句话说,OpenClaw 把 Markdown 文件当作真值源(Source of Truth),向量索引只是为了加速搜索而构建的派生索引。索引丢失可以重建,但 Markdown 文件包含了所有原始信息。
isMemoryPath 函数定义了哪些文件属于"记忆":
规则很简单:根目录下的 MEMORY.md(或 memory.md),以及 memory/ 目录下的所有 .md 文件。
MEMORY.md 是用户的长期记忆文件,通常包含持久的偏好、规则和知识。它可以被用户手动编辑,也可以被 Agent 在对话中写入。典型内容:
日志记忆:memory/YYYY-MM-DD.md
memory/ 目录下的日期命名文件是会话记忆的快照。当用户使用 /new 命令开始新会话时,session-memory 钩子会自动将当前会话的关键对话内容保存到这里:
除了标准路径,用户可以通过配置添加额外的记忆目录:
这允许用户将团队共享的知识库、项目文档等纳入记忆搜索范围。
listMemoryFiles 函数扫描所有记忆文件:
注意安全措施:walkDir 会跳过符号链接(entry.isSymbolicLink()),防止通过符号链接引入不可控的文件。
20.1.3 记忆管理器(src/memory/manager.ts)
MemoryIndexManager
MemoryIndexManager 是记忆系统的核心引擎。它负责:文件索引、向量嵌入、BM25 全文搜索、混合排序、缓存管理。
MemoryIndexManager 通过静态方法 get 获取实例,使用全局缓存避免重复创建:
衍生解释:单例模式与缓存键
单例模式(Singleton Pattern)确保一个类只有一个实例。这里使用 Map 作为缓存,Key 由 agentId + 配置序列化组成。这意味着同一个 Agent 使用相同配置时共享同一个管理器实例,但不同 Agent 或不同配置会创建独立实例。这比传统的单例更灵活——它是参数化单例。
记忆搜索的配置由 resolveMemorySearchConfig 统一解析,支持全局默认值和每个 Agent 的覆盖:
默认值经过精心调校:
每个分块约 400 token(~1600 字符)
Markdown 文件被分割成固定大小的分块(Chunk),每个分块独立嵌入向量:
衍生解释:分块与重叠(Chunking & Overlap)
为什么要分块?因为嵌入模型有输入长度限制(如 8192 token),而且更短的文本通常能产生更精确的语义向量。分块的挑战在于语义断裂——一段连贯的论述可能被截断在两个分块的边界。重叠(Overlap) 通过让相邻分块共享一部分文本来缓解这个问题。例如 80 token 的重叠意味着分块 A 的最后 80 个 token 也会出现在分块 B 的开头。
管理器使用 chokidar 监视记忆文件的变更,并设置 dirty 标记:
当 Agent 调用 memory_search 时,如果 dirty 为 true,会先触发增量同步再执行搜索——实现懒索引(Lazy Indexing)。
"Markdown 即记忆" 是核心设计哲学——纯文本文件作为真值源,向量索引只是派生数据。
记忆有两层结构——MEMORY.md 存储长期知识,memory/YYYY-MM-DD.md 存储会话快照。
MemoryIndexManager 是核心引擎——通过参数化单例缓存、文件监视、懒索引等机制管理整个记忆生命周期。
分块算法以行为单位——按字符数估算 token 数,支持重叠以避免语义断裂。
文件监视实现实时感知——chokidar 监听文件变更,设置脏标记,搜索时按需重建索引。
配置支持多层覆盖——全局默认值 → Agent 级别覆盖,包括嵌入提供者、分块策略、搜索参数等。