OpenClaw 源码深度解析(三):记忆篇 — 会话持久化、压缩与记忆系统

OpenClaw v2026.2.25 | Node.js 22+ | TypeScript ESM


引言

一个 AI Agent 如果只能记住当前对话,那它就是个玩具。真正有用的 Agent 需要长期记忆——记住你是谁、上次聊了什么、你的偏好和习惯。

OpenClaw 的记忆系统是整个架构中最精巧的部分。它不是一个简单的数据库,而是一个三层文件系统 + 智能压缩 + 记忆刷盘的复合体系。本文深入解析这个系统——从 jsonl transcript 的树结构到 auto-compaction 的触发机制,从 MEMORY.md 的蒸馏逻辑到 cache-TTL 上下文裁剪。


一、三层记忆架构

OpenClaw 的记忆不是单一存储,而是三层各有分工的体系:

┌─────────────────────────────────────────────────────┐
│  Layer 1: MEMORY.md — 精选长期记忆                    │
│  ├── 核心事实、偏好、决策                             │
│  ├── 只在主会话加载 (安全考虑)                        │
│  └── 由 daily notes 蒸馏而来                         │
├─────────────────────────────────────────────────────┤
│  Layer 2: memory/YYYY-MM-DD.md — 每日记忆日志         │
│  ├── 当天事件的原始记录 (append-only)                 │
│  ├── 不自动注入 prompt                                │
│  └── Agent 用 read 工具按需读取                       │
├─────────────────────────────────────────────────────┤
│  Layer 3: <sessionId>.jsonl — 对话记录               │
│  ├── 完整的对话树 (user/assistant/tool messages)      │
│  ├── Agent Loop 的"工作记忆"                         │
│  └── 超过上限时自动压缩                               │
└─────────────────────────────────────────────────────┘

类比

  • Layer 3 (jsonl) = 你的短期工作记忆(正在处理的事)
  • Layer 2 (daily md) = 你的日记本(今天发生了什么)
  • Layer 1 (MEMORY.md) = 你的长期知识(你知道的重要事实)

二、Layer 3:Transcript (对话记录)

2.1 文件格式

Transcript 是 JSONL 格式——每行一个 JSON 对象,支持增量写入,不需要解析整个文件就能追加新内容。

// 第一行: session header
{"type":"session","id":"sess_20260310_abc","cwd":"/home/user/.openclaw/workspace","timestamp":"2026-03-10T15:00:00Z","parentSession":null}

// 第二行+: 消息 (树结构)
{"id":"msg_001","parentId":"sess_20260310_abc","role":"user","content":"帮我查一下天气","timestamp":"2026-03-10T15:00:01Z"}

{"id":"msg_002","parentId":"msg_001","role":"assistant","content":"好的,我来帮你查。","toolCalls":[{"id":"call_1","name":"web_fetch","input":{"url":"https://wttr.in/Beijing?format=j1"}}],"timestamp":"2026-03-10T15:00:02Z"}

{"id":"msg_003","parentId":"msg_002","role":"tool","name":"web_fetch","toolCallId":"call_1","content":"北京 晴 15-25°C 风力3级","timestamp":"2026-03-10T15:00:03Z"}

{"id":"msg_004","parentId":"msg_003","role":"assistant","content":"今天北京晴天,气温15-25°C,风力3级,适合外出活动。","timestamp":"2026-03-10T15:00:04Z"}

2.2 树结构设计

每条消息有 idparentId,形成一棵对话树:

sess_20260310_abc (root)
    └── msg_001 (user: 帮我查一下天气)
            └── msg_002 (assistant: 好的... [tool_call: web_fetch])
                    └── msg_003 (tool: 天气数据)
                            └── msg_004 (assistant: 今天北京晴天...)

为什么是树而不是列表? 因为 OpenClaw 支持会话分支。你可以从某个历史节点 fork 出新分支,探索不同的对话路径。这在 coding agent 场景中特别有用——"试试另一个方案"时不需要从零开始。

2.3 SessionManager

Pi SDK 的 SessionManager 负责读写这些文件:

// Pi SDK 内部 (简化)
class SessionManager {
  private file: string;
  private entries: Map<string, SessionEntry>;  // id → entry

  static open(file: string): SessionManager {
    // 1. 读取 jsonl 文件
    const lines = readFileSync(file, 'utf-8').split('\n');
    // 2. 解析每一行为 SessionEntry
    // 3. 构建 id → entry 映射和 parentId 索引
    return new SessionManager(file, entries);
  }

