openclawmemorydesign-principlesagenticarchitecture

从 Memory 子系统看 OpenClaw 的架构设计哲学

核心设计原则

mindmap
  root((OpenClaw Design))
    Agentic First
      AI 自主决策
      非规则驱动
      NO_REPLY 静默
    Explicit over Implicit
      Tool-based 检索
      非自动注入
      可控可观测
    Layered Architecture
      职责分离
      渐进增强
      故障降级
    Robust Engineering
      原子操作
      可回滚
      防抖节流

一、Agentic 设计:让 AI 自主决策

对比:规则驱动 vs Agentic

flowchart TB
    subgraph "规则驱动(反模式)"
        R1[检测关键词 X] --> R2[自动写入记忆]
        R3[检测代码块] --> R4[自动写入记忆]
        
        R1 --> P1[问题: 僵化]
        R3 --> P2[问题: 容易出错]
    end
    
    subgraph "Agentic(正模式)"
        A1[上下文快满] --> A2[触发 Flush]
        A2 --> A3[AI 判断价值]
        A3 --> A4{值得记录?}
        A4 -->|是| A5[写入记忆]
        A4 -->|否| A6[NO_REPLY]
        
        A3 --> B1[优势: 灵活]
        A3 --> B2[优势: 智能]
    end

Memory Flush 的 Agentic 设计

场景: 长会话上下文即将被压缩

传统方案:

# 反模式:规则驱动
if "important" in message or "decision" in message:
    save_to_memory(message)

OpenClaw 方案:

// 正模式:Agentic
async function memoryFlush() {
  // 1. 触发条件:上下文快满
  if (totalTokens > threshold) {
    // 2. 给 AI 一个特殊 Turn
    const prompt = `
      Pre-compaction memory flush.
      Store durable memories now (use memory/YYYY-MM-DD.md).
      If nothing to store, reply with NO_REPLY.
    `;
    
    // 3. AI 自主决定写什么
    const response = await agent.generate(prompt);
    
    if (response !== "NO_REPLY") {
      writeToMemory(response);
    }
    // 4. NO_REPLY = 静默跳过,不影响用户体验
  }
}

关键洞察:

  • AI 比规则更懂什么值得记住
  • NO_REPLY 让”不操作”也是有效决策
  • 非侵入式设计,不打扰正常对话

二、显式优于隐式:Tool-based 架构

对比:自动注入 vs Tool 调用

sequenceDiagram
    participant U as User
    participant A as Agent
    participant M as Memory
    
    rect rgb(255, 200, 200)
        Note over U,M: 自动注入(反模式)
        U->>A: "还记得我们讨论的路由器吗?"
        Note over A: 系统自动加载相关记忆
        A->>M: 隐式查询
        M->>A: 注入 Prompt
        A->>U: "记得,你配置了 Omada..."
    end
    
    rect rgb(200, 255, 200)
        Note over U,M: Tool-based(正模式)
        U->>A: "还记得我们讨论的路由器吗?"
        Note over A: System Prompt 要求先搜索
        A->>M: memory_search("路由器配置")
        M->>A: 返回结果
        A->>U: "记得,你配置了 Omada..."
    end

Tool-based 的优势

1. 可控性:

// System Prompt 强制要求
"Before answering anything about prior work, decisions, dates, 
people, preferences, or todos: run memory_search..."

2. 可观测性:

  • 每次记忆访问都记录在日志
  • 可以分析 Agent 的检索策略
  • 调试时清楚知道用了哪些上下文

3. 成本可控:

  • 不每次都加载全部记忆
  • 按需检索,减少 Token 消耗

4. 准确性:

  • 显式检索比隐式注入更精确
  • Agent 知道自己在找什么

三、分层架构:职责分离与渐进增强

Memory 系统的五层架构

flowchart TB
    subgraph "Layer 5: Interface"
        L5[memory_search Tool
            memory_get Tool]
    end
    
    subgraph "Layer 4: Routing"
        L4[SearchManager
            Backend Router
            Fallback Logic]
    end
    
    subgraph "Layer 3: Implementation"
        L3a[Builtin Backend
            MemoryIndexManager]
        L3b[QMD Backend
            QmdMemoryManager]
    end
    
    subgraph "Layer 2: Abstraction"
        L2[EmbeddingProviders
            OpenAI/Gemini/Local]
    end
    
    subgraph "Layer 1: Storage"
        L1[(SQLite + FTS5)]
    end
    
    L5 --> L4
    L4 --> L3a
    L4 --> L3b
    L3a --> L2
    L3b --> L2
    L2 --> L1

每层的设计意图

层级职责设计决策
ToolLLM 接口统一封装,参数校验
Routing后端选择故障降级,配置切换
Backend核心逻辑双实现,渐进采用
Embedding向量化多 Provider,自动回退
Storage持久化SQLite,零依赖

渐进增强策略

flowchart LR
    A[MVP] --> B[增强]
    B --> C[完整]
    
    A1[SQLite + OpenAI] --> B1[+ Hybrid Search]
    B1 --> C1[+ QMD Backend]
    
    A2[向量搜索] --> B2[+ BM25 + MMR]
    B2 --> C2[+ Query Expansion]

设计原则: 基础版本可用,高级功能可选,不强制复杂性。

四、鲁棒性工程:故障处理与恢复

安全重建机制

