OpenClaw 记忆系统架构深度解析:从 Markdown 到混合检索

12333社保查询网www.sz12333.net.cn 2026-02-15来源:人力资源和社会保障局

  OpenClaw 是目前最受关注的开源 AI Agent 框架, 没有之一。 我在前一篇文章深入研究OpenClaw - 系统提示词解析和大家一起学习了OpenClaw的提示词系统,今天我们来看看他是怎么管理记忆的。

  OpenClaw以纯 Markdown 文件为”唯一真实来源”的持久化记忆系统。 在 GitHub 斩获超过 14.5 万颗星之后,这个项目(曾先后更名 Clawdbot → Moltbot → OpenClaw)向业界证明:AI Agent 的记忆不一定要藏在不透明的向量数据库里,Markdown 文件 + SQLite 索引 + BM25/向量混合搜索的组合就能构建出生产级别的记忆架构。本文将从底层源码出发,逐层拆解这套系统的存储模型、检索机制、上下文注入、压缩策略与安全考量,并与 Claude Code、ChatGPT、AutoGPT、LangChain 及 MemGPT 进行一些横向的对比。

为什么 AI Agent 需要记忆?LLM 无状态的根本困境

  大语言模型本质上是无状态的函数:给定输入,产出输出,然后遗忘一切。每次对话都从零开始,无法累积对用户偏好、项目上下文或历史决策的认知。这种无状态性在单轮问答场景中可以接受,但对于需要跨会话连续工作的 AI Agent 来说则是致命缺陷。

  会话记忆(Session Memory)与长期记忆(Long-term Memory)解决的是两个不同维度的问题。会话记忆维持单次交互的上下文连贯性——当你在一次对话中提到”那个文件”时,Agent 能回溯上文找到具体路径。长期记忆则跨越会话边界,让 Agent 在数周甚至数月后仍然记得你的技术栈偏好、项目架构决策和工作习惯。

  真实场景的需求验证了这一点:一个运行数周的个人助理需要记住你偏好 Bash 命令而非长篇理论解释;一个管理日程的 Agent 需要知道你每周三下午有例会;一个代码助手需要记住项目使用 TypeScript + Bun 而非 Python + pip。没有持久记忆,Agent 就只是一个每次启动都需要重新”认识”你的陌生人。

  OpenClaw 正是为此而生。它的核心哲学可以用四个字概括——“Text > Brain”——文件是唯一的记忆来源,Agent 只保留被写入磁盘的信息。

OpenClaw 如何存储记忆:文件即真相三层文件结构

  OpenClaw 的记忆存储在 Agent 工作区目录下(默认 ~/.openclaw/workspace/),采用清晰的三层结构:

  ~/.openclaw/workspace/├── MEMORY.md # 长期策划记忆:偏好、决策、持久事实├── memory/│ ├── 2026-02-13.md # 今日追加日志│ ├── 2026-02-12.md # 昨日日志│ └── ... # 历史日志├── sessions/│ └── 2026-01-30-memory-system-research.md # 会话转录(LLM 生成描述性文件名)├── USER.md # 用户身份与偏好├── SOUL.md # Agent 人格设定└── AGENTS.md # 核心指令

  MEMORY.md 是长期记忆的核心载体,存放经过策划的持久事实——技术栈选择、架构决策、长期目标。关键设计:它仅在私聊会话中加载,永远不会在群组上下文中注入,从架构层面保护隐私。文件默认不存在,用户需手动创建。Bootstrap 加载时字符上限为 20,000 字符(由 bootstrapMaxChars 配置),超出时采用 70/20/10 截断策略:取头部 70%、尾部 20%、预留 10% 给截断标记。

  memory/YYYY-MM-DD.md 是每日追加日志,捕获当天的活动、笔记和上下文。它们是 append-only 的——每天自动创建新文件,旧内容不修改。会话启动时,系统加载今日和昨日的日志文件。系统提示词明确指导 Agent:“如果有人说’记住这个’,写到文件里(不要只存在内存中)。”

  sessions/ 目录存放会话转录,使用 LLM 生成的描述性 slug 命名(如 2026-01-30-memory-system-research.md)。这是可选功能,需通过 experimental.sessionMemory: true 启用。