  append(entry: SessionEntry): void {
    // 追加写入 (原子操作)
    appendFileSync(this.file, JSON.stringify(entry) + '\n');
    this.entries.set(entry.id, entry);
  }

  getHistory(): SessionEntry[] {
    // 从 root 开始,按 parentId 链遍历,返回有序的消息列表
    return this.traverseTree(this.rootId);
  }
}

2.4 SessionManager 缓存

频繁打开和解析 jsonl 文件很浪费。OpenClaw 缓存了 SessionManager 实例:

// src/agents/pi-embedded-runner/session-manager-cache.ts
const cache = new Map<string, CacheEntry>();

interface CacheEntry {
  manager: SessionManager;
  lastAccess: number;
  refCount: number;
}

function getSessionManager(file: string): SessionManager {
  const entry = cache.get(file);
  if (entry) {
    entry.lastAccess = Date.now();
    entry.refCount++;
    return entry.manager;
  }

  const manager = SessionManager.open(file);
  cache.set(file, { manager, lastAccess: Date.now(), refCount: 1 });
  return manager;
}

function releaseSessionManager(file: string): void {
  const entry = cache.get(file);
  if (entry) {
    entry.refCount--;
    if (entry.refCount <= 0) {
      cache.delete(file);
    }
  }
}

缓存有 TTL(5 分钟),超时自动释放。这样同一 session 短时间内收到多条消息时,不需要重复解析。

2.5 损坏修复

jsonl 文件可能损坏(进程崩溃时写到一半)。OpenClaw 有自动修复机制:

// src/agents/session-file-repair.ts
function repairSessionFileIfNeeded(file: string): void {
  const lines = readFileSync(file, 'utf-8').split('\n');
  const valid: string[] = [];
  let repaired = false;

  for (const line of lines) {
    if (!line.trim()) continue;
    try {
      JSON.parse(line);
      valid.push(line);
    } catch {
      // 跳过无效行 (损坏的 JSON)
      repaired = true;
    }
  }

  if (repaired) {
    // 备份原文件
    copyFileSync(file, `${file}.bak.${Date.now()}`);
    // 写入修复后的内容
    writeFileSync(file, valid.join('\n') + '\n');
  }
}

三、Session Store (会话元数据)

3.1 sessions.json

除了 transcript 文件,OpenClaw 还维护一个 sessions.json,存储每个 session 的元数据

{
  // sessionKey → SessionEntry
  "agent:main:telegram:user:123456": {
    "sessionId": "sess_20260310_abc",
    "updatedAt": 1709984400000,
    "chatType": "direct",
    "provider": "telegram",
    "displayName": "张三",
    "inputTokens": 15230,
    "outputTokens": 3840,
    "totalTokens": 19070,
    "contextTokens": 45000,
    "thinkingLevel": 2,
    "modelOverride": null,
    "compactionCount": 3,
    "memoryFlushAt": 1709980800000,
    "memoryFlushCompactionCount": 3
  },
  "agent:main:telegram:group:-1009876543210": {
    "sessionId": "sess_20260310_def",
    "updatedAt": 1709983500000,
    "chatType": "group",
    "compactionCount": 0
  }
}

为什么需要两层?

sessions.json .jsonl transcript
用途 快速查找 session 状态 存储完整对话内容
大小 小 (几百 KB) 大 (可达数 MB)
读写频率 每次消息更新 每次消息追加
可编辑 ✅ 安全可编辑 ⚠️ 不建议手动编辑

3.2 自动维护

sessions.json 有自动清理机制,防止无限膨胀:

// 配置
interface MaintenanceConfig {
  mode: 'warn' | 'enforce';      // warn=只报告, enforce=自动清理
  pruneAfter: string;             // 默认 '30d' — 30天不活跃的 session
  maxEntries: number;             // 默认 500 — 最多保留多少 session
  rotateBytes: number;            // 默认 10MB — 文件超过多大时轮转
  maxDiskBytes?: number;          // 总磁盘预算 (可选)
  highWaterBytes?: number;        // 清理目标 (默认 maxDiskBytes * 80%)
}

// 清理顺序
// 1. 删除最老的归档/orphan transcript 文件
// 2. 如果还不够,驱逐最老的 session entry + 对应 transcript
// 3. 直到磁盘使用低于 highWaterBytes

