OpenClaw 的记忆系统通过结构化的文件存储和索引机制,实现了跨对话的长期记忆功能。要正确配置使其自动加载用户画像和项目背景,关键在于建立规范的记忆目录结构、配置索引文件,并确保启动流程正确执行记忆加载。

一、记忆系统核心架构

OpenClaw 采用三层记忆架构,其中长期记忆通过本地文件系统持久化存储:

记忆层级 存储位置 生命周期 核心作用
短期记忆 对话上下文 单次对话 保持当前对话连贯性
中期记忆 Daily Notes 按日期组织 记录每日工作流水账
长期记忆 memory/ 目录 持久化存储 存储用户画像、项目背景等核心信息

二、长期记忆目录结构配置

首先需要在 OpenClaw 工作空间创建标准化的记忆目录结构:

# 创建记忆系统根目录
mkdir -p ~/.openclaw/workspace/memory/

# 创建核心记忆文件
cd ~/.openclaw/workspace/memory/
touch MEMORY.md
touch user_profile.md
touch project_current.md

标准目录结构如下 :

~/.openclaw/workspace/memory/
├── MEMORY.md          # 记忆索引(所有记忆的目录)
├── user_profile.md    # 用户画像
├── project_*.md       # 各项目的背景信息
├── feedback_*.md      # 用户给过的反馈和偏好
└── reference_*.md     # 外部资源的引用信息

三、记忆文件内容规范

3.1 MEMORY.md - 记忆索引文件

这是记忆系统的入口文件,AI 在每次启动时会首先读取此文件来决定加载哪些记忆 :

# 记忆索引

## 用户相关
- [用户画像](user_profile.md) — 职业背景、工作偏好、沟通风格

## 项目相关
- [项目:OpenClaw配置](project_openclaw_config.md) — OpenClaw 记忆系统配置项目
- [项目:内容创作](project_content_creation.md) — 技术文章写作项目

## 反馈记录
- [反馈:文档格式](feedback_doc_format.md) — 用户对文档格式的具体要求

## 外部参考
- [参考:OpenClaw文档](reference_openclaw_docs.md) — OpenClaw 官方文档链接

关键原则MEMORY.md 仅作为索引,不存储具体内容。每条记忆单独存储为独立文件,索引文件只记录文件名和简要描述 。

3.2 user_profile.md - 用户画像文件

用户画像让 AI 了解服务对象的身份、职业和工作方式:

---
name: 用户画像
type: user
last_updated: 2024-01-15
---

## 基本信息
- 姓名:张工程师
- 职业:全栈开发工程师,专注于 AI 应用开发
- 公司:某科技公司技术部

## 工作偏好
- 沟通风格:直接、高效、喜欢用示例说明
- 文档偏好:结构清晰、代码示例丰富、步骤详细
- 工具栈:Python/JavaScript、Docker、Git、VS Code

## 技术背景
- 擅长领域:后端开发、数据库设计、API 开发
- 学习方向:大语言模型应用、自动化工作流
- 常用框架:FastAPI、React、LangChain

## 个性化设置
- 时区:Asia/Shanghai (UTC+8)
- 工作时间:周一至周五 9:00-18:00
- 项目管理工具:飞书、GitHub Projects

3.3 project_*.md - 项目背景文件

项目背景记忆让 AI 理解当前工作的上下文和历史进展:

---
name: 项目:OpenClaw记忆系统配置
type: project
created: 2024-01-10
status: active
priority: high
---

## 项目概述
本项目旨在配置 OpenClaw 的完整记忆系统,实现跨对话的长期记忆功能。

## 当前状态
- ✅ 已完成:记忆目录结构创建
- ✅ 已完成:MEMORY.md 索引文件配置
- ✅ 已完成:用户画像文件创建
- 🔄 进行中:项目背景文件编写
- ⏳ 待完成:反馈记录机制配置
- ⏳ 待完成:自动加载流程测试