flowchart TB
    A[Start] --> B{需要重建?}
    B -->|是| C[创建 tmp DB]
    C --> D[在 tmp 中重建]
    D --> E[关闭原 DB]
    E --> F[原 -> backup]
    F --> G[tmp -> 新]
    G --> H[删除 backup]
    H --> I[完成]
    
    F -.->|失败| R[Rollback]
    G -.->|失败| R
    R -->|恢复| J[backup -> 原]
    
    B -->|否| K[增量更新]

关键点:

  • 原子性: 文件重命名是原子操作
  • 零停机: 读旧库,写新库
  • 可回滚: 任何步骤失败都能恢复

故障降级

// search-manager.ts
async search(query: string) {
  try {
    if (this.backend === "qmd") {
      return await this.qmdManager.search(query);
    }
  } catch (err) {
    // QMD 失败,记录日志
    log.warn("qmd failed; switching to builtin");
    
    // 切换到 Builtin
    this.fallbackToBuiltin();
  }
  
  // 使用 Builtin 兜底
  return this.builtinManager.search(query);
}

设计原则: 优雅降级,保证核心功能可用。

防抖与节流

文件监控防抖:

// 双重防抖
watcher = chokidar.watch(patterns, {
  awaitWriteFinish: {
    stabilityThreshold: 1500,  // 第一层: 写入完成防抖
    pollInterval: 100
  }
});
 
markDirty() {
  this.dirty = true;
  setTimeout(() => {      // 第二层: 事件聚合防抖
    if (this.dirty) this.sync();
  }, 1500);
}

为什么重要?

  • 避免文件写入过程中触发同步
  • 批量处理文件变更(如 git checkout)
  • 减少不必要的索引更新

五、分层存储:信息价值的生命周期

三层记忆架构

flowchart TB
    subgraph "Session Memory"
        S1[JSON Lines] --> S2[临时]
        S2 --> S3[可能丢失]
    end
    
    subgraph "Daily Memory"
        D1[memory/2026-01-15.md] --> D2[短期]
        D2 --> D3[自动创建]
    end
    
    subgraph "Permanent Memory"
        P1[MEMORY.md] --> P2[长期]
        P2 --> P3[人工精选]
    end
    
    S3 -.->|价值提炼| D1
    D2 -.->|总结沉淀| P1

信息衰减策略

Session:    ████████████████████  临时,当前会话
               ↓ Flush
Daily:      ████████████████░░░░  短期,按日期组织  
               ↓ 总结
Permanent:  ██████████░░░░░░░░░░  长期,精选知识

设计意图: 不是所有信息都值得永久保存,分层衰减减少噪声。

六、缓存策略:性能优化的艺术

两级缓存设计

flowchart TB
    subgraph "L1: Memory"
        M[LRU Cache] -->|进程内| A[Fastest]
        M -->|LRU 淘汰| D[Drop]
    end
    
    subgraph "L2: SQLite"
        S[embedding_cache] -->|持久化| B[Fast]
        S -->|maxEntries| E[Evict]
    end
    
    subgraph "Source"
        P[Provider API] -->|Slowest| C[Expensive]
    end
    
    A -->|miss| B
    B -->|miss| C
    C -->|write| B
    C -->|write| A

为什么有效?

  • 命中率 > 80%(典型场景)
  • 成本降低 90%+
  • 搜索速度提升 10x+

失效策略: 基于内容 hash,内容不变永不过期。

七、设计决策权衡

关键决策回顾

决策选择理由代价
后端架构Builtin + QMD渐进采用,故障降级维护两套代码
向量存储JSON in SQLite简单,无依赖查询性能
检索方式Tool-based可控,可观测Agent 需显式调用
写入策略Agentic Flush智能,灵活实现复杂
缓存策略Hash-based永不过期存储增长

取舍的艺术

性能 vs 简单性:

  • 选择: JSON 存储而非专用向量数据库
  • 理由: 简单性优先,性能通过缓存弥补

自动化 vs 可控性:

  • 选择: Tool-based 而非自动注入
  • 理由: 可控性优先,AI 更懂何时检索

智能 vs 确定性:

  • 选择: Agentic 而非规则驱动
  • 理由: 智能优先,接受一定的非确定性

八、给 dm_claw 的启示

值得借鉴的模式

  1. Agentic 设计: 让 AI 自主决策写入内容
  2. Tool-based 检索: 显式调用,可控可观测
  3. 分层架构: 5 层分离,职责清晰
  4. 安全重建: 原子操作,失败可回滚
  5. 双后端: 默认可用,高级功能可选
  6. 两级缓存: 内存 + 持久化,命中率 > 80%

可以改进的地方

  1. 向量存储: Python 可用更高效的方案(如 FAISS)
  2. 查询扩展: Python 生态有更多 IR 库可用
  3. 多模态: 可考虑支持图片、音频记忆

最小可行产品 (MVP)

flowchart LR
    A[SQLite + FTS5] --> B[sentence-transformers]
    B --> C[向量搜索]
    C --> D[Daily Memory]
    D --> E[Agentic Flush]

核心功能:

  • SQLite + Python embedding
  • 向量搜索
  • Daily Memory 写入
  • Flush 触发机制

不需要的功能(初期):

  • Hybrid Search
  • MMR 重排
  • Session Indexing
  • QMD Backend

总结

OpenClaw Memory 系统的设计哲学:

  1. Agentic: 让 AI 做决策,而非硬编码规则
  2. Explicit: 显式 Tool 调用,可控可观测
  3. Layered: 分层架构,渐进增强
  4. Robust: 原子操作,故障降级
  5. Smart: 智能缓存,性能优化

这些原则不仅适用于 Memory 系统,也可以指导其他 AI 系统的设计。


相关文档: 项目概览, Memory 源码分析, 混合搜索技术