整理一篇学习笔记,把看到的一些要点和自己的理解都记下来。
OpenClaw 源码剖析(五):Memory 与安全——AI 的记忆机制与防线
写在前面:这是 OpenClaw 源码剖析系列的最终篇。前四篇我们拆完了架构全景、Gateway 调度器、Agent Loop 引擎和 Channel/Skills 适配层。今天,我们进入两个最"深沉"的子系统——Memory 和 安全。Memory 解决的麻烦是:AI 助手如何跨会话记住你的偏好、项目信息和对话历史?如何在上下文窗口有限的情况下,既不遗忘重要信息,又不被无关记忆淹没? 安全解决的麻烦是:当 AI 助手拥有执行 Shell 命令、读写文件、访问网络的能力时,如何防止它被恶意指令操控,做出危险操作? 这两个系统看似独立,实则紧密耦合——Memory Flush 在压缩前保存重要信息,PRISM 在执行前拦截危险操作,两者共同守护着 AI Agent 的"记忆完整性"和"行为安全性"。
📑 文章目录
- 📌 一、Memory 系统:AI 的"记忆大脑"是怎么开发的
- 🧠 二、三层记忆架构:Session → Daily → Persistent
- 🔍 三、混合检索:BM25 + 向量搜索的双引擎
- 💾 四、双源存储:Daily Notes 与 MEMORY.md
- 🔄 五、Memory Flush:压缩前的"存档点"
- 🛡️ 六、安全架构:五层纵深防御
- 🔒 七、PRISM:零 Fork 运行时安全层
- 📦 八、Sandbox 沙箱:工具执行的隔离边界
- 🚀 九、生产部署安全清单
- 🏁 十、系列终章回顾
📌 一、Memory 系统:AI 的"记忆大脑"是怎么开发的
1.1 为什么 AI 助手需要记忆?
没有记忆的 AI 助手就像一条金鱼——每次对话都从零开始,你告诉它的偏好转头就忘,你讨论的项目背景下次还要重新解释。这在简单问答场景下可以接受,但在 OpenClaw 的定位(个人 AI 助手)下是致命的。一个真正有用的助手务必记住:你叫什么名字、你用什么编程语言、你在做什么项目、你之前讨论过什么。
但记忆又不能是简单的"把所有对话存下来"。LLM 的上下文窗口是有限的(GPT-4o 是 128K tokens,Claude 3.5 是 200K tokens),而且检索全量历史既慢又贵。OpenClaw 的解法是分层记忆 + 混合检索——把记忆分成不同层次,用不同的策略存储和检索,在"记住重要的"和"忘记无关的"之间找到平衡。
1.2 Memory 系统的设计原则
原则说明文件优先(File-First)所有记忆都是纯 Markdown 文件,可读、可编辑、可 Git 追踪本地优先(Local-First)索引存储在本地 SQLite,不依赖外部向量数据库混合检索(Hybrid Search)BM25 关键词匹配 + sqlite-vec 向量语义搜索自动保存(Auto-Flush)上下文压缩前自动触发 Memory Flush,防止信息丢失可观测(Observable)记忆文件是纯文本,用户可以随时查看和修改
🧠 二、三层记忆架构:Session → Daily → Persistent
OpenClaw 的记忆系统分为三层,从短到长,从热到冷:
2.1 Session 记忆(会话级)
Session 记忆是最短期的记忆,存储在 JSONL 会话文件中。它记录了当前对话的完整历史——用户说了什么、Agent 回复了什么、调用了哪些工具、返回了什么结果。Session 记忆的生命周期与对话绑定:对话完成,Session 文件持久化到磁盘;下次对话,Agent 可以通过 session.list 查看历史会话。
Session 记忆的核心挑战是上下文窗口有限。当对话轮次过多、工具调用结果过长时,Session 记忆会超出 LLM 的上下文窗口。这时就需要 Compaction(压缩)——把旧消息摘要压缩,腾出空间给新消息。我们在第三篇已经详细拆解了 Compaction 的三阶段流程,这里不再重复。
2.2 Daily Notes(日级)
Daily Notes 是中期记忆,存储在 memory/YYYY-MM-DD.md 文件中。每天一个文件,记录当天发生的重要事项。Daily Notes 由 Memory Flush 自动生成——当上下文接近阈值时,Agent 会触发一次静默的推理轮次,将重要信息写入当天的 Daily Note。
Daily Notes 的设计挺巧妙:它不是把对话原封不动地复制,而是让 LLM 主动总结"今天发生了什么重要的事"。这意味着 Daily Notes 是经过筛选和压缩的——只有 LLM 认为重要的信息才会被保存。这种"AI 自主决定记什么"的机制,比简单的全量存储高效得多。
2.3 Persistent Memory(持久级)
Persistent Memory 是最长期的记忆,存储在 MEMORY.md 文件中。它记录的是结构化的、稳定的、跨时间的信息——用户偏好、项目配置、常用模式、重要决策等。与 Daily Notes 不同,MEMORY.md 通常由用户手动维护或由 Agent 在明确指令下更新。
MEMORY.md 的格式是结构化的 Markdown,通常包含以下 Section:
# User Preferences
- 编程语言:Python、TypeScript
- 编辑器:VS Code + Vim
- 沟通语言:中文
# Current Projects
- OpenClaw 源码剖析系列(5篇,进行中)
- RAG 系统优化(调研阶段)
# Important Decisions
- 2026-04-15:决定使用 SQLite + sqlite-vec 替代 Pinecone
这种纯文本格式的最大好处是可读可编辑——用户可以随时用任何文本编辑器打开 MEMORY.md,查看 Agent 记住了什么,修改错误的记忆,添加新的信息。这是"文件优先"哲学的极致体现。
🔍 三、混合检索:BM25 + 向量搜索的双引擎
3.1 为什么需要混合检索?
单一检索方式都有局限:
- BM25(关键词匹配):擅长精确匹配(如"OpenClaw"、“SQLite”),但不理解语义(“数据库"匹配不到"DB”)
- 向量搜索(语义匹配):擅长语义相似(“记忆系统"能匹配到"知识存储”),但可能遗漏精确关键词
3.2 MemoryIndexManager 的达成
MemoryIndexManager(src/memory/manager.ts)是记忆检索的核心引擎。它使用 SQLite 作为底层存储,配合两个 SQLite 扩展:
组件功能说明SQLite FTS5全文搜索(BM25)内置扩展,零配置,对 Markdown 文本建立倒排索引sqlite-vec向量搜索SQLite 扩展,支持向量相似度搜索(余弦距离)
索引构建流程:
1. 文件扫描:扫描 memory/*.md 和 MEMORY.md,提取文本内容
2. 分块(Chunking):按段落或标题分割,每个块 200-500 tokens
3. BM25 索引:将文本块插入 FTS5 虚拟表
4. 向量索引:将文本块通过 Embedding 模型转换为向量,存入 sqlite-vec
5. 增量更新:文件变更时只更新受影响的块,不全量重建
3.3 Embedding 提供者:本地优先,云端回退
OpenClaw 的 Embedding 策略是"本地优先,云端回退":
尝试本地 Embedding(ONNX Runtime + 小模型)
↓ 失败?
尝试云端 Embedding(OpenAI text-embedding-3-small)
↓ 失败?
降级为纯 BM25 检索(无向量搜索)
这种降级策略确保了即使在离线环境下,记忆检索仍然可用——只是少了语义搜索能力,精确匹配依然开发。
3.4 检索 API
Agent 通过两个工具访问记忆:
工具功能说明memory_search搜索记忆输入查询,返回最相关的记忆片段memory_get获取具体行输入文件路径和行号,返回精确内容
这两个工具在 System Prompt 的 Memory Section 中被注入,Agent 知道何时使用它们。例如,当用户问"我之前讨论过什么 RAG 方案?"时,Agent 会调用 memory_search("RAG 方案"),从 Daily Notes 和 MEMORY.md 中检索相关信息。
💾 四、双源存储:Daily Notes 与 MEMORY.md
OpenClaw 的长期记忆有两个"水源":
4.1 动态源:Daily Notes(memory/YYYY-MM-DD.md)
Daily Notes 是动态的、自动生成的记忆。它的特点是:
- 自动创建:Memory Flush 触发时,Agent 自动写入
- 按时间组织:每天一个文件,自然的时间线
- 内容灵活:可以是总结、决策、待办事项、关键信息
- 检索权重较低:在混合检索中,Daily Notes 的权重低于 MEMORY.md
# 2026-05-07
## 讨论要点
- 完成了 OpenClaw 源码剖析系列第四篇(Channel 与 Skills)
- 确认第五篇将覆盖 Memory 和安全系统
- 用户偏好:文章风格保持技术深度 + 图文并茂
## 待办事项
- [ ] 第五篇需要包含 PRISM 安全层详解
- [ ] 系列完结后整理为 PDF 合集
4.2 静态源:MEMORY.md
MEMORY.md 是静态的、手动维护的记忆。它的特点是:
- 用户控制:用户可以随时查看、编辑、删除
- 结构化:按 Section 组织,信息稳定
- 检索权重较高:在混合检索中,MEMORY.md 的匹配结果排在 Daily Notes 前面
- 跨时间:不按日期分割,所有持久信息集中在一个文件
4.3 双源合并检索
当 Agent 调用 memory_search 时,检索流程是:
1. 并行查询:同时查询 FTS5(BM25)和 sqlite-vec(向量)
2. 结果合并:BM25 结果和向量结果取并集,按相关度排序
3. 权重调整:MEMORY.md 的匹配结果权重 × 1.5,Daily Notes 权重 × 1.0
4. 去重:同一文件的不同块只保留最相关的
5. 返回 Top-K:返回最相关的 K 个记忆片段(默认 K=5)
🔄 五、Memory Flush:压缩前的"存档点"
Memory Flush 是 OpenClaw 记忆系统最精妙的设计之一。它的核心思想是:在上下文压缩(Compaction)之前,先让 Agent 把重要信息保存到记忆文件中,确保信息不丢失。
5.1 触发条件
Memory Flush 由 shouldRunMemoryFlush() 函数判断:
```
function shouldRunMemoryFlush(params) {
const totalTokens = params.entry?.totalTokens;
if (!totalTokens || totalTokens Memory 用"文件优先 + 混合检索"让 AI 跨会话记住你,安全用"五层纵深防御"让 AI 守住底线。两者共同守护着 AI Agent 最核心的两个维度:记忆的完整性和行为的安全性。这就是 OpenClaw 的"记忆与防线"——让 AI 既能记住好事,又不会做坏事。
参考链接:
- OpenClaw GitHub 仓库
- OpenClaw Memory 文档
- OpenClaw PRISM 论文 (arXiv:2603.11853)
- PingCAP: Local-First RAG with SQLite
- MMNTM: OpenClaw Memory Architecture Walkthrough
- Nebius: OpenClaw Security Hardening Guide
- DataCamp: OpenClaw Security Best Practices
就写这么多吧,内容比较基础,适合入门回顾。有补充的地方欢迎留言一起完善。
评论 (0)
暂无评论