3.3 Session 生命周期

新消息到达
    │
    ▼
sessionKey 是否存在于 sessions.json?
    ├── 否 → 创建新 entry,分配新 sessionId
    └── 是 → 检查是否需要重置:
        │
        ├── Daily Reset (默认每天凌晨 4:00)
        │   └── 到时间后第一条消息触发新 session
        │
        ├── Idle Reset (配置 session.reset.idleMinutes)
        │   └── 超过空闲时间后第一条消息触发新 session
        │
        └── 都不需要 → 复用现有 session

Daily Reset 和 Idle Reset 是惰性触发的——不是定时器主动重置,而是下一条消息到达时检查条件。


四、Auto-Compaction (自动压缩)

这是记忆系统最核心的机制。随着对话越来越长,context tokens 会逼近模型的上限。如果不处理,LLM 会报 context overflow 错误。

4.1 触发条件

Auto-compaction 由 Pi SDK 决定触发,有两种场景:

// 场景 1: 溢出恢复
// LLM 返回 context overflow 错误 → 自动压缩 → 用压缩后的历史重试

// 场景 2: 阈值维护
// 每次成功 turn 后检查:
if (contextTokens > contextWindow - reserveTokens) {
  // 触发压缩
  // reserveTokens 默认 16384 (为下一轮留余量)
}

4.2 压缩过程

压缩前:
┌───────────────────────────────────────────┐
│ [系统消息]                                  │
│ [msg_001] 用户: 帮我查天气                 │
│ [msg_002] 助手: 好的 [tool_call]           │
│ [msg_003] 工具: 天气数据                   │
│ [msg_004] 助手: 今天晴天...                │
│ [msg_005] 用户: 那明天呢                   │
│ [msg_006] 助手: 好的 [tool_call]           │
│ [msg_007] 工具: 明天数据                   │
│ [msg_008] 助手: 明天多云...                │
│ [msg_009] 用户: 谢谢                       │
│ [msg_010] 助手: 不客气                     │
└───────────────────────────────────────────┘

              ↓ 压缩 (LLM 生成摘要)

压缩后:
┌───────────────────────────────────────────┐
│ [系统消息]                                  │
│ [compaction] 对话摘要: 用户询问了今明两天   │
│   的北京天气。今天晴15-25°C,明天多云12-20°C│
│ [msg_009] 用户: 谢谢                       │
│ [msg_010] 助手: 不客气                     │
└───────────────────────────────────────────┘

压缩的本质是:让 LLM 把旧对话总结成一段摘要,然后用摘要替换旧消息。新消息保持原样,因为它们最可能是接下来对话的上下文。

4.3 Compaction Safeguard Extension

OpenClaw 没有完全信任 Pi SDK 的默认压缩行为。它注入了一个压缩保护扩展

// src/agents/pi-extensions/compaction-safeguard.ts
// 为压缩提供额外的安全策略

// 1. 自适应 token 预算
//    根据历史大小动态调整压缩摘要的 token 预算
function adaptiveTokenBudget(totalTokens: number, contextWindow: number): number {
  // 历史越长,摘要可以越长 (因为有更多内容要保留)
  const ratio = totalTokens / contextWindow;
  return Math.min(
    contextWindow * 0.1,       // 最多用 10% 的上下文窗口
    2000 + ratio * 3000        // 基础 2000 + 按比例增长
  );
}

// 2. 工具失败摘要
//    压缩时额外保留工具失败的信息 (避免重蹈覆辙)
function includeToolFailureSummaries(entries: SessionEntry[]): string {
  const failures = entries.filter(e =>
    e.role === 'tool' && e.content.startsWith('Error:')
  );
  if (!failures.length) return '';
  return '\n[重要: 以下工具调用曾失败]\n' +
    failures.map(f => `- ${f.name}: ${f.content}`).join('\n');
}

// 3. 文件操作摘要
//    保留关键文件变更记录
function includeFileOperationSummaries(entries: SessionEntry[]): string {
  const fileOps = entries.filter(e =>
    e.toolName === 'write' || e.toolName === 'edit'
  );
  if (!fileOps.length) return '';
  return '\n[文件变更记录]\n' +
    fileOps.map(f => `- ${f.toolName}: ${f.params.path}`).join('\n');
}