## 项目配置详情
- 记忆存储路径:~/.openclaw/workspace/memory/
- 索引文件:MEMORY.md
- 记忆类型:用户画像、项目背景、反馈记录、外部引用
- 更新频率:用户画像每月检查,项目背景按需更新

## 相关文件
- 配置文档:~/.openclaw/workspace/docs/memory_system.md
- 测试脚本:~/.openclaw/workspace/scripts/test_memory.py

## 注意事项
1. 记忆文件使用 YAML Front Matter 格式
2. 每次重要变更后更新 last_updated 字段
3. 定期清理过期或无效的记忆条目

四、自动加载配置

4.1 BOOT.md 启动配置

在 OpenClaw 的启动配置文件中添加记忆加载任务,确保每次对话开始时自动加载记忆:

# ~/.openclaw/workspace/BOOT.md

## 系统启动任务
启动时自动执行以下任务:

### 1. 记忆系统初始化
1. 检查 memory/ 目录是否存在,不存在则创建
2. 读取 memory/MEMORY.md 记忆索引文件
3. 加载所有标记为 active 的记忆文件
4. 验证记忆文件的有效性(检查最后修改时间)

### 2. 记忆状态检查
- 检查记忆文件的最后更新时间
- 超过30天的记忆标记为"待验证"
- 无效或损坏的记忆文件记录到日志

### 3. 上下文注入
- 将用户画像注入系统提示词
- 将当前活跃项目背景加载到工作上下文
- 应用最近的反馈记录到行为规则

### 4. 会话准备
- 建立本次会话的短期记忆缓冲区
- 设置记忆写入触发器(用户纠正、重要确认等)
- 初始化记忆检索器用于相关记忆召回

4.2 自动化脚本实现

可以创建自动化脚本确保记忆系统的正确加载:

#!/usr/bin/env python3
# memory_loader.py - OpenClaw 记忆自动加载脚本 

import os
import yaml
import json
from datetime import datetime, timedelta
from pathlib import Path