SQLite 索引:搜索加速层而非真相来源

  Markdown 文件是真相,SQLite 数据库是索引。每个 Agent 拥有独立的 SQLite 文件,位于 ~/.openclaw/memory/{agentId}.sqlite。数据库包含四张核心表和两张虚拟表(源码引用:memory-schema.ts:9-75):

  核心表:files 跟踪文件的修改时间、大小和内容哈希,用于增量索引(跳过未变更文件);chunks 存储文本块、行号范围、SHA-256 哈希和 JSON 序列化的嵌入向量;embedding_cache 实现跨文件的嵌入去重——相同文本只嵌入一次;meta 存储索引元数据(嵌入提供者、模型、分块参数的指纹)。

  虚拟表:chunks_fts 使用 SQLite 的 FTS5 扩展构建全文搜索索引,支撑 BM25 关键词检索;vec_chunks 使用 sqlite-vec 扩展存储浮点向量,支撑余弦相似度搜索。如果 sqlite-vec 不可用,系统回退到 JavaScript 暴力计算余弦相似度。

嵌入服务:自动选择与优雅降级

  OpenClaw 支持多种嵌入(embedding)提供者,按优先级自动选择(源码引用:embeddings.ts:135-167):

  提供者

  默认模型

  维度

  特点

  本地 (node-llama-cpp)

  embeddinggemma-300M-Q8_0.gguf (~600MB)

  可变

  零成本、离线运行,M1 Mac 约 50 tokens/秒

  OpenAI

  text-embedding-3-small

  1536

  支持 Batch API(降低 50% 成本),约 1000 tokens/秒

  Gemini

  gemini-embedding-001

  768

  异步批处理,有免费额度

  Voyage

  可配置

  可变

  需 VOYAGE_API_KEY

  如果所有提供者都失败,系统优雅降级到纯 BM25 关键词搜索,不会崩溃。嵌入缓存使用 SHA-256 哈希去重,默认上限 50,000 条。

分块策略:400 token 滑动窗口

  内容在嵌入前需要分块。OpenClaw 采用带重叠的滑动窗口算法(源码引用:internal.ts:144-215):目标块大小 ~400 tokens(约 1,600 字符,按 4 字符 ≈ 1 token 估算),重叠 80 tokens(约 320 字符)。算法保留行边界,每个块记录起始行号和结束行号,以便后续精确定位。重叠区确保跨块边界的信息不会丢失——上一个块的尾部内容会被携带到下一个块的头部。

记忆如何注入对话上下文:混合检索引擎memory_search:BM25 + 向量的加权融合

  memory_search 是 OpenClaw 记忆检索的核心工具(源码引用:memory-tool.ts:22-69),采用混合检索架构,将两种互补的检索方法通过加权得分融合:

  向量搜索(默认权重 70%)使用余弦相似度匹配语义。查询语句被嵌入为向量后,通过 sqlite-vec 的 vec_distance_cosine() 函数在数据库内计算距离。它擅长处理同义表达——”Mac Studio 网关主机”和”运行网关的那台机器”能匹配上。

  BM25 关键词搜索(默认权重 30%)使用 FTS5 全文索引匹配精确词元。它擅长处理 ID、环境变量名、代码符号等精确匹配场景。BM25 的排名值(越小越好)通过归一化公式转换为 [0, 1] 区间的分数:

  bm25Score = 1 / (1 + max(0, rank))

  融合算法(源码引用:hybrid.ts:39-111)的关键设计是使用并集而非交集——只要在任一检索方法中得分高的块都会被保留。最终得分公式:

  finalScore = 0.7 × vectorScore + 0.3 × textScore

  系统从两侧各取 maxResults × candidateMultiplier(默认 4 倍)个候选,融合后返回得分最高的结果。每个结果包含不超过 700 字符的摘要片段、文件路径、行号范围和相关度分数。

  OpenClaw 选择加权融合而非 RRF(Reciprocal Rank Fusion)是有意为之:RRF 会将分数拉平为序数排名,丢失余弦相似度的绝对值信息。一个 0.98 的语义匹配理应碾压 0.71 的弱匹配,而不是被简单排名稀释。

memory_get:精确读取指定文件

  当 memory_search 定位到相关文件和行号后,Agent 可以调用 memory_get 工具读取特定文件的特定行范围,获取完整上下文。路径被限制在 MEMORY.md 和 memory/ 目录内(除非通过 extraPaths 显式扩展),防止路径穿越。