这个设计很有洞察力:普通的压缩会丢失"失败经验"。如果 Agent 之前尝试某个方法失败了,压缩后它可能会再次尝试同样的方法。Safeguard 扩展确保失败信息被保留。

4.4 reserveTokens 安全下限

// src/agents/pi-settings.ts
function ensurePiCompactionReserveTokens(config: Config): number {
  const configured = config.agents?.defaults?.compaction?.reserveTokens ?? 16384;
  const floor = config.agents?.defaults?.compaction?.reserveTokensFloor ?? 20000;

  // 如果配置值低于下限,强制提升
  return Math.max(configured, floor);
}

为什么需要安全下限?因为压缩不是瞬间完成的。如果 reserveTokens 太小,Agent 在压缩之前的最后一次运行就可能触发 overflow。留足 20000 tokens 的余量,确保有足够空间完成"记忆刷盘→压缩"的流程。


五、Pre-Compaction Memory Flush (压缩前记忆刷盘)

这是 OpenClaw 记忆系统最精妙的设计之一。

问题

当 auto-compaction 发生时,旧对话会被摘要替换。摘要中会丢失很多细节。如果 Agent 之前了解到的用户偏好、重要决策、待办事项没有被持久化到 MEMORY.md,它们就会永久丢失。

解决方案

在压缩之前,OpenClaw 注入一次静默的 Agent 运行,让 Agent 把重要信息写到文件里:

// 触发条件
// 当 contextTokens 超过 "软阈值" (softThresholdTokens)
// 但还没到 Pi SDK 的硬压缩阈值

if (sessionEntry.contextTokens > contextWindow - reserveTokens - softThresholdTokens) {
  // 检查本压缩周期是否已经 flush 过
  if (sessionEntry.memoryFlushCompactionCount !== sessionEntry.compactionCount) {
    await runMemoryFlush(params);
    sessionEntry.memoryFlushAt = Date.now();
    sessionEntry.memoryFlushCompactionCount = sessionEntry.compactionCount;
  }
}

Flush 的实现

async function runMemoryFlush(params: FlushParams): Promise<void> {
  // 发送一条特殊的用户消息,要求 Agent 保存记忆
  const flushPrompt = params.config.agents?.defaults?.compaction?.memoryFlush?.prompt
    ?? '[System] Context is nearing compaction threshold. Review recent conversation and write any important facts, decisions, preferences, or open loops to memory/YYYY-MM-DD.md and update MEMORY.md if needed. Reply with NO_REPLY when done.';

  // 额外的系统提示
  const flushSystemPrompt = params.config.agents?.defaults?.compaction?.memoryFlush?.systemPrompt
    ?? 'This is a silent housekeeping turn. Write important context to disk. Start your reply with NO_REPLY.';

  // 运行一次完整的 Agent 运行 (但不投递给用户)
  await runEmbeddedPiAgent({
    ...params,
    prompt: flushPrompt,
    appendSystemPrompt: flushSystemPrompt,
    onBlockReply: (payload) => {
      // 以 NO_REPLY 开头 → 不发送给用户
      if (payload.text.startsWith('NO_REPLY')) return;
    },
  });
}

时序图

contextTokens 增长
    │
    ▼
contextWindow - reserveTokens - softThreshold  (默认: 上限前 4000 tokens)
    │
    ├── 触发 Memory Flush!
    │   ├── Agent 静默运行
    │   ├── Agent 用 write 工具更新 memory/2026-03-10.md
    │   ├── Agent 用 edit 工具更新 MEMORY.md
    │   ├── Agent 回复 NO_REPLY
    │   └── 用户完全不知道发生了这件事
    │
    ▼
contextWindow - reserveTokens  (Pi SDK 硬压缩阈值)
    │
    ├── 触发 Auto-Compaction!
    │   ├── 旧对话被 LLM 摘要替换
    │   ├── 但重要信息已经在文件里了
    │   └── 下次 Agent 启动时 read MEMORY.md 恢复记忆
    │
    ▼
contextWindow  (溢出)
    └── 不会到这里,因为已经压缩过了

这个设计解决了 AI Agent 长期运行的核心难题:如何在无限对话中保持重要信息不丢失。


六、Cache-TTL Context Pruning (缓存感知上下文裁剪)

这是 OpenClaw 在 token 成本优化上的另一个巧妙设计。

问题

