OpenClaw源码深度剖析:AI记忆机制与安全防线
OpenClaw 源码剖析(五):Memory 与安全——AI 的记忆机制与防线
存储与安全体系,是AI Agent迈向实用化的关卡。一个连用户基础信息都记不住的助手,和一个能精准回溯项目细节的助手,体验差距巨大。OpenClaw作为坐拥21万Star的个人AI框架,在此问题上提供了极为务实的设计方案。本文直击其底层源码,拆解记忆机制的运作逻辑与安全防线的构建方式。
核心结论先放在这里:OpenClaw在记忆与安全上走的是"实用主义"路线——无需昂贵的向量数据库,也无须复杂的模型微调,仅凭标准的文件系统与精妙的策略组合,便搭建了一套可投入使用的记忆与防护系统。
一、Memory 系统:AI 的"记忆大脑"是怎么工作的
为什么 AI 助手需要记忆?
缺乏记忆能力的AI助手好比一条金鱼——每次对话都是全新开始。你告知的偏好它转身即忘,讨论过的项目背景下次还得重新铺垫。这种体验在简单的一问一答场景下或许忍忍就过去了,但对于OpenClaw这样的个人AI助手是完全不可接受的。一个真正有价值的助手必须记住:你的称呼、常用编程语言、在进行的项目、过往的对话要点。
然而,记忆系统绝不能是"将所有对话原文存档"的粗暴方案。LLM的上下文窗口终究存在上限——GPT-4o是128K tokens,Claude 3.5是200K tokens,且全量检索既拖慢响应速度又消耗大量计算资源。OpenClaw的解法是分层记忆加混合检索:将记忆按层级拆解,用不同策略进行存取,在"记牢关键信息"与"遗忘冗余内容"之间找到最优平衡点。
Memory 系统的设计原则
| 原则 | 说明 |
|---|---|
| 文件优先(File-First) | 所有记忆均以纯 Markdown 文件存储,可读、可编辑、可纳入 Git 版本追踪 |
| 本地优先(Local-First) | 索引存放于本地 SQLite,无需依赖外部向量数据库 |
| 混合检索(Hybrid Search) | BM25 关键词匹配 + sqlite-vec 向量语义搜索 |
| 自动保存(Auto-Flush) | 上下文压缩前自动触发 Memory Flush,避免信息丢失 |
| 可观测(Observable) | 记忆文件为纯文本,用户可随时查阅与修改 |
二、三层记忆架构:Session → Daily → Persistent
OpenClaw的记忆系统划分为三层,从短期到长期,从热数据到冷数据,逐层递进。
Session 记忆(会话级)
这是最短暂的一层,存于JSONL会话文件中。它完整记录了当前对话的全过程——用户的提问、Agent的回复、调用的工具、返回的结果。Session记忆与对话生命周期完全绑定:对话结束即持久化至磁盘,下次对话可通过session.list回溯历史会话。
Session记忆面临的核心挑战在于上下文窗口限制。随着对话轮次增多、工具调用结果变长,Session内容很快会触及LLM的承载上限。此时必须执行Compaction(压缩)——将旧消息提炼为摘要,为新内容腾出空间。这部分流程系列第三篇已做过详细阐述,此处不再赘述。
Daily Notes(日级)
Daily Notes属于中期记忆,存储于memory/YYYY-MM-DD.md文件中。每天一个独立文件,记录当日发生的关键事项。它由Memory Flush自动生成——当上下文即将占满预设阈值时,Agent会触发一次静默推理轮次,将重要信息整理写入当天的Daily Note。
这个设计非常有巧思:Daily Notes并非原封不动复制对话内容,而是让LLM主动判断"今天发生了哪些重要事件"。被保留下来的信息经过了筛选与提炼,只有LLM判定为有价值的内容才会被写入。这种"AI自主决定记录什么"的机制,远比简单的全量存储高效。
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 + 向量搜索的双引擎
为什么需要混合检索?
单一的检索方式总有局限:
- BM25(关键词匹配):擅长精确匹配,例如"OpenClaw"、"SQLite"这类关键词一抓一个准,但它无法理解语义——搜索"数据库"匹配不到"DB"。
- 向量搜索(语义匹配):擅长语义相似度判断,"记忆系统"能匹配到"知识存储",但反过来它可能漏掉精确定位的关键词。
OpenClaw的解决思路是混合检索——同时执行BM25和向量搜索,再将结果合并、去重、排序。这样既能精确匹配关键词,又不会丢失语义层面的相关性。
MemoryIndexManager 的实现
MemoryIndexManager(src/memory/manager.ts)是记忆检索的核心引擎。底层使用SQLite进行存储,配合两个SQLite扩展:
| 组件 | 功能 | 说明 |
|---|---|---|
| SQLite FTS5 | 全文搜索(BM25) | 内置扩展,零配置,对 Markdown 文本建立倒排索引 |
| sqlite-vec | 向量搜索 | SQLite 扩展,支持向量相似度搜索(余弦距离) |
索引构建的流程大致如下:
- 文件扫描:扫描
memory/*.md和MEMORY.md,提取所有文本内容 - 分块:按段落或标题进行分割,每个块控制在200-500 tokens左右
- BM25索引:将文本块插入FTS5虚拟表
- 向量索引:将文本块通过Embedding模型转换为向量,存入sqlite-vec
- 增量更新:文件变更时仅更新受影响的块,避免全量重建
Embedding 提供者:本地优先,云端回退
OpenClaw的Embedding策略是"本地优先,云端回退":
尝试本地 Embedding(ONNX Runtime + 小模型)
↓ 失败?尝试云端 Embedding(OpenAI text-embedding-3-small)
↓ 失败?降级为纯 BM25 检索(无向量搜索)
这套降级策略确保了即使在离线环境下,记忆检索仍然可用——缺失的只是语义层面的搜索能力,但精确匹配依旧正常运行。
检索 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的长期记忆有两个"水源":
动态源:Daily Notes(memory/YYYY-MM-DD.md)
Daily Notes是动态、自动生成的记忆,特点如下:
- 自动创建:Memory Flush触发时,Agent自动写入
- 按时间组织:每天一个文件,形成自然的时间轴
- 内容灵活:可以是总结、决策、待办事项、关键信息
- 检索权重较低:在混合检索中,Daily Notes的权重低于MEMORY.md
Daily Notes的典型内容:
# 2026-05-07
## 讨论要点
- 完成了 OpenClaw 源码剖析系列第四篇(Channel 与 Skills)
- 确认第五篇将覆盖 Memory 和安全系统
- 用户偏好:文章风格保持技术深度 + 图文并茂
## 待办事项
- [ ] 第五篇需要包含 PRISM 安全层详解
- [ ] 系列完结后整理为 PDF 合集
静态源:MEMORY.md
MEMORY.md是静态、手动维护的记忆,特点不同:
- 用户控制:用户可以随时查看、编辑、删除
- 结构化:按Section组织,信息相对稳定
- 检索权重较高:混合检索时,MEMORY.md的匹配结果会排在Daily Notes前面
- 跨时间:不按日期分割,所有持久信息集中在一个文件里
双源合并检索
当Agent调用memory_search时,检索流程如下:
- 并行查询:同时查FTS5(BM25)和sqlite-vec(向量)
- 结果合并:BM25结果和向量结果取并集,按相关度排序
- 权重调整:MEMORY.md的匹配结果权重 × 1.5,Daily Notes权重 × 1.0
- 去重:同一个文件的不同块只保留最相关的
- 返回Top-K:返回最相关的K个记忆片段(默认K=5)
五、Memory Flush:压缩前的"存档点"
Memory Flush可以说是OpenClaw记忆系统里最精妙的设计之一。核心思想非常直接:在上下文压缩(Compaction)之前,先让Agent把重要信息保存到记忆文件里,确保信息不丢失。
触发条件
Memory Flush由shouldRunMemoryFlush()函数判断:
function shouldRunMemoryFlush(params) {
const totalTokens = params.entry?.totalTokens;
if (!totalTokens || totalTokens <= 0) return false;
// 计算阈值:上下文窗口 - 预留 - 软阈值
const threshold = Math.max(0, params.contextWindowTokens - params.reserveTokensFloor - params.softThresholdTokens);
if (totalTokens < threshold) return false;
// 每个 Compaction 周期只 Flush 一次
const compactionCount = params.entry?.compactionCount ?? 0;
const lastFlushAt = params.entry?.memoryFlushCompactionCount;
if (typeof lastFlushAt === "number" && lastFlushAt === compactionCount) {
return false; // 本周期已 Flush 过
}
return true;
}
几个关键参数:
| 参数 | 默认值 | 说明 |
|---|---|---|
DEFAULT_MEMORY_FLUSH_SOFT_TOKENS | 4000 | 软阈值,给 Agent 留出"存档"的空间 |
reserveTokensFloor | 模型相关 | 硬预留,确保 Compaction 有足够空间 |
memoryFlushCompactionCount | 自动追踪 | 防止同一周期重复 Flush |
Flush 流程
- 检测:
shouldRunMemoryFlush()返回true - 静默推理:Agent执行一次不向用户展示的推理轮次,Prompt为"将重要信息保存到 memory/YYYY-MM-DD.md"
- 写入:Agent调用
write_file工具,把总结写入Daily Note - 标记:记录
memoryFlushCompactionCount,防止重复 - 继续:Compaction正常执行,旧消息被压缩
这个设计的精妙之处在于:它把一个破坏性操作(压缩 = 丢失信息)变成了一个有准备的操作(先存档,再压缩)。就像是游戏里的"存档点"——在Boss战之前自动保存,就算失败了也不至于从头再来。
六、安全架构:五层纵深防御
OpenClaw的安全架构采用的是纵深防御策略,从外到内分五层:
L1:Gateway 认证
最外层的防御线是Gateway的认证机制。所有连接到Gateway的客户端——不管是Channel、CLI还是Web UI——都必须通过挑战-响应认证。Gateway支持两种认证模式:
- Token认证:在
openclaw.yaml中配置auth.token,客户端连接时必须提供 - Password认证:配置
auth.password,客户端通过密码认证
远程访问时推荐使用Tailscale——Gateway绑定127.0.0.1:18789,Tailscale提供加密隧道,无需公网暴露端口。
L2:Tool Policy 策略
第二层是工具执行策略。每个工具调用都要经过Tool Policy检查:
- allow:自动放行(比如
read_file、browser_tool) - confirm:需要用户确认(比如
write_file、bash) - deny:硬性拒绝(比如
rm -rf /)
这部分在第三篇已经详细拆解过六步链路,不再重复了。
L3:Sandbox 沙箱隔离
第三层是工具执行的沙箱隔离,提供以下隔离维度:
| 隔离维度 | 实现方式 |
|---|---|
| 文件系统 | 限制可访问的目录范围 |
| 网络 | 可选的网络隔离 |
| 进程 | Docker 容器隔离 |
| 资源 | CPU、内存、执行时间限制 |
沙箱信息通过sandbox-info.ts注入到System Prompt中,Agent知道自己的执行边界在哪里。
L4:PRISM 运行时防护
第四层是PRISM——OpenClaw的运行时安全层。这是最复杂也最关键的安全组件,下一节会详细拆解。
L5:审计与可观测
最内一层是审计和可观测性。所有工具调用、安全事件、策略变更都记录到链式审计日志中,支持完整性校验和事后追溯。
七、PRISM:零 Fork 运行时安全层
PRISM(Plugin-based Runtime Intrusion Security Monitor)是OpenClaw的运行时安全层,2026年3月发表在arXiv上(arXiv:2603.11853)。其核心设计理念是零Fork——不修改OpenClaw任何上游代码,通过插件机制嵌入Gateway进程。
三组件架构
PRISM由三个组件构成:
| 组件 | 运行方式 | 职责 |
|---|---|---|
| In-Process Plugin | 嵌入 Gateway 进程 | 10 个运行时 Hook 拦截,热重载策略 |
| Sidecar Service | 独立进程(可选) | LLM 辅助扫描,网络治理,密钥过滤 |
| Security Dashboard | Web UI | 审计记录,健康探针,Allow 工作流 |
十个运行时 Hook
PRISM在Agent运行时的10个关键节点插入了Hook:
| Hook | 拦截点 | 安全检查 |
|---|---|---|
onToolCall | 工具调用前 | 策略检查、风险评分 |
onToolResult | 工具返回后 | 输出过滤、密钥检测 |
onMessage | 消息发送前 | Prompt Injection 检测 |
onResponse | LLM 响应后 | 敏感信息过滤 |
onFileWrite | 文件写入前 | 路径白名单、权限检查 |
onFileRead | 文件读取前 | 路径白名单 |
onNetworkRequest | 网络请求前 | 域名/路径白名单 |
onShellExec | Shell 执行前 | 命令白名单、危险命令检测 |
onSessionStart | 会话开始时 | 初始化安全上下文 |
onSessionEnd | 会话结束时 | 审计记录、安全清理 |
风险累积评分
PRISM最重要的创新是风险累积评分。它不对每个操作做独立的"允许/拒绝"判断,而是累积风险分数。随着可疑操作增多,响应级别会逐步升级:
| 风险等级 | 分数范围 | 响应动作 |
|---|---|---|
| ✅ 低风险 | 0-30 | 正常执行,记录审计日志 |
| ⚠️ 中风险 | 31-60 | 额外日志,限制工具范围 |
| ???? 高风险 | 61-80 | 禁止危险工具,需要用户确认 |
| ???? 严重 | 81-100 | 会话级锁定,停止所有工具调用 |
这种渐进式响应比简单的"一刀切"实用得多。单个可疑操作不会直接触发锁定,但连续多个可疑操作会让风险分数逐渐累积到锁定级别。这就好比信用卡的风控系统——一笔异常交易可能只是你在旅行,但连续多笔异常交易就会触发冻结。
启发式优先,LLM 辅助
PRISM的扫描路径是启发式优先,LLM辅助:
- 启发式扫描(快速、低成本):正则匹配危险命令、路径遍历、密钥模式
- LLM 辅助扫描(慢速、高成本):当启发式无法判断时,调用 LLM 分析意图
这种设计保证了大部分安全检查都在毫秒级完成,只有边缘情况才需要LLM介入。
八、Sandbox 沙箱:工具执行的隔离边界
沙箱的必要性
当AI助手具备执行Shell命令的能力时,沙箱就不是"可选的"了,而是"必须的"。一个没有沙箱的Agent就像一把没有保险的枪——你不知道它什么时候会走火。
OpenClaw的沙箱系统在三个维度提供隔离:
文件系统沙箱
文件系统沙箱限制Agent可访问的目录范围。默认情况下,Agent只能访问工作空间目录(~/.openclaw/workspace/)和临时目录。访问其他目录需要经过Tool Policy的confirm级别审批。
# openclaw.yaml 沙箱配置
sandbox:
allowedPaths:
- ~/.openclaw/workspace/
- /tmp/openclaw/
deniedPaths:
- /etc/
- ~/.ssh/
- ~/.aws/
网络沙箱
网络沙箱限制Agent的出站网络访问。PRISM的Sidecar Service提供网络治理:
- 域名白名单:只允许访问特定域名
- 路径保护:禁止访问内网敏感路径
- 出站密钥过滤:检测并阻止API Key、密码等敏感信息外泄
Docker 容器沙箱
对于高风险操作(比如执行用户提交的代码),OpenClaw支持Docker容器级别的隔离:
sandbox:
docker:
enabled: true
image: openclaw/sandbox:latest
readOnlyRoot: true # 只读根文件系统
memoryLimit: 512m # 内存限制
cpuLimit: 0.5 # CPU 限制
timeout: 30s # 执行超时
networkMode: none # 无网络访问
九、生产部署安全清单
将OpenClaw部署到生产环境时,安全不是什么"锦上添花"的事,而是必须到位。下面是根据官方文档和社区最佳实践整理的安全清单:
网络层
| 检查项 | 说明 | 配置 |
|---|---|---|
| Gateway 绑定 127.0.0.1 | 禁止公网直接访问 | openclaw.yaml: gateway.host: 127.0.0.1 |
| 启用认证 | Token 或 Password 至少选一个 | openclaw.yaml: auth.token: |
| 远程访问走 Tailscale | 加密隧道,零公网暴露 | tailscale up + Gateway 绑定 Tailscale IP |
| 禁止暴露 18789 端口 | 防火墙规则 | ufw deny 18789 |
容器层
| 检查项 | 说明 |
|---|---|
| 非特权用户运行 | Docker 容器不以 root 运行 |
| 只读文件系统 | 根文件系统挂载为 read-only |
| 资源限制 | CPU、内存、PID 限制 |
| 禁止特权模式 | --privileged 标志永远不要用 |
凭证层
| 检查项 | 说明 |
|---|---|
| API Key 存 .env | 不入 Git,不硬编码 |
| PRISM 密钥过滤 | 防止 API Key 通过工具调用外泄 |
| Auth Profile 轮换 | LLM API Key 轮换/冷却机制 |
| 定期轮换 Gateway Token | 至少每月更换一次 |
运行时层
| 检查项 | 说明 |
|---|---|
| 启用 PRISM | 生产环境必须开启 |
| Tool Policy 最小权限 | 只开放必要的工具 |
| ClawHub 技能审查 | 安装前检查技能来源和代码 |
| 定期审计日志 | 每周检查 PRISM 审计记录 |
十、系列终章回顾
五篇文章,从全局到局部,从架构到源码,完整拆解了OpenClaw这个21万Star的AI Agent框架。用一张表来回顾整个系列:
| 篇目 | 核心主题 | 一句话总结 |
|---|---|---|
| 第一篇 | 项目全景 | 框架做得越少,Agent 能做的越多——减法才是最难的加法 |
| 第二篇 | Gateway | 不思考,但确保思考发生在正确的时间、正确的上下文、正确的隔离边界内 |
| 第三篇 | Agent Loop | 双层循环分离健壮性和正确性,让 AI 既能干好事,又不出坏事 |
| 第四篇 | Channel & Skills | 适配器模式抹平平台差异,提示词插件实现能力无限扩展 |
| 第五篇 | Memory & 安全 | 文件优先的记忆 + 纵深防御的安全,守护 AI 的记忆完整性和行为安全性 |
OpenClaw 的核心设计哲学
回顾整个系列,OpenClaw的设计哲学可以归纳为三条:
1. 减法优于加法
OpenClaw的底层框架pi-mono只有4个工具,系统提示词不到1000个token。它不依赖LangChain/LangGraph这些重量级框架,而是用最少的代码解决最核心的问题。这种"减法"不是偷懒,而是对问题本质的深刻理解——AI Agent的复杂性应该来自任务本身,而不是框架。
2. 文件优先
配置是YAML文件,记忆是Markdown文件,会话是JSONL文件,技能是Markdown加脚本文件。所有状态都是纯文件,可读、可编辑、可Git追踪。这种"文件优先"设计让OpenClaw的每个组件都是可观测的、可审计的、可恢复的。
3. 纵深防御
从Gateway认证到Tool Policy,从Sandbox隔离到PRISM运行时防护,从审计日志到密钥过滤——OpenClaw的安全不是一层墙,而是一条完整的防线。每一层都不完美,但每一层都在不同维度提供保护,组合起来就是一道坚不可摧的纵深防御体系。
给开发者的建议
如果正在基于OpenClaw构建自己的AI助手,可以给出五条建议:
- 先跑起来,再优化:用
openclaw onboard五分钟启动,先体验再深入 - 从Skill开始扩展:不要改框架代码,先写一个SKILL.md试试
- 安全不能省:生产环境必须开启PRISM + Tool Policy + Sandbox
- 记忆是你的资产:定期维护MEMORY.md,它是你AI助手的"长期记忆"
- 读源码:OpenClaw的源码写得非常清晰,是最好的学习材料
总结速查卡
Memory 核心概念
| 概念 | 一句话解释 |
|---|---|
| 三层记忆 | Session(会话级)→ Daily Notes(日级)→ MEMORY.md(持久级) |
| 混合检索 | BM25 关键词匹配 + sqlite-vec 向量语义搜索 |
| 双源存储 | Daily Notes(动态自动)+ MEMORY.md(静态手动) |
| Memory Flush | 压缩前自动存档,防止信息丢失 |
| MemoryIndexManager | SQLite + FTS5 + sqlite-vec,本地优先零依赖 |
| Embedding 降级 | 本地 ONNX → 云端 OpenAI → 纯 BM25 |
安全核心概念
| 概念 | 一句话解释 |
|---|---|
| 五层纵深防御 | 认证 → Tool Policy → Sandbox → PRISM → 审计 |
| PRISM | 零 Fork 运行时安全层,插件嵌入 Gateway 进程 |
| 风险累积评分 | 渐进式响应,0-100 分,四级响应 |
| 10 Hook | 从工具调用到会话生命周期的全链路拦截 |
| 启发式优先 | 正则快速扫描,LLM 辅助边缘情况 |
| 零 Fork | 不修改上游代码,通过插件机制嵌入 |
参考链接:
- 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