上下文注入的层次

  会话启动时,系统自动注入:MEMORY.md(仅私聊)、今日和昨日的 daily log、AGENTS.md / SOUL.md / USER.md 等工作区文件,总量受 bootstrapMaxChars(20,000 字符) 限制。memory_search 的检索结果是按需注入的——仅当 Agent 主动调用搜索工具时才会加入上下文,不会自动填充。这种设计在 token 预算管理上更加精细。

记忆的修改、删除与压缩:对抗遗忘的机制Agent 如何写入记忆

  Agent 通过标准文件操作工具写入记忆文件。系统提示词给出明确指导:持久决策和偏好写入 MEMORY.md,日常笔记和运行上下文写入 memory/YYYY-MM-DD.md。当 Agent 写入文件后,文件监控器(FSWatcher)会在 1.5 秒防抖窗口后标记索引为 dirty,触发后台异步重索引。 ”智能同步”确保刚写入的记忆在下一次搜索时立即可用。

  这个过程完全是有Agent主导的,也就是说Agent会主动调用memory工具来进行记忆的写入操作。

预压缩记忆冲刷:OpenClaw 最具创新性的机制

  长对话不可避免地逼近上下文窗口上限。当这发生时,系统必须”压缩”(compaction)——将较旧的消息总结或截断。问题在于:压缩会丢失细节。 GitHub Issue #5429 记录了一个用户因静默压缩丢失 ~45 小时工作上下文的案例——Agent 报告完全不记得之前讨论的内容。

  OpenClaw 的解决方案是预压缩记忆冲刷(Pre-compaction Memory Flush)。当会话 token 数逼近阈值时,系统触发一次静默的 agentic turn,提示模型将”持久记忆”写入磁盘。触发阈值计算公式:

  flushTrigger = contextWindow - reserveTokensFloor - softThresholdTokens

  以 200K 上下文窗口为例:200,000 - 20,000 - 4,000 = 176,000 tokens 时触发。此时系统注入两条提示——系统提示”Session nearing compaction. Store durable memories now.“和用户提示”Write any lasting notes to memory/YYYY-MM-DD.md; reply with NO_REPLY if nothing to store.” Agent 通常回复 NO_REPLY,用户完全无感。每个压缩周期仅触发一次冲刷(通过 memoryFlushCompactionCount 追踪),只读工作区模式下自动跳过。

会话裁剪与压缩的区别

  Session Pruning(会话裁剪)是轻量级操作——仅裁剪旧的工具执行结果,在内存中按请求处理,不修改持久化的 JSONL 转录。它尊重提供者缓存(如 Anthropic 的 prompt caching),优先裁剪无缓存的内容。

  Compaction(压缩)是重量级操作——将上下文窗口中超出 keepRecentTokens(默认 20,000 tokens)的旧消息替换为 LLM 生成的摘要。采用分阶段摘要策略:对被丢弃的消息、主历史和分割的 turn 前缀分别摘要。摘要保留大意但丢失具体细节——文件路径、精确命令、配置值、决策推理过程等。

完整记忆工作流:从用户输入到记忆检索

  一条用户消息在 OpenClaw 中的完整旅程如下:

  1. 消息路由:用户通过任意渠道(WhatsApp、Telegram、Slack、iMessage、CLI)发送消息,Gateway WebSocket 服务器接收并路由到 Agent Runtime。
  2. 上下文组装:Runtime 的 System Prompt Builder 动态合并系统指令、可用工具、技能和记忆内容。Session History Loader 从 JSONL 转录中加载历史交互。MEMORY.md(仅私聊)、今日/昨日 daily log 和工作区文件被注入,总量受 20,000 字符上限。
  3. 记忆检索:Agent 根据用户查询决定是否调用 memory_search。混合检索引擎从 BM25 和向量搜索两侧各取 maxResults × 4 个候选,加权融合后返回最多 6 个结果(默认),每个结果摘要不超过 700 字符。
  4. 精确读取:如需更多上下文,Agent 调用 memory_get 读取指定文件的指定行范围。
  5. LLM 推理:完整上下文发送给模型(Claude、GPT 等),Context Window Guard 监控 token 数。
  6. 工具执行与记忆写入:Agent 可能执行 shell 命令、浏览器操作、文件读写等。如果对话中产生了值得记住的信息,Agent 将其写入 MEMORY.md 或当日 daily log。
  7. 索引更新:文件变更触发 FSWatcher → 1.5 秒防抖 → 后台异步重索引。MemoryIndexManager(源码:manager.ts:119-232)通过文件哈希比对实现增量更新。
  8. 预压缩检查:如果 token 数逼近 contextWindow - reserveTokensFloor - softThresholdTokens,触发静默记忆冲刷 turn。
  9. 压缩(如需要):旧消息被摘要,保留最近 20,000 tokens 的原始对话。