LLM provider 的 prompt caching 有 TTL(通常是 1 小时)。如果 session 超过 1 小时没有活动,缓存过期了。下一次请求时,整个 prompt 需要重新缓存(付 cacheWrite 费用)。

但更糟的是:旧的 tool_result 已经没用了(比如 1 小时前查的天气),但它们仍然占据 context,导致:

  1. 缓存命中失败,全部重新缓存
  2. 旧的 tool_result 占据空间,可用 token 变少

解决方案

当 session 空闲超过 cache TTL 后,主动裁剪旧的 tool_result,然后重新缓存精简后的上下文:

// src/agents/pi-extensions/context-pruning.ts
function pruneExpiredToolResults(params: PruneParams): PrunedResult {
  const now = Date.now();
  const ttlMs = parseTTL(params.config.contextPruning.ttl); // e.g., '1h'

  const history = params.sessionManager.getHistory();
  const pruned: SessionEntry[] = [];
  let savedTokens = 0;

  for (const entry of history) {
    // 裁剪超过 TTL 的 tool_result
    if (entry.role === 'tool' && isToolPrunable(entry)) {
      const age = now - entry.timestamp;
      if (age > ttlMs) {
        savedTokens += estimateTokens(entry.content);
        // 替换为简短摘要而不是完全删除
        pruned.push({
          ...entry,
          content: `[tool result pruned: ${entry.name}, ${Math.round(age / 60000)}min ago]`,
        });
        continue;
      }
    }
    pruned.push(entry);
  }

  return { pruned, savedTokens };
}

Heartbeat 保热

配合 heartbeat,可以让缓存永远不过期

# 心跳间隔略小于 cache TTL
agents:
  defaults:
    heartbeat:
      every: "55m"  # cache TTL 是 1h,55m 发一次心跳保持缓存活跃

这样做的效果:

  • 正常活跃 session:缓存一直 warm,cacheRead 费用
  • 空闲超过 TTL 的 session:裁剪旧数据后重新缓存,减少后续 cacheWrite
  • 长期空闲 session:持续裁剪,保持 context 精简

七、Session Reset 策略

7.1 Daily Reset

// 默认每天凌晨 4:00 (Gateway 主机本地时间)
function checkDailyReset(entry: SessionEntry, config: Config): boolean {
  const resetHour = config.session?.reset?.dailyHour ?? 4;

  const lastDate = new Date(entry.updatedAt);
  const now = new Date();

  // 最后活跃日期 < 今天 AND 当前小时 >= resetHour
  return (
    lastDate.toDateString() !== now.toDateString() &&
    now.getHours() >= resetHour
  );
}

Daily Reset 的设计意图是每天一个全新的对话上下文。这避免了 context 无限膨胀,也让 Agent 有一个"清新的开始"——同时仍然可以通过 MEMORY.md 恢复重要信息。

7.2 Idle Reset

function checkIdleReset(entry: SessionEntry, config: Config): boolean {
  const idleMinutes = config.session?.reset?.idleMinutes;
  if (!idleMinutes) return false;

  const elapsed = Date.now() - entry.updatedAt;
  return elapsed > idleMinutes * 60 * 1000;
}

7.3 重置后的连续性

重置只创建新 session,不会删除旧数据

sess_20260310_abc  (昨天的 transcript, 保留)
sess_20260311_def  (今天的 transcript, 新建)

旧 transcript 仍然在磁盘上,只是不再作为默认上下文加载。Agent 可以通过 /context 命令查看,或者通过 memory 工具回顾。


八、NO_REPLY 静默机制

OpenClaw 有一个特殊的约定:如果 Agent 的回复以 NO_REPLY 开头,这条消息不会投递给用户

这在多个场景中使用:

  1. Memory Flush — 压缩前刷盘,用户不应看到
  2. Heartbeat — 心跳检查的输出,不需要通知用户
  3. Cron 任务 — 后台定时任务的内部处理
  4. Session Spawn — 子 agent 的内部运行
// 投递层检查
function shouldDeliverToUser(text: string): boolean {
  return !text.trim().startsWith('NO_REPLY');
}

// 流式阶段也做了优化: 如果第一个 chunk 是 NO_REPLY,
// 不发送 typing indicator,避免用户看到"正在输入"又没消息

九、记忆系统的数据流全景

┌─────────────────────────────────────────────────────────────┐
│                     用户发消息                                │
└──────────────────────────┬──────────────────────────────────┘
                           │
                           ▼