class MemoryLoader:
    def __init__(self, workspace_path="~/.openclaw/workspace"):
        self.workspace = Path(workspace_path).expanduser()
        self.memory_dir = self.workspace / "memory"
        self.index_file = self.memory_dir / "MEMORY.md"
        
    def load_memory_index(self):
        """加载记忆索引文件"""
        if not self.index_file.exists():
            print("记忆索引文件不存在,创建默认索引...")
            self.create_default_index()
            
        memories = []
        with open(self.index_file, 'r', encoding='utf-8') as f:
            lines = f.readlines()
            for line in lines:
                if line.strip().startswith('- ['):
                    # 解析索引条目: - [用户画像](user_profile.md) — 描述
                    parts = line.strip()[2:].split('](')
                    if len(parts) == 2:
                        name = parts[0][1:]  # 移除开头的 [
                        file_part = parts[1].split(')')[0]
                        description = parts[1].split(' — ')[1] if ' — ' in parts[1] else ""
                        
                        memories.append({
                            'name': name,
                            'file': file_part,
                            'description': description,
                            'path': self.memory_dir / file_part
                        })
        return memories
    
    def load_memory_content(self, memory_entry):
        """加载单个记忆文件内容"""
        if not memory_entry['path'].exists():
            print(f"警告:记忆文件不存在 {memory_entry['file']}")
            return None
            
        with open(memory_entry['path'], 'r', encoding='utf-8') as f:
            content = f.read()
            
        # 解析 YAML Front Matter(如果存在)
        if content.startswith('---'):
            parts = content.split('---', 2)
            if len(parts) >= 3:
                try:
                    front_matter = yaml.safe_load(parts[1])
                    body_content = parts[2].strip()
                    return {
                        'front_matter': front_matter,
                        'content': body_content,
                        'raw': content
                    }
                except yaml.YAMLError:
                    return {'content': content, 'raw': content}
        
        return {'content': content, 'raw': content}
    
    def check_memory_freshness(self, memory_path):
        """检查记忆新鲜度"""
        if not memory_path.exists():
            return 'missing'
            
        stat = memory_path.stat()
        last_modified = datetime.fromtimestamp(stat.st_mtime)
        days_old = (datetime.now() - last_modified).days
        
        if days_old > 30:
            return 'stale'
        elif days_old > 7:
            return 'aging'
        else:
            return 'fresh'
    
    def create_default_index(self):
        """创建默认记忆索引"""
        default_index = """# 记忆索引

## 用户相关
- [用户画像](user_profile.md) — 职业背景、工作偏好、沟通风格

## 项目相关
- [项目:默认项目](project_default.md) — 当前活跃项目信息

## 反馈记录
- [反馈:系统使用](feedback_system.md) — 系统使用偏好和纠正记录
"""
        self.memory_dir.mkdir(parents=True, exist_ok=True)
        with open(self.index_file, 'w', encoding='utf-8') as f:
            f.write(default_index)
            
    def load_all_memories(self):
        """加载所有记忆"""
        print("开始加载 OpenClaw 记忆系统...")
        
        # 1. 加载索引
        memories = self.load_memory_index()
        print(f"找到 {len(memories)} 个记忆条目")
        
        # 2. 加载并验证每个记忆
        loaded_memories = []
        for memory in memories:
            status = self.check_memory_freshness(memory['path'])
            
            if status == 'missing':
                print(f"  ⚠️  {memory['name']}: 文件缺失")
                continue
                
            content = self.load_memory_content(memory)
            if content:
                memory['status'] = status
                memory['content'] = content
                loaded_memories.append(memory)
                
                if status == 'fresh':
                    print(f"  ✅ {memory['name']}: 已加载(状态良好)")
                elif status == 'aging':
                    print(f"  ⚠️  {memory['name']}: 已加载(需要更新)")
                elif status == 'stale':
                    print(f"  ⚠️  {memory['name']}: 已加载(已过时)")
        
        # 3. 组织记忆数据
        organized = {
            'user_profile': None,
            'projects': [],
            'feedbacks': [],
            'references': []
        }
        
        for memory in loaded_memories:
            if 'user' in memory['file']:
                organized['user_profile'] = memory
            elif 'project' in memory['file']:
                organized['projects'].append(memory)
            elif 'feedback' in memory['file']:
                organized['feedbacks'].append(memory)
            elif 'reference' in memory['file']:
                organized['references'].append(memory)
        
        print(f"记忆加载完成:用户画像 x{1 if organized['user_profile'] else 0}, "
              f"项目 x{len(organized['projects'])}, "
              f"反馈 x{len(organized['feedbacks'])}")
        
        return organized

# 使用示例
if __name__ == "__main__":
    loader = MemoryLoader()
    memories = loader.load_all_memories()
    
    # 将加载的记忆转换为系统提示词
    system_prompt = "基于以下记忆信息进行对话:

"
    
    if memories['user_profile']:
        profile = memories['user_profile']
        system_prompt += f"用户画像:{profile['name']}
"
        system_prompt += f"{profile['content'].get('content', '')[:500]}...

"
    
    if memories['projects']:
        system_prompt += "当前项目:
"
        for project in memories['projects'][:3]:  # 只加载前3个项目
            system_prompt += f"- {project['name']}: {project['description']}