索引与重索引

  索引存储了嵌入提供者、模型、端点指纹和分块参数。如果任何一项发生变化(例如从本地嵌入切换到 OpenAI),OpenClaw 会自动重置并完整重索引。会话转录使用增量索引,阈值为 100KB 新数据或 50 条新消息(deltaBytes: 100000, deltaMessages: 50)。

优势与不足:工程权衡的真实面貌核心优势

  OpenClaw 的记忆系统有五个突出优势。首先是极致透明:所有记忆都是纯文本 Markdown,用任何编辑器打开即可查看、修改、删除。Agent 记错了?直接编辑文件。这种透明度在 AI Agent 领域几乎独一无二。其次是版本可控:记忆文件可以放入 Git 仓库,git diff 即可追踪 Agent”认知”的变化。第三是零厂商锁定:没有专有数据库格式,迁移只需复制文件。第四是隐私优先:所有数据留在本地,MEMORY.md 的私聊限定从架构层面保护敏感信息。第五是优雅降级:嵌入失败走 BM25,BM25 失败走向量搜索,都失败了还有原始 Markdown 文件。

关键不足

  可扩展性受限是最突出的问题。每日一个日志文件,一年 365 个;加上会话转录,文件量持续增长。没有内置的保留策略或自动归档机制,需要人工维护。GitHub Issue #5771记录了仅记忆搜索注入就在新会话上触发上下文溢出的案例。

  上下文压缩导致记忆丢失是最被诟病的设计。压缩保留大意但丢失细节——文件路径、精确命令、配置值、决策推理。Issue #5429 中用户丢失 45 小时工作上下文的案例引发了广泛讨论。虽然预压缩冲刷机制在一定程度上缓解了这个问题,但它依赖 Agent “自觉”写入记忆,无法保证完整性。

  安全性是另一个值得关注的领域。记忆文件以明文存储在 ~/.openclaw/ 这一可预测路径下。Cisco 的分析发现 26% 的 Agent 技能存在至少一个安全漏洞。1Password 的研究警告:”一个被盗的 API token 已经够糟了——但一百个被盗的 token 和会话,加上一份描述你是谁、在做什么、与谁合作的长期记忆文件,那完全是另一回事。” 安全研究者识别出的”致命三角”——访问私有数据 + 暴露于不可信内容 + 具备外部通信能力同时保留记忆——使得记忆系统成为攻击面的关键组成部分。

  此外,跨项目噪声(不相关项目的记忆污染搜索结果)、无语义关系追踪(块与块之间没有关联)和单机限制(默认不支持跨设备同步)也是开发者常见的痛点。社区通过 Mem0(外部记忆存储)、Cognee(知识图谱增强)和 Graphiti(时序知识图谱)等插件尝试弥补这些不足。

