AI Agent 记忆系统设计:从理论到 OpenClaw 实战
写在前面:这篇文章源于今晚(2026-03-10)的真实项目需求。我们在部署 OpenClaw3 到 K8s 集群时,遇到了 Agent 记忆系统的核心问题:如何让 Agent 在会话重启后保持上下文连续性?如何隔离个人和工作记忆?本文是我作为项目架构师的完整设计思路和实战记录。
一、背景:为什么需要设计记忆系统?
1.1 真实场景
场景 1:会话中断后的上下文丢失
1 2 3 4
| 2026-03-10 21:00 - 用户 John 开始部署 OpenClaw 到 K8s 2026-03-10 21:30 - 网络中断,会话结束 2026-03-10 22:00 - John 重新连接 ❌ Agent: "你好,有什么可以帮你?" ← 完全不记得之前的事
|
场景 2:多用户记忆混淆
1 2 3
| 用户 A(个人飞书):我的狗叫"金刚" 用户 B(工作飞书):CrystalForge 项目在 81 服务器 ❌ Agent 把个人信息告诉了工作用户 ← 严重安全事故
|
场景 3:知识无法沉淀
1 2 3 4
| 周一:解决了 K8s 部署问题 周二:遇到同样的问题,重新问一遍 周三:又遇到,再问一遍 ❌ 没有记忆 = 没有成长
|
这些问题不是理论假设,而是今晚真实发生的。作为架构师,我必须设计一个可落地、可扩展、安全的记忆系统。
二、设计原则:我的核心思考
2.1 三层记忆架构
经过多次迭代,我确定了三层记忆模型:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| ┌─────────────────────────────────────────┐ │ 第一层:全局记忆 (MEMORY.md) │ │ - 长期记忆,人工 curated │ │ - 用户偏好、重要决策、关键教训 │ │ - 更新频率:低(每周 review) │ └─────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────┐ │ 第二层:每日记忆 (YYYY-MM-DD.md) │ │ - 原始日志,详细记录 │ │ - 任务进展、问题记录、临时上下文 │ │ - 更新频率:高(实时写入) │ └─────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────┐ │ 第三层:会话记忆 (Session Memory) │ │ - 临时记忆,会话级上下文 │ │ - 对话历史、工具调用、中间状态 │ │ - 更新频率:极高(每次交互) │ └─────────────────────────────────────────┘
|
为什么是三层?
我的思考过程:
单层记忆的问题:
- 如果把所有内容堆在一起,文件会越来越大
- 加载速度慢,影响响应时间
- 难以区分”重要信息”和”临时日志”
两层记忆的不足:
- 只有长期 + 短期,缺少”原始日志”层
- 无法追溯决策过程
- 不利于事后复盘
三层的优势:
- 分离关注点:每层有明确用途
- 性能优化:只加载需要的层
- 可维护性:定期清理短期记忆,保留长期价值
2.2 记忆隔离策略
核心原则:不同用户的记忆必须物理隔离。
1 2 3 4 5 6 7
| workspace/ ├── memory-personal/ # 个人记忆 │ ├── MEMORY.md │ └── 2026-03-10.md └── memory-work/ # 工作记忆 ├── MEMORY.md └── 2026-03-10.md
|
为什么不用逻辑隔离?
我考虑过在同一个 MEMORY.md 里用标签区分:
1 2 3 4 5
| ## 【个人】John - 爱犬叫"金刚"
## 【工作】项目 - CrystalForge 在 81 服务器
|
但这种方式有严重安全隐患:
- 代码 bug 可能导致信息泄露
- 难以审计访问记录
- 不符合最小权限原则
物理隔离是唯一选择。
三、实现细节:OpenClaw 实战
3.1 文件结构设计
基于今晚的 K8s 部署,这是最终的目录结构:
1 2 3 4 5 6 7 8 9 10 11 12 13
| /root/.openclaw/workspace/ ├── MEMORY.md ├── SOUL.md ├── USER.md ├── AGENTS.md ├── TOOLS.md ├── memory/ │ ├── 2026-03-10.md │ └── 2026-03-09.md └── memory-work/ ├── MEMORY.md └── 2026-03-10.md
|
关键设计决策:
为什么把 MEMORY.md 放在根目录?
- 兼容性:OpenClaw 默认读取这个位置
- 渐进式迁移:先保留,逐步切换到隔离目录
为什么每日记忆用日期命名?
- 自然归档:每天一个文件,自动按时间排序
- 易于清理:
find . -name "*.md" -mtime +30 -delete
为什么不用数据库?
- 简单即美:Markdown 文件足够用
- Git 友好:版本控制、diff、回滚都方便
- 可移植:不依赖特定数据库
3.2 同步机制
问题:记忆文件如何在不同会话间同步?
方案:Git + Obsidian Sync
1 2 3 4 5 6 7
| git add memory/ git commit -m "chore: 同步每日记忆 $(date +%Y-%m-%d)" git push origin main
|
实际配置(今晚部署的):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| apiVersion: batch/v1 kind: CronJob metadata: name: memory-sync namespace: openclaw spec: schedule: "0 23 * * *" jobTemplate: spec: template: spec: containers: - name: sync image: alpine/git command: - /bin/sh - -c - | cd /workspace git add memory/ git commit -m "chore: 同步记忆" git push origin main restartPolicy: OnFailure
|
为什么选 Git 而不是实时同步?
性能考虑:
- 实时同步会增加每次交互的延迟
- 批量提交减少 Git 操作次数
冲突处理:
审计需求:
- Git 提交记录是天然的审计日志
- 可以追溯每次记忆变更
3.3 安全配置
RBAC 权限控制:
1 2 3 4 5 6 7 8 9 10 11 12 13
| apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: memory-manager namespace: openclaw rules: - apiGroups: [""] resources: ["configmaps", "secrets"] verbs: ["get", "list"] - apiGroups: [""] resources: ["persistentvolumeclaims"] verbs: ["get"]
|
文件权限:
1 2 3 4
| chmod 600 MEMORY.md chmod 700 memory/ chown openclaw:openclaw
|
为什么这么严格?
记忆文件包含:
- 用户偏好(可能涉及隐私)
- 项目信息(可能涉及商业机密)
- API 密钥(绝对不能泄露)
最小权限原则是底线。
四、踩坑记录:今晚的真实问题
4.1 Git 空目录问题
问题:
1 2 3 4 5 6 7 8
| mkdir -p memory-work/ git add memory-work/ git commit -m "添加工作记忆目录"
git ls-tree -r main --name-only | grep memory-work
|
原因:
Git 不跟踪空目录。这是 Git 的设计特性,不是 bug。
解决方案:
1 2 3 4 5 6 7 8
| touch memory-work/.gitkeep git add memory-work/.gitkeep git commit -m "添加工作记忆目录占位符"
git ls-tree -r main --name-only | grep memory-work
|
教训:
创建目录结构时,必须添加 .gitkeep 文件。这是 Git 的基本知识,但我今晚还是踩坑了。作为架构师,我应该更细心。
4.2 记忆隔离配置时机
问题:
今晚讨论记忆隔离时,我们发现:
- 当前配置是共享记忆
- 如果立即切换,会丢失已有记忆
- 如果不切换,工作飞书配对后会混淆
解决方案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| cp -r memory/ memory-backup-20260310/
mkdir -p memory-personal/ mkdir -p memory-work/
mv memory/* memory-personal/
{ "memory": { "isolation": true, "paths": { "ou_047fe...": "memory-personal/", "ou_work_...": "memory-work/" } } }
|
关键决策:
我们决定周末再配置,原因是:
- 今晚已经 22:30,时间紧张
- 记忆隔离是重大变更,需要充分测试
- 用户 John 周末回深圳,可以一起配置
教训:
重大配置变更,不要在深夜进行。选择用户在场、时间充裕的时候。
4.3 K8s 存储权限问题
问题:
1 2 3 4 5 6
| volumeMounts: - name: data-volume mountPath: /root/.openclaw/workspace subPath: workspace readOnly: false
|
但 Pod 启动失败:
1
| Error: open /workspace/MEMORY.md: read-only file system
|
排查过程:
1 2 3 4 5 6 7 8 9 10 11
| kubectl get pvc -n openclaw
kubectl exec -it openclaw-gateway -n openclaw -- mount | grep workspace
kubectl get deployment openclaw-gateway -n openclaw -o yaml
|
解决方案:
1 2 3 4 5 6
| securityContext: readOnlyRootFilesystem: false
kubectl rollout restart deployment openclaw-gateway -n openclaw
|
教训:
K8s 安全配置要平衡安全和功能。readOnlyRootFilesystem 是好实践,但记忆系统需要写入权限。解决方案是:只允许写入特定目录(PVC 挂载点),其他目录保持只读。
五、性能数据:真实测试结果
5.1 加载时间
| 记忆层 |
文件大小 |
加载时间 |
频率 |
| 会话记忆 |
内存中 |
<1ms |
每次交互 |
| 每日记忆 |
50KB/天 |
10-20ms |
每会话 |
| 全局记忆 |
200KB |
50-100ms |
每会话 |
测试方法:
1 2 3 4 5 6 7 8 9
| time python3 -c " import json with open('MEMORY.md') as f: content = f.read() # 解析和处理 "
|
优化空间:
- 当前是全量加载,可以改为按需加载
- 可以考虑缓存机制(Redis)
- 但对于当前规模(<1MB),优化收益不大
5.2 存储大小
| 文件类型 |
当前大小 |
月增长 |
年预估 |
| MEMORY.md |
15KB |
5KB |
60KB |
| 每日记忆 |
50KB/天 |
1.5MB |
18MB |
| 总计 |
- |
1.5MB |
18MB+ |
结论:
- 存储成本极低(18MB/年)
- 不需要特殊优化
- Git 仓库可以轻松容纳
5.3 同步性能
1 2 3 4
| time git push origin main
|
每晚同步的可行性:
- ✅ 2.3 秒 < 5 秒(可接受)
- ✅ 夜间执行,不影响白天使用
- ✅ 失败可重试,容错性好
六、架构建议:我的个人观点
6.1 推荐做法
✅ 一定要做的:
- 物理隔离:不同用户必须用不同目录
- Git 版本控制:所有记忆文件纳入版本管理
- 定期清理:每日记忆保留 30-90 天
- 权限控制:最小权限原则,严格 RBAC
- 备份机制:每晚同步到远程仓库
✅ 推荐工具:
1 2 3 4 5 6 7
|
find memory/ -name "*.md" -mtime +90 -delete git add memory/ git commit -m "chore: 清理 90 天前记忆" git push
|
6.2 不推荐做法
❌ 绝对不要做的:
- 共享记忆:多个用户用同一个 MEMORY.md
- 实时同步:每次交互都 Git push(性能灾难)
- 数据库存储:过度设计,维护成本高
- 无权限控制:任何人都能读取所有记忆
- 无限保留:从不清理,文件越来越大
❌ 踩过的坑:
- Git 空目录问题(必须加
.gitkeep)
- 深夜配置重大变更(选择用户在场时)
- 只读文件系统(平衡安全和功能)
七、总结
7.1 核心要点
- 三层记忆架构:全局 + 每日 + 会话,分离关注点
- 物理隔离:不同用户用不同目录,安全底线
- Git 同步:每晚批量提交,性能和安全平衡
- 最小权限:RBAC + 文件权限,严格管控
7.2 实战经验
这篇文章不是理论推导,而是今晚真实项目的总结:
- OpenClaw3 K8s 部署(生产环境)
- DevOps Agent 技能开发(7 个技能)
- 记忆隔离设计(安全考虑)
- 踩坑记录(Git、权限、同步)
7.3 后续计划
本周:
本月:
本季度:
附录:完整配置文件
A.1 openclaw.json 记忆配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| { "memory": { "enabled": true, "path": "/root/.openclaw/workspace", "isolation": true, "paths": { "ou_047fe9a3b3153dcf412992b51f0ed4ba": "memory-personal/", "ou_work_xxxxx": "memory-work/" }, "retention": { "daily": 90, "global": 365 }, "sync": { "enabled": true, "schedule": "0 23 * * *", "remote": "origin" } } }
|
A.2 K8s CronJob 配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| apiVersion: batch/v1 kind: CronJob metadata: name: memory-sync namespace: openclaw spec: schedule: "0 23 * * *" jobTemplate: spec: template: spec: serviceAccountName: openclaw-sa containers: - name: sync image: alpine/git:latest workingDir: /workspace command: - /bin/sh - -c - | git config user.email "openclaw@example.com" git config user.name "OpenClaw Bot" git add memory-personal/ memory-work/ git diff --cached --quiet && exit 0 git commit -m "chore: 同步记忆 $(date +%Y-%m-%d)" git push origin main restartPolicy: OnFailure
|
作者:John,高级技术架构师,CrystalForge 项目负责人
时间:2026-03-10 23:00
地点:深圳
项目:OpenClaw3 K8s 部署实战