0%

AI Agent 记忆系统设计:从理论到 OpenClaw 实战

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) │
│ - 临时记忆,会话级上下文 │
│ - 对话历史、工具调用、中间状态 │
│ - 更新频率:极高(每次交互) │
└─────────────────────────────────────────┘

为什么是三层?

我的思考过程:

  1. 单层记忆的问题

    • 如果把所有内容堆在一起,文件会越来越大
    • 加载速度慢,影响响应时间
    • 难以区分”重要信息”和”临时日志”
  2. 两层记忆的不足

    • 只有长期 + 短期,缺少”原始日志”层
    • 无法追溯决策过程
    • 不利于事后复盘
  3. 三层的优势

    • 分离关注点:每层有明确用途
    • 性能优化:只加载需要的层
    • 可维护性:定期清理短期记忆,保留长期价值

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
# K8s PVC 中的实际路径
/root/.openclaw/workspace/
├── MEMORY.md # 默认记忆(首个用户)
├── SOUL.md # Agent 身份定义
├── USER.md # 用户信息
├── AGENTS.md # 工作规范
├── TOOLS.md # 工具配置
├── memory/ # 每日记忆
│ ├── 2026-03-10.md
│ └── 2026-03-09.md
└── memory-work/ # 工作记忆(隔离)
├── MEMORY.md
└── 2026-03-10.md

关键设计决策

  1. 为什么把 MEMORY.md 放在根目录?

    • 兼容性:OpenClaw 默认读取这个位置
    • 渐进式迁移:先保留,逐步切换到隔离目录
  2. 为什么每日记忆用日期命名?

    • 自然归档:每天一个文件,自动按时间排序
    • 易于清理:find . -name "*.md" -mtime +30 -delete
  3. 为什么不用数据库?

    • 简单即美: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

# Obsidian 双向同步
# Obsidian ←→ GitLab ←→ OpenClaw

实际配置(今晚部署的):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# K8s CronJob
apiVersion: batch/v1
kind: CronJob
metadata:
name: memory-sync
namespace: openclaw
spec:
schedule: "0 23 * * *" # 每晚 23:00
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 而不是实时同步?

  1. 性能考虑

    • 实时同步会增加每次交互的延迟
    • 批量提交减少 Git 操作次数
  2. 冲突处理

    • 每晚同步,冲突概率低
    • 即使冲突,人工解决也来得及
  3. 审计需求

    • Git 提交记录是天然的审计日志
    • 可以追溯每次记忆变更

3.3 安全配置

RBAC 权限控制

1
2
3
4
5
6
7
8
9
10
11
12
13
# Kubernetes RBAC
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"] # 只能读取 PVC

文件权限

1
2
3
4
# 记忆文件权限
chmod 600 MEMORY.md # 仅所有者可读写
chmod 700 memory/ # 仅所有者可访问目录
chown openclaw: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
# 输出:memory-work/.gitkeep ✅

教训

创建目录结构时,必须添加 .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
# 1. 备份当前记忆
cp -r memory/ memory-backup-20260310/

# 2. 创建隔离目录
mkdir -p memory-personal/
mkdir -p memory-work/

# 3. 迁移现有记忆(到个人目录)
mv memory/* memory-personal/

# 4. 更新 openclaw.json
{
"memory": {
"isolation": true,
"paths": {
"ou_047fe...": "memory-personal/",
"ou_work_...": "memory-work/"
}
}
}

# 5. 周末测试验证

关键决策

我们决定周末再配置,原因是:

  • 今晚已经 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
# 1. 检查 PVC
kubectl get pvc -n openclaw
# 输出:openclaw-data-pvc Bound 200Gi

# 2. 检查挂载
kubectl exec -it openclaw-gateway -n openclaw -- mount | grep workspace
# 输出:/dev/ceph/... on /workspace type ceph (ro, ...) ← 只读!

# 3. 检查 Deployment
kubectl get deployment openclaw-gateway -n openclaw -o yaml
# 发现:readOnlyRootFilesystem: true ← 根因!

解决方案

1
2
3
4
5
6
# 修改 Deployment
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 命令测试
time python3 -c "
import json
with open('MEMORY.md') as f:
content = f.read()
# 解析和处理
"

# 输出:real 0m0.082s ← 82ms

优化空间

  • 当前是全量加载,可以改为按需加载
  • 可以考虑缓存机制(Redis)
  • 但对于当前规模(<1MB),优化收益不大

5.2 存储大小

文件类型 当前大小 月增长 年预估
MEMORY.md 15KB 5KB 60KB
每日记忆 50KB/天 1.5MB 18MB
总计 - 1.5MB 18MB+

结论

  • 存储成本极低(18MB/年)
  • 不需要特殊优化
  • Git 仓库可以轻松容纳

5.3 同步性能

1
2
3
4
# Git 同步测试
time git push origin main

# 输出:real 0m2.341s ← 2.3 秒

每晚同步的可行性

  • ✅ 2.3 秒 < 5 秒(可接受)
  • ✅ 夜间执行,不影响白天使用
  • ✅ 失败可重试,容错性好

六、架构建议:我的个人观点

6.1 推荐做法

✅ 一定要做的

  1. 物理隔离:不同用户必须用不同目录
  2. Git 版本控制:所有记忆文件纳入版本管理
  3. 定期清理:每日记忆保留 30-90 天
  4. 权限控制:最小权限原则,严格 RBAC
  5. 备份机制:每晚同步到远程仓库

✅ 推荐工具

1
2
3
4
5
6
7
# 记忆管理脚本
#!/bin/bash
# cleanup-memory.sh
find memory/ -name "*.md" -mtime +90 -delete
git add memory/
git commit -m "chore: 清理 90 天前记忆"
git push

6.2 不推荐做法

❌ 绝对不要做的

  1. 共享记忆:多个用户用同一个 MEMORY.md
  2. 实时同步:每次交互都 Git push(性能灾难)
  3. 数据库存储:过度设计,维护成本高
  4. 无权限控制:任何人都能读取所有记忆
  5. 无限保留:从不清理,文件越来越大

❌ 踩过的坑

  • Git 空目录问题(必须加 .gitkeep
  • 深夜配置重大变更(选择用户在场时)
  • 只读文件系统(平衡安全和功能)

七、总结

7.1 核心要点

  1. 三层记忆架构:全局 + 每日 + 会话,分离关注点
  2. 物理隔离:不同用户用不同目录,安全底线
  3. Git 同步:每晚批量提交,性能和安全平衡
  4. 最小权限: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 部署实战