┌─────────────────────────────────────────────────────────────┐
│  Session 初始化                                              │
│  ├── 读取 sessions.json → 找到 sessionKey                   │
│  ├── 检查 daily/idle reset → 可能创建新 session              │
│  ├── 打开 .jsonl transcript → 恢复对话树                     │
│  ├── 读取 MEMORY.md (仅主会话)                               │
│  └── 注入 workspace 文件到 system prompt                     │
└──────────────────────────┬──────────────────────────────────┘
                           │
                           ▼
┌─────────────────────────────────────────────────────────────┐
│  Agent Loop 执行                                             │
│  ├── LLM 根据历史 + 新消息做出决策                            │
│  ├── 可能调用 read/edit/write 工具                           │
│  │   └── write memory/2026-03-10.md → 记录事件              │
│  │   └── edit MEMORY.md → 更新长期记忆                       │
│  └── 回复用户                                                │
└──────────────────────────┬──────────────────────────────────┘
                           │
                           ▼
┌─────────────────────────────────────────────────────────────┐
│  持久化                                                     │
│  ├── SessionManager.append() → 追加到 .jsonl                │
│  ├── 更新 sessions.json (tokens, timestamp)                 │
│  └── 检查 compaction 条件                                    │
│       │                                                      │
│       ├── contextTokens > 软阈值?                            │
│       │   └── 触发 Memory Flush!                             │
│       │       ├── Agent 静默运行                              │
│       │       ├── 重要信息 → memory/*.md + MEMORY.md          │
│       │       └── 回复 NO_REPLY                              │
│       │                                                      │
│       └── contextTokens > 硬阈值?                            │
│           └── 触发 Auto-Compaction!                          │
│               ├── LLM 生成对话摘要                            │
│               ├── 旧消息替换为摘要                            │
│               ├── Safeguard: 保留失败记录                     │
│               └── 新消息保持原样                              │
└──────────────────────────┬──────────────────────────────────┘
                           │
                           ▼
┌─────────────────────────────────────────────────────────────┐
│  空闲期                                                     │
│  ├── Cache TTL 过期? → Context Pruning (裁剪旧 tool_result)  │
│  ├── Heartbeat? → 保持缓存 warm (可选)                       │
│  └── Daily Reset? → 下次消息创建新 session                   │
└─────────────────────────────────────────────────────────────┘

十、设计亮点总结

  1. 三层记忆,各司其职 — 短期(jsonl) + 日记(daily md) + 长期(MEMORY.md),类似人类的记忆系统
  2. 树结构 transcript — 支持 fork/分支,不是简单的追加日志
  3. Pre-Compaction Memory Flush — 压缩前强制刷盘,防止重要信息丢失。这是整个系统最有创意的设计
  4. Compaction Safeguard — 压缩时保留失败记录,防止 Agent 重蹈覆辙
  5. Cache-TTL Pruning — 主动裁剪过期工具结果,配合 heartbeat 保热,优化 token 成本
  6. NO_REPLY 静默机制 — 后台任务不干扰用户,一个约定解决了多种场景
  7. 惰性 Session Reset — 不主动重置,下条消息时检查,简化状态管理
  8. 自动维护 — sessions.json 自动清理过期条目和磁盘预算控制

系列完结

三篇文章覆盖了 OpenClaw 最核心的三条代码路径:

篇章 核心问题 关键模块
规划篇 消息如何变成一次 Agent 运行 路由、Session 初始化、System Prompt 构建、工具准备
执行篇 Agent Loop 如何调用 LLM 和工具 流式调用、工具执行、分块响应、错误恢复
记忆篇 如何持久化和管理长期记忆 Transcript、Compaction、Memory Flush、Context Pruning

OpenClaw 的架构有几个贯穿始终的设计哲学:

  • 文件即状态 — 用文件系统做持久化,简单、透明、可 debug
  • 渐进式复杂度 — 简单场景简单处理(斜杠命令快速通道),复杂场景才走完整链路
  • 防护层叠 — 多层安全机制(Tool Policy、AbortSignal、Compaction Safeguard)
  • 成本意识 — Cache-TTL Pruning、Heartbeat 保热、History Limiting 都是为了控制 token 成本

希望这个系列对你理解 OpenClaw 的架构有帮助。如果你想进一步深入某个模块,或者想用 Spring Boot 实现其中某个子系统,随时聊。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