"
    
    print("
生成的系统提示词前缀:")
    print("=" * 50)
    print(system_prompt[:1000])

五、记忆写入与更新机制

5.1 记忆写入时机

配置 AI 在特定时机自动写入记忆:

触发条件 记忆类型 写入内容示例
用户明确要求记住 用户画像/项目背景 "记住我是全栈工程师,擅长Python"
用户纠正AI行为 反馈记录 "文档结构需要先确认再写作"
项目状态变更 项目背景 "项目进入测试阶段,版本v1.2"
重要决策确认 参考信息 "决定使用SQLite作为记忆数据库"

5.2 记忆更新策略

# memory_updater.py - 记忆更新辅助函数 

def update_user_profile(profile_data):
    """更新用户画像记忆"""
    profile_path = Path("~/.openclaw/workspace/memory/user_profile.md").expanduser()
    
    # 读取现有画像
    if profile_path.exists():
        with open(profile_path, 'r', encoding='utf-8') as f:
            content = f.read()
        
        # 解析并更新YAML front matter
        if content.startswith('---'):
            parts = content.split('---', 2)
            front_matter = yaml.safe_load(parts[1]) if len(parts) > 1 else {}
            front_matter.update(profile_data)
            front_matter['last_updated'] = datetime.now().strftime('%Y-%m-%d')
            
            # 重新写入
            new_content = f"---
{yaml.dump(front_matter, allow_unicode=True)}---
{parts[2] if len(parts) > 2 else ''}"
            with open(profile_path, 'w', encoding='utf-8') as f:
                f.write(new_content)
    else:
        # 创建新的用户画像
        front_matter = {
            'name': '用户画像',
            'type': 'user',
            'created': datetime.now().strftime('%Y-%m-%d'),
            'last_updated': datetime.now().strftime('%Y-%m-%d')
        }
        front_matter.update(profile_data)
        
        content = f"---
{yaml.dump(front_matter, allow_unicode=True)}---

"
        profile_path.parent.mkdir(parents=True, exist_ok=True)
        with open(profile_path, 'w', encoding='utf-8') as f:
            f.write(content)
    
    print(f"用户画像已更新:{profile_path}")

def add_feedback_memory(feedback_text, category="general"):
    """添加反馈记录"""
    timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
    feedback_file = f"feedback_{category}_{timestamp}.md"
    feedback_path = Path(f"~/.openclaw/workspace/memory/{feedback_file}").expanduser()
    
    front_matter = {
        'name': f'反馈:{category}',
        'type': 'feedback',
        'created': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
        'category': category
    }
    
    content = f"---
{yaml.dump(front_matter, allow_unicode=True)}---

{feedback_text}"
    
    with open(feedback_path, 'w', encoding='utf-8') as f:
        f.write(content)
    
    # 更新MEMORY.md索引
    update_memory_index(feedback_file, f"反馈:{category}", f"用户关于{category}的反馈")
    
    print(f"反馈记录已添加:{feedback_file}")

六、记忆系统维护最佳实践

6.1 定期维护任务

  1. 每月记忆检查

    • 验证所有记忆文件的有效性
    • 更新过时的项目状态
    • 清理无效的外部引用链接
  2. 记忆质量评估

    • 检查记忆是否被频繁使用
    • 评估记忆的准确性和相关性
    • 合并相似或重复的记忆条目
  3. 备份与版本控制

    # 使用Git进行记忆版本管理
    cd ~/.openclaw/workspace/memory/
    git add .
    git commit -m "更新记忆系统 - $(date +%Y%m%d)"
    git push origin main
    

6.2 故障排查指南

问题现象 可能原因 解决方案
AI不加载记忆 MEMORY.md格式错误 检查索引文件格式,确保使用标准Markdown列表
记忆内容混乱 记忆文件没有YAML头 为所有记忆文件添加标准的YAML Front Matter
加载速度慢 记忆文件过大 拆分大文件,保持每个记忆文件<10KB
记忆冲突 多个记忆文件内容矛盾 建立记忆优先级规则,以最新确认为准

6.3 性能优化建议

  1. 记忆分块加载:只加载与当前任务相关的记忆
  2. 缓存机制:对频繁使用的记忆进行内存缓存
  3. 懒加载:仅在需要时加载详细的记忆内容
  4. 增量更新:只更新发生变化的部分,减少IO操作

七、高级配置:


参考来源

 

Logo

小龙虾开发者社区是 CSDN 旗下专注 OpenClaw 生态的官方阵地,聚焦技能开发、插件实践与部署教程,为开发者提供可直接落地的方案、工具与交流平台,助力高效构建与落地 AI 应用

更多推荐