横向对比:六种 Agent 记忆架构的设计

  将 OpenClaw 置于更广阔的 AI Agent 记忆生态中审视,能更清楚地看到其设计取舍的独特性。

  Claude Code 最接近的对标。它同样使用 Markdown 文件(CLAUDE.md,支持项目级、用户级和企业级层次),同样强调人类可读和版本可控。但 Claude Code 没有内置语义检索——所有记忆在会话启动时整体加载到上下文窗口,没有 BM25 或向量搜索。它本质上是无状态的:没有跨会话对话历史回忆。Auto Memory 功能正在推出,但仍限于 MEMORY.md 的前 200 行。

  ChatGPT 记忆走向了完全对立的方向。它的记忆是云端、不透明的:一个时间戳标注的事实列表(如”用户名字是 X,偏好 Y”)加上最近约 15 条对话摘要,全部自动注入每次提示。用户能看到存储了什么事实,但看不到完整的上下文组装过程。不支持版本控制、不可导出、不可移植——但对普通用户来说体验最流畅。

  AutoGPT 的记忆系统经历了一个耐人寻味的演变:最初使用 Pinecone/Weaviate/ChromaDB 等向量数据库,后来经过”vector memory revamp”移除了所有向量数据库实现,回归到 JSON 文件存储。Jina.AI 创始人韩潇指出,向量数据库对 Agent 场景是”大炮打蚊子”——Agent 产生记忆的速度(每次约 10 秒)慢到用 NumPy 暴力搜索 10 万条嵌入也只需毫秒。这与 OpenClaw 选择 SQLite 而非独立向量数据库的逻辑不谋而合。

  LangChain 提供了灵活记忆抽象——ConversationBufferMemory(全量缓存)、ConversationSummaryMemory(LLM 摘要)、VectorStoreRetrieverMemory(向量检索)等多种模块。但它是开发者工具包而非终端产品,没有对存储格式的”观点”,不使用 Markdown 作为原生格式,且原始记忆类已在 v0.3.1 后弃用。

  MemGPT/Letta 是精密系统,受操作系统虚拟内存启发,构建了三层架构:Core Memory(始终在上下文窗口内的可写块)、Recall Memory(全量对话历史的可搜索数据库)和 Archival Memory(Agent 自主管理的语义可搜索长期存储)。LLM 自身通过函数调用管理记忆——memory_replace、archival_memory_insert、conversation_search 等。当上下文满时触发”内存压力”,Agent 自主决定保留什么。这是最接近”AI 操作系统”的记忆管理方式,但以牺牲人类可读性和部署简单性为代价:需要 Docker + PostgreSQL + 向量数据库的完整基础设施。

  维度

  OpenClaw

  Claude Code

  ChatGPT

  AutoGPT

  LangChain

  MemGPT/Letta

  存储格式

  Markdown 文件

  Markdown 文件

  云端不透明

  JSON/向量 DB

  可配置

  结构化块 + 向量 DB

  检索方式

  BM25+向量混合

  全量加载

  直接注入

  相似度搜索

  按类型不同

  LLM 函数调用

  跨会话持久

   文件持久

   文件持久

   云端持久

  部分

  默认仅会话

   服务端持久

  人类可读

   极高

   极高

   不透明

   嵌入

   编程接口

  部分可读

  自主管理

  部分(冲刷机制)

   手动

   自动

   核心创新

  部署复杂度

  低(SQLite)

  低(文件)

  零(云端)

  中

  高(需集成)

  高(Docker 栈)

结论

  OpenClaw 的记忆架构在 AI Agent 领域提出了一个鲜明的技术立场:记忆系统不必复杂才能有效。SQLite + FTS5 + sqlite-vec 的组合在单用户场景下完全够用,避免了分布式系统的运维成本。400 token 滑动窗口分块 + 7030 加权融合的混合检索在语义理解和精确匹配之间取得了合理平衡。预压缩记忆冲刷机制虽不完美,但巧妙地利用了 LLM 自身的判断能力来对抗信息丢失。

  更深层的洞察是:OpenClaw 代表了 AI Agent 记忆设计的一种”UNIX 哲学”——文本文件、可组合、可检查、可版本控制。当行业普遍追求更复杂的向量数据库和知识图谱方案时,OpenClaw 证明了透明性和可控性本身就是一种竞争优势。对于大多数个人 AI Agent 使用场景,”能 cat 出来的记忆”比”需要 API 查询的记忆”更实用。

  然而,随着 Agent 使用场景向多租户、多设备和企业级演进,Markdown-first 架构的扩展边界将会显现。社区生态已经通过 Mem0、Cognee、Graphiti 等插件开始向这些方向探索。对开发者而言,OpenClaw 的记忆系统不仅是一个可直接使用的生产方案,更是一份关于”如何在简单性与功能性之间取舍”的实践教材。

本文标题:OpenClaw 记忆系统架构深度解析:从 Markdown 到混合检索本文网址:https://www.sz12333.net.cn/zhzx/kexue/74654.html 编辑:12333社保查询网

本站是社保查询公益性网站链接,数据来自各地人力资源和社会保障局,具体内容以官网为准。
定期更新查询链接数据 苏ICP备17010502号-11