欢迎光临
我们一直在努力

OpenClaw 会话管理:状态追踪与上下文深度解析

深入剖析 OpenClaw 会话生命周期、状态追踪机制、上下文继承与隔离策略、跨会话持久化方案,结合实战案例帮助你构建稳定可靠的多会话 AI Agent 系统。


目录

    • 一、引言:为什么会话管理是 Agent 系统的核心
    • 二、会话管理架构:Session / Tool / Agent 三角关系
      • 2.1 核心架构模型
      • 2.2 会话存储结构
      • 2.3 会话元数据时间戳
    • 三、会话状态机制:从路由到生命周期
      • 3.1 消息路由:会话的第一道关卡
      • 3.2 DM 隔离:多用户场景的必修课
      • 3.3 会话生命周期
    • 四、上下文管理策略:继承、隔离与传递
      • 4.1 引导文件注入:每轮对话的起点
      • 4.2 子 Agent 上下文模式:Fork vs Isolated
      • 4.3 跨会话消息传递
      • 4.4 上下文可见性控制
    • 五、跨会话持久化:状态保存与恢复
      • 5.1 会话状态的所有权模型
      • 5.2 记忆文件:跨会话的"长期记忆"
      • 5.3 会话恢复的场景与策略
      • 5.4 压缩后的后继转录
    • 六、会话清理:过期会话回收机制
      • 6.1 自动清理策略
      • 6.2 清理的安全保护
      • 6.3 手动清理与预览
      • 6.4 maxEntries 的高水位缓冲
    • 七、多会话并发:并行会话管理
      • 7.1 并发会话的场景
      • 7.2 子 Agent 深度与工具分配
      • 7.3 并发消息的队列管理
    • 八、上下文压缩与剪枝:让对话持续运转
      • 8.1 Pruning(剪枝):轻量级上下文优化
      • 8.2 Compaction(压缩):语义级上下文缩减
      • 8.3 自动压缩与手动压缩
      • 8.4 压缩配置进阶
    • 九、上下文引擎:可插拔的上下文组装
      • 9.1 上下文引擎的概念
      • 9.2 Legacy 引擎
      • 9.3 插件引擎
      • 9.4 故障隔离
    • 十、实战案例 1:用户会话恢复
      • 10.1 场景描述
      • 10.2 会话状态分析
      • 10.3 恢复流程
      • 10.4 最佳实践
    • 十一、实战案例 2:多任务并行处理
      • 11.1 场景描述
      • 11.2 并行任务架构
      • 11.3 结果收集
      • 11.4 并行管理的注意事项
    • 十二、实战案例 3:会话历史分析
      • 12.1 场景描述
      • 12.2 数据收集
      • 12.3 安全过滤机制
      • 12.4 分析维度
    • 十三、最佳实践与生产建议
      • 13.1 会话配置检查清单
      • 13.2 安全审计
      • 13.3 性能优化建议
      • 13.4 常见问题排查
    • 十四、总结
    • 📚 参考资料

一、引言:为什么会话管理是 Agent 系统的核心

在传统聊天机器人中,会话不过是"一问一答"的简单容器。但当 AI Agent 具备了工具调用、文件操作、子任务派生等能力后,会话就变成了一个复杂的状态机——它承载着上下文记忆、工具权限、运行时变量和跨轮次的协作状态。

OpenClaw 作为一个全功能的 AI Agent 运行时,将会话管理视为系统的核心基础设施。一个设计良好的会话管理体系,需要回答以下关键问题:

  • 🔹 用户发来的消息如何路由到正确的会话?
  • 🔹 多用户环境下,会话如何隔离以避免上下文泄露?
  • 🔹 长时间运行的会话如何管理上下文窗口,防止 token 溢出?
  • 🔹 子 Agent 会话与父会话之间如何传递上下文?
  • 🔹 过期会话如何安全回收,而不丢失关键数据?

本文将从架构设计到实战案例,全面解析 OpenClaw 的会话管理机制。


二、会话管理架构:Session / Tool / Agent 三角关系

2.1 核心架构模型

OpenClaw 的会话管理不是孤立存在的,它建立在 Session(会话)— Tool(工具)— Agent(代理) 三角关系之上。理解这个三角关系,是掌握整个会话体系的前提。

#mermaid-svg-CWDXgVyDZQVfbay8{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-CWDXgVyDZQVfbay8 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-CWDXgVyDZQVfbay8 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-CWDXgVyDZQVfbay8 .error-icon{fill:#552222;}#mermaid-svg-CWDXgVyDZQVfbay8 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-CWDXgVyDZQVfbay8 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-CWDXgVyDZQVfbay8 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-CWDXgVyDZQVfbay8 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-CWDXgVyDZQVfbay8 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-CWDXgVyDZQVfbay8 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-CWDXgVyDZQVfbay8 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-CWDXgVyDZQVfbay8 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-CWDXgVyDZQVfbay8 .marker.cross{stroke:#333333;}#mermaid-svg-CWDXgVyDZQVfbay8 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-CWDXgVyDZQVfbay8 p{margin:0;}#mermaid-svg-CWDXgVyDZQVfbay8 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-CWDXgVyDZQVfbay8 .cluster-label text{fill:#333;}#mermaid-svg-CWDXgVyDZQVfbay8 .cluster-label span{color:#333;}#mermaid-svg-CWDXgVyDZQVfbay8 .cluster-label span p{background-color:transparent;}#mermaid-svg-CWDXgVyDZQVfbay8 .label text,#mermaid-svg-CWDXgVyDZQVfbay8 span{fill:#333;color:#333;}#mermaid-svg-CWDXgVyDZQVfbay8 .node rect,#mermaid-svg-CWDXgVyDZQVfbay8 .node circle,#mermaid-svg-CWDXgVyDZQVfbay8 .node ellipse,#mermaid-svg-CWDXgVyDZQVfbay8 .node polygon,#mermaid-svg-CWDXgVyDZQVfbay8 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-CWDXgVyDZQVfbay8 .rough-node .label text,#mermaid-svg-CWDXgVyDZQVfbay8 .node .label text,#mermaid-svg-CWDXgVyDZQVfbay8 .image-shape .label,#mermaid-svg-CWDXgVyDZQVfbay8 .icon-shape .label{text-anchor:middle;}#mermaid-svg-CWDXgVyDZQVfbay8 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-CWDXgVyDZQVfbay8 .rough-node .label,#mermaid-svg-CWDXgVyDZQVfbay8 .node .label,#mermaid-svg-CWDXgVyDZQVfbay8 .image-shape .label,#mermaid-svg-CWDXgVyDZQVfbay8 .icon-shape .label{text-align:center;}#mermaid-svg-CWDXgVyDZQVfbay8 .node.clickable{cursor:pointer;}#mermaid-svg-CWDXgVyDZQVfbay8 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-CWDXgVyDZQVfbay8 .arrowheadPath{fill:#333333;}#mermaid-svg-CWDXgVyDZQVfbay8 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-CWDXgVyDZQVfbay8 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-CWDXgVyDZQVfbay8 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-CWDXgVyDZQVfbay8 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-CWDXgVyDZQVfbay8 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-CWDXgVyDZQVfbay8 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-CWDXgVyDZQVfbay8 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-CWDXgVyDZQVfbay8 .cluster text{fill:#333;}#mermaid-svg-CWDXgVyDZQVfbay8 .cluster span{color:#333;}#mermaid-svg-CWDXgVyDZQVfbay8 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-CWDXgVyDZQVfbay8 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-CWDXgVyDZQVfbay8 rect.text{fill:none;stroke-width:0;}#mermaid-svg-CWDXgVyDZQVfbay8 .icon-shape,#mermaid-svg-CWDXgVyDZQVfbay8 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-CWDXgVyDZQVfbay8 .icon-shape p,#mermaid-svg-CWDXgVyDZQVfbay8 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-CWDXgVyDZQVfbay8 .icon-shape .label rect,#mermaid-svg-CWDXgVyDZQVfbay8 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-CWDXgVyDZQVfbay8 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-CWDXgVyDZQVfbay8 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-CWDXgVyDZQVfbay8 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

Tool Layer

Session Layer

OpenClaw Runtime

cross-session

spawn

announce

Gateway 网关

Session Store 会话存储

Agent Runtime 代理运行时

主会话 Main Session

群组会话 Group Session

定时任务会话 Cron Session

子代理会话 Subagent Session

sessions_list

sessions_send

sessions_spawn

session_status

Gateway 是整个运行时的中枢,负责消息路由、会话创建和生命周期管理。Session Store 持久化所有会话状态和对话记录。Agent Runtime 则通过一组 Session Tools 与会话层交互,实现跨会话通信和子 Agent 编排。

2.2 会话存储结构

所有会话状态由 Gateway 统一管理,存储路径如下:

存储项路径说明
会话元数据 ~/.openclaw/agents/<agentId>/sessions/sessions.json 包含生命周期时间戳、路由信息
对话记录 ~/.openclaw/agents/<agentId>/sessions/<sessionId>.jsonl JSONL 格式的完整对话历史
工作空间 ~/.openclaw/workspace Agent 的工作目录,引导文件和技能

值得注意的是,会话存储与工作空间是物理隔离的。工作空间存放的是 Agent 的"记忆"(AGENTS.md、SOUL.md 等),而会话存储则是对话的"日志"。这种分离设计确保了即使会话被清理,Agent 的核心身份和知识不会丢失。

2.3 会话元数据时间戳

sessions.json 中为每个会话维护了三个独立的时间戳,各有用途:

时间戳字段含义用途
sessionStartedAt 当前 SessionId 开始的时间 每日重置的判定依据
lastInteractionAt 最后一次用户/渠道交互时间 空闲重置的判定依据
updatedAt 最后一次存储行变更时间 列表排序和清理的参考,不用于重置判定

这种三时间戳设计看似简单,实则解决了"系统后台事件不应延长会话生命周期"这一关键问题。心跳(Heartbeat)、定时任务(Cron)和后台执行(Exec)等系统事件会更新 updatedAt,但不会刷新 sessionStartedAt 或 lastInteractionAt,确保会话过期判定只基于真实用户交互。


三、会话状态机制:从路由到生命周期

3.1 消息路由:会话的第一道关卡

每条消息到达 Gateway 后,首先要解决的问题是"这条消息属于哪个会话"。OpenClaw 根据消息来源进行路由:

消息来源路由行为
私信(DM) 默认共享同一会话
群聊 每个群独立隔离
频道/房间 每个频道独立隔离
定时任务 每次运行创建新会话
Webhook 每个 Hook 独立隔离

#mermaid-svg-DXfylGI4somLXKv5{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-DXfylGI4somLXKv5 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-DXfylGI4somLXKv5 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-DXfylGI4somLXKv5 .error-icon{fill:#552222;}#mermaid-svg-DXfylGI4somLXKv5 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-DXfylGI4somLXKv5 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-DXfylGI4somLXKv5 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-DXfylGI4somLXKv5 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-DXfylGI4somLXKv5 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-DXfylGI4somLXKv5 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-DXfylGI4somLXKv5 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-DXfylGI4somLXKv5 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-DXfylGI4somLXKv5 .marker.cross{stroke:#333333;}#mermaid-svg-DXfylGI4somLXKv5 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-DXfylGI4somLXKv5 p{margin:0;}#mermaid-svg-DXfylGI4somLXKv5 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-DXfylGI4somLXKv5 .cluster-label text{fill:#333;}#mermaid-svg-DXfylGI4somLXKv5 .cluster-label span{color:#333;}#mermaid-svg-DXfylGI4somLXKv5 .cluster-label span p{background-color:transparent;}#mermaid-svg-DXfylGI4somLXKv5 .label text,#mermaid-svg-DXfylGI4somLXKv5 span{fill:#333;color:#333;}#mermaid-svg-DXfylGI4somLXKv5 .node rect,#mermaid-svg-DXfylGI4somLXKv5 .node circle,#mermaid-svg-DXfylGI4somLXKv5 .node ellipse,#mermaid-svg-DXfylGI4somLXKv5 .node polygon,#mermaid-svg-DXfylGI4somLXKv5 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-DXfylGI4somLXKv5 .rough-node .label text,#mermaid-svg-DXfylGI4somLXKv5 .node .label text,#mermaid-svg-DXfylGI4somLXKv5 .image-shape .label,#mermaid-svg-DXfylGI4somLXKv5 .icon-shape .label{text-anchor:middle;}#mermaid-svg-DXfylGI4somLXKv5 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-DXfylGI4somLXKv5 .rough-node .label,#mermaid-svg-DXfylGI4somLXKv5 .node .label,#mermaid-svg-DXfylGI4somLXKv5 .image-shape .label,#mermaid-svg-DXfylGI4somLXKv5 .icon-shape .label{text-align:center;}#mermaid-svg-DXfylGI4somLXKv5 .node.clickable{cursor:pointer;}#mermaid-svg-DXfylGI4somLXKv5 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-DXfylGI4somLXKv5 .arrowheadPath{fill:#333333;}#mermaid-svg-DXfylGI4somLXKv5 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-DXfylGI4somLXKv5 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-DXfylGI4somLXKv5 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-DXfylGI4somLXKv5 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-DXfylGI4somLXKv5 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-DXfylGI4somLXKv5 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-DXfylGI4somLXKv5 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-DXfylGI4somLXKv5 .cluster text{fill:#333;}#mermaid-svg-DXfylGI4somLXKv5 .cluster span{color:#333;}#mermaid-svg-DXfylGI4somLXKv5 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-DXfylGI4somLXKv5 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-DXfylGI4somLXKv5 rect.text{fill:none;stroke-width:0;}#mermaid-svg-DXfylGI4somLXKv5 .icon-shape,#mermaid-svg-DXfylGI4somLXKv5 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-DXfylGI4somLXKv5 .icon-shape p,#mermaid-svg-DXfylGI4somLXKv5 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-DXfylGI4somLXKv5 .icon-shape .label rect,#mermaid-svg-DXfylGI4somLXKv5 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-DXfylGI4somLXKv5 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-DXfylGI4somLXKv5 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-DXfylGI4somLXKv5 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

dmScope: main

dmScope: main

隔离

隔离

每次新建

隔离

👤 Alice 私信

主会话

👤 Bob 私信

👥 群组 A

群组会话 A

👥 群组 B

群组会话 B

⏰ 定时任务

临时会话

🔗 Webhook

Hook 会话

3.2 DM 隔离:多用户场景的必修课

在单用户场景下,所有私信共享一个会话是合理的——它提供了跨渠道的连续性。但在多用户环境中,这会导致严重的上下文泄露:Alice 的私密对话可能被 Bob 看到。

OpenClaw 提供了四种 DM 隔离策略,通过 session.dmScope 配置:

{
session: {
// 策略一:所有私信共享一个会话(默认,适合单用户)
dmScope: "main",

// 策略二:按发送者隔离(跨渠道共享)
dmScope: "per-peer",

// 策略三:按渠道+发送者隔离(推荐,最安全)
dmScope: "per-channel-peer",

// 策略四:按账户+渠道+发送者隔离(最细粒度)
dmScope: "per-account-channel-peer",
},
}

生产环境推荐使用 per-channel-peer。它确保每个用户在每个渠道上拥有独立的会话,同时通过 session.identityLinks 可以将同一用户在不同渠道的身份关联起来,实现跨渠道的会话共享。

3.3 会话生命周期

会话从创建到消亡,经历以下阶段:

#mermaid-svg-AWk3nTSUDRCNR6Ax{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-AWk3nTSUDRCNR6Ax .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-AWk3nTSUDRCNR6Ax .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-AWk3nTSUDRCNR6Ax .error-icon{fill:#552222;}#mermaid-svg-AWk3nTSUDRCNR6Ax .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-AWk3nTSUDRCNR6Ax .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-AWk3nTSUDRCNR6Ax .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-AWk3nTSUDRCNR6Ax .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-AWk3nTSUDRCNR6Ax .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-AWk3nTSUDRCNR6Ax .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-AWk3nTSUDRCNR6Ax .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-AWk3nTSUDRCNR6Ax .marker{fill:#333333;stroke:#333333;}#mermaid-svg-AWk3nTSUDRCNR6Ax .marker.cross{stroke:#333333;}#mermaid-svg-AWk3nTSUDRCNR6Ax svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-AWk3nTSUDRCNR6Ax p{margin:0;}#mermaid-svg-AWk3nTSUDRCNR6Ax defs #statediagram-barbEnd{fill:#333333;stroke:#333333;}#mermaid-svg-AWk3nTSUDRCNR6Ax g.stateGroup text{fill:#9370DB;stroke:none;font-size:10px;}#mermaid-svg-AWk3nTSUDRCNR6Ax g.stateGroup text{fill:#333;stroke:none;font-size:10px;}#mermaid-svg-AWk3nTSUDRCNR6Ax g.stateGroup .state-title{font-weight:bolder;fill:#131300;}#mermaid-svg-AWk3nTSUDRCNR6Ax g.stateGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-AWk3nTSUDRCNR6Ax g.stateGroup line{stroke:#333333;stroke-width:1;}#mermaid-svg-AWk3nTSUDRCNR6Ax .transition{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-AWk3nTSUDRCNR6Ax .stateGroup .composit{fill:white;border-bottom:1px;}#mermaid-svg-AWk3nTSUDRCNR6Ax .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px;}#mermaid-svg-AWk3nTSUDRCNR6Ax .state-note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-AWk3nTSUDRCNR6Ax .state-note text{fill:black;stroke:none;font-size:10px;}#mermaid-svg-AWk3nTSUDRCNR6Ax .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-AWk3nTSUDRCNR6Ax .edgeLabel .label rect{fill:#ECECFF;opacity:0.5;}#mermaid-svg-AWk3nTSUDRCNR6Ax .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-AWk3nTSUDRCNR6Ax .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-AWk3nTSUDRCNR6Ax .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-AWk3nTSUDRCNR6Ax .edgeLabel .label text{fill:#333;}#mermaid-svg-AWk3nTSUDRCNR6Ax .label div .edgeLabel{color:#333;}#mermaid-svg-AWk3nTSUDRCNR6Ax .stateLabel text{fill:#131300;font-size:10px;font-weight:bold;}#mermaid-svg-AWk3nTSUDRCNR6Ax .node circle.state-start{fill:#333333;stroke:#333333;}#mermaid-svg-AWk3nTSUDRCNR6Ax .node .fork-join{fill:#333333;stroke:#333333;}#mermaid-svg-AWk3nTSUDRCNR6Ax .node circle.state-end{fill:#9370DB;stroke:white;stroke-width:1.5;}#mermaid-svg-AWk3nTSUDRCNR6Ax .end-state-inner{fill:white;stroke-width:1.5;}#mermaid-svg-AWk3nTSUDRCNR6Ax .node rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-AWk3nTSUDRCNR6Ax .node polygon{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-AWk3nTSUDRCNR6Ax #statediagram-barbEnd{fill:#333333;}#mermaid-svg-AWk3nTSUDRCNR6Ax .statediagram-cluster rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-AWk3nTSUDRCNR6Ax .cluster-label,#mermaid-svg-AWk3nTSUDRCNR6Ax .nodeLabel{color:#131300;}#mermaid-svg-AWk3nTSUDRCNR6Ax .statediagram-cluster rect.outer{rx:5px;ry:5px;}#mermaid-svg-AWk3nTSUDRCNR6Ax .statediagram-state .divider{stroke:#9370DB;}#mermaid-svg-AWk3nTSUDRCNR6Ax .statediagram-state .title-state{rx:5px;ry:5px;}#mermaid-svg-AWk3nTSUDRCNR6Ax .statediagram-cluster.statediagram-cluster .inner{fill:white;}#mermaid-svg-AWk3nTSUDRCNR6Ax .statediagram-cluster.statediagram-cluster-alt .inner{fill:#f0f0f0;}#mermaid-svg-AWk3nTSUDRCNR6Ax .statediagram-cluster .inner{rx:0;ry:0;}#mermaid-svg-AWk3nTSUDRCNR6Ax .statediagram-state rect.basic{rx:5px;ry:5px;}#mermaid-svg-AWk3nTSUDRCNR6Ax .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#f0f0f0;}#mermaid-svg-AWk3nTSUDRCNR6Ax .note-edge{stroke-dasharray:5;}#mermaid-svg-AWk3nTSUDRCNR6Ax .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-AWk3nTSUDRCNR6Ax .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-AWk3nTSUDRCNR6Ax .statediagram-note text{fill:black;}#mermaid-svg-AWk3nTSUDRCNR6Ax .statediagram-note .nodeLabel{color:black;}#mermaid-svg-AWk3nTSUDRCNR6Ax .statediagram .edgeLabel{color:red;}#mermaid-svg-AWk3nTSUDRCNR6Ax #dependencyStart,#mermaid-svg-AWk3nTSUDRCNR6Ax #dependencyEnd{fill:#333333;stroke:#333333;stroke-width:1;}#mermaid-svg-AWk3nTSUDRCNR6Ax .statediagramTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-AWk3nTSUDRCNR6Ax :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

消息路由创建

用户交互(刷新 lastInteractionAt)

上下文接近限制

压缩完成

空闲超时

每日重置(凌晨4点)

/new 或 /reset

新会话创建

新会话创建

新会话创建

维护清理(pruneAfter)

Active

Compacting

IdleReset

DailyReset

ManualReset

Pruned

三种重置触发方式的对比:

重置方式触发条件时间戳判定可配置性
每日重置 凌晨 4:00(默认) 基于 sessionStartedAt 自动,可切换时区
空闲重置 无用户交互超过阈值 基于 lastInteractionAt session.reset.idleMinutes
手动重置 用户执行 /new 或 /reset 立即 即时生效

关键设计细节:心跳、Cron、Exec 等系统事件不会延长会话生命周期。当重置触发时,旧会话中排队的系统事件通知会被丢弃,避免过期上下文污染新会话的首轮提示。


四、上下文管理策略:继承、隔离与传递

4.1 引导文件注入:每轮对话的起点

每个会话的首轮,OpenClaw 会将工作空间中的引导文件(Bootstrap Files)注入到系统提示的 Project Context 中:

文件作用加载策略
AGENTS.md 操作指令与记忆规范 每次会话加载
SOUL.md 人格、语气与边界 每次会话加载
USER.md 用户画像与称呼偏好 每次会话加载
IDENTITY.md Agent 名称、风格、Emoji 每次会话加载
TOOLS.md 本地工具约定 每次会话加载
BOOTSTRAP.md 首次运行仪式 仅首次,完成后删除
HEARTBEAT.md 心跳检查清单 心跳触发时加载

空文件会被跳过,超大文件会被截断并插入标记。通过 agents.defaults.bootstrapMaxChars(默认 20000)和 agents.defaults.bootstrapTotalMaxChars(默认 60000)可以控制注入上限。

4.2 子 Agent 上下文模式:Fork vs Isolated

当通过 sessions_spawn 创建子 Agent 时,上下文传递是最关键的架构决策之一。OpenClaw 提供两种模式:

Isolated 模式(默认): 子 Agent 从零开始,只接收任务描述和子代理运行时规则。这是最安全的模式,避免了父会话上下文的泄露。

Fork 模式: 子 Agent 继承父会话的完整对话历史。适用于子任务需要理解父对话背景的场景,例如"根据我们之前讨论的方案继续实现"。

# 示例:通过 sessions_spawn 创建子 Agent
# Isolated 模式(默认)
result = sessions_spawn(
task="分析这份代码的性能瓶颈",
# context 参数省略,默认 isolated
)

# Fork 模式(继承父会话上下文)
result = sessions_spawn(
task="根据我们刚才讨论的优化方向,重构这段代码",
context="fork", # 子 Agent 将看到父对话历史
)

代码说明: 上述示例展示了两种上下文模式的使用方式。isolated 模式适用于独立任务,子 Agent 不会看到父会话中的任何历史消息;fork 模式则将父会话的完整对话传递给子 Agent,使其能够理解之前的讨论背景。选择哪种模式取决于子任务是否依赖父对话上下文。

4.3 跨会话消息传递

sessions_send 是 Agent 跨会话通信的核心工具,支持两种模式:

  • Fire-and-forget(即发即忘): 设置 timeoutSeconds: 0,消息入队后立即返回
  • Wait-for-reply(等待回复): 设置超时时间,阻塞等待目标 Agent 的响应

# Fire-and-forget 模式
sessions_send(
targetSessionKey="group:discord:123456",
message="后台任务已完成,结果已存储",
timeoutSeconds=0, # 不等待回复
)

# Wait-for-reply 模式
response = sessions_send(
targetSessionKey="agent:research-worker",
message="请查找 OpenClaw 会话管理的最佳实践",
timeoutSeconds=60, # 最多等待 60 秒
)

代码说明: sessions_send 的两种使用模式覆盖了不同的跨会话通信需求。Fire-and-forget 适合通知类消息(如任务完成通知),Wait-for-reply 适合需要协作的场景(如请求其他 Agent 的分析结果)。发送到目标会话的消息会被标记为 [Inter-session message],接收方应将其视为工具路由数据,而非终端用户的直接指令。

跨会话消息还支持 A2A Ping-Pong 模式:两个 Agent 可以交替对话,最多进行 session.agentToAgent.maxPingPongTurns(默认 5)轮。目标 Agent 可以回复 REPLY_SKIP 提前终止对话。

4.4 上下文可见性控制

Session Tools 的可见性通过 visibility 配置进行作用域限制:

级别作用域适用场景
self 仅当前会话 严格隔离
tree 当前会话 + 派生的子 Agent 默认,最常用
agent 当前 Agent 的所有会话 单 Agent 多会话协作
all 所有会话(跨 Agent) 多 Agent 全局协调

沙箱会话(Sandbox)会被强制限制为 tree 级别,无论配置如何。


五、跨会话持久化:状态保存与恢复

5.1 会话状态的所有权模型

OpenClaw 采用 Gateway 所有权模型:所有会话状态由 Gateway 统一持有,UI 客户端通过查询 Gateway 获取会话数据。这种设计保证了状态的一致性——无论你从哪个客户端访问,看到的都是同一份会话状态。

5.2 记忆文件:跨会话的"长期记忆"

会话记录是对话的"短期记忆",而工作空间中的记忆文件则是 Agent 的"长期记忆":

<!– memory/2026-06-19.md 示例 –>
## 今日要点

### 决策
– 采用 per-channel-peer 隔离策略
– 启用空闲重置,阈值 120 分钟

### 关键发现
– 系统事件不会延长会话生命周期
– 压缩前会自动提醒 Agent 保存重要笔记

### 待办
– [ ] 检查 session.identityLinks 配置
– [ ] 测试子 Agent fork 模式的上下文传递

代码说明: 这是 OpenClaw 推荐的每日记忆日志格式。文件路径遵循 memory/YYYY-MM-DD.md 命名规范,Agent 在每次会话开始时会自动读取今天和昨天的日志。这种设计将"正在进行的对话"(会话内)和"需要持久记住的知识"(文件中)清晰分离。

5.3 会话恢复的场景与策略

会话恢复并不是简单地"重新打开旧对话",而是涉及多个层面的状态还原:

恢复层面机制持久性
对话历史 JSONL 转录文件 永久(直到被清理)
上下文窗口 压缩摘要 + 最近消息 会话级别
Agent 身份 SOUL.md / IDENTITY.md 文件级别,跨会话
工作空间状态 文件系统 持久,独立于会话
运行时变量 session_status 中的模型/令牌信息 会话级别

在压缩(Compaction)发生之前,OpenClaw 会自动提醒 Agent 将重要笔记保存到记忆文件。这一设计确保了即使上下文被压缩,关键信息也不会丢失——它们已经从"对话记忆"转移到了"文件记忆"。

5.4 压缩后的后继转录

当启用 truncateAfterCompaction 时,OpenClaw 不会原地改写现有转录文件,而是创建一个新的后继转录(Successor Transcript),包含压缩摘要、保留状态和未压缩的尾部。旧转录文件仍然保留,供分支/恢复流程引用。

{
agents: {
defaults: {
compaction: {
truncateAfterCompaction: true, // 启用后继转录
maxActiveTranscriptBytes: 5242880, // 5MB 触发压缩
},
},
},
}

代码说明: 这个配置启用了两个关键特性。truncateAfterCompaction 让每次压缩后创建新的转录文件,避免单文件无限增长。maxActiveTranscriptBytes 设置了活跃转录的字节上限,当 JSONL 文件超过 5MB 时,即使模型上下文窗口还有余量,也会触发压缩——这对长时间运行的会话特别有用,因为本地转录可能会持续增长,即使提供端的上下文管理已经处理了模型上下文。


六、会话清理:过期会话回收机制

6.1 自动清理策略

OpenClaw 内置了会话清理机制,在 enforce 模式下自动运行:

{
session: {
maintenance: {
mode: "enforce", // 执行模式,"warn" 仅报告不执行
pruneAfter: "30d", // 30 天后清理
maxEntries: 500, // 最多保留 500 条
},
},
}

代码说明: 会话维护配置控制着 OpenClaw 如何自动回收过期会话。mode: "enforce" 表示实际执行清理操作;如果设置为 "warn",则只报告将被清理的会话而不实际删除。pruneAfter: "30d" 意味着超过 30 天的会话将被清理。maxEntries: 500 限制了会话存储的最大条目数,超出时按时间顺序淘汰最旧的。

6.2 清理的安全保护

清理机制并非简单的"一刀切",它有精细的保护策略:

  • 持久化外部对话指针:群组会话和线程范围的聊天会话会被保留,因为它们可能仍被外部渠道引用
  • 合成条目可过期:Cron、Hook、Heartbeat、ACP 和子 Agent 条目可以按时间淘汰
  • DM 范围修复:如果之前使用过私信隔离,后来又改回 main 模式,可以通过 openclaw sessions cleanup –dry-run –fix-dm-scope 预览并清理过时的隔离行

6.3 手动清理与预览

OpenClaw 提供了 CLI 命令用于手动管理会话清理:

# 预览将被清理的会话(不实际执行)
openclaw sessions cleanup –dry-run

# 立即执行清理
openclaw sessions cleanup –enforce

# 修复 DM 范围变更后的残留数据
openclaw sessions cleanup –dry-run –fix-dm-scope

生产环境建议先运行 –dry-run 确认清理范围,再使用 –enforce 实际执行。

6.4 maxEntries 的高水位缓冲

对于生产级 maxEntries 限制,Gateway 运行时写入使用一个高水位缓冲区,按批次清理回退到配置上限。这种设计避免了每条新会话都触发清理操作的性能开销。

同时,会话存储读取在 Gateway 启动时不会执行清理或上限裁剪,避免了每次启动都运行完整存储清理的问题。如需立即应用上限,使用 openclaw sessions cleanup –enforce。


七、多会话并发:并行会话管理

7.1 并发会话的场景

在实际使用中,Agent 可能同时处理多个任务,每个任务运行在独立的会话中:

并发场景会话类型隔离级别
多用户同时私信 DM 会话 per-channel-peer
Agent 执行后台任务 子 Agent 会话 tree
定时任务并行触发 Cron 会话 每次独立
多渠道消息同时到达 渠道会话 按渠道隔离

7.2 子 Agent 深度与工具分配

OpenClaw 对子 Agent 的嵌套深度有严格控制,并通过深度动态分配工具权限:

深度可用工具说明
叶子节点(depth 0) 基础工具 不含会话编排工具
编排节点(depth 1,需 maxSpawnDepth ≥ 2) sessions_spawn, subagents, sessions_list, sessions_history 可以管理自己的子 Agent
更深层 受 maxSpawnDepth 限制 默认最大深度为 1

#mermaid-svg-fRXluj0S0WyTcM1K{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-fRXluj0S0WyTcM1K .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-fRXluj0S0WyTcM1K .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-fRXluj0S0WyTcM1K .error-icon{fill:#552222;}#mermaid-svg-fRXluj0S0WyTcM1K .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-fRXluj0S0WyTcM1K .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-fRXluj0S0WyTcM1K .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-fRXluj0S0WyTcM1K .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-fRXluj0S0WyTcM1K .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-fRXluj0S0WyTcM1K .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-fRXluj0S0WyTcM1K .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-fRXluj0S0WyTcM1K .marker{fill:#333333;stroke:#333333;}#mermaid-svg-fRXluj0S0WyTcM1K .marker.cross{stroke:#333333;}#mermaid-svg-fRXluj0S0WyTcM1K svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-fRXluj0S0WyTcM1K p{margin:0;}#mermaid-svg-fRXluj0S0WyTcM1K .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-fRXluj0S0WyTcM1K .cluster-label text{fill:#333;}#mermaid-svg-fRXluj0S0WyTcM1K .cluster-label span{color:#333;}#mermaid-svg-fRXluj0S0WyTcM1K .cluster-label span p{background-color:transparent;}#mermaid-svg-fRXluj0S0WyTcM1K .label text,#mermaid-svg-fRXluj0S0WyTcM1K span{fill:#333;color:#333;}#mermaid-svg-fRXluj0S0WyTcM1K .node rect,#mermaid-svg-fRXluj0S0WyTcM1K .node circle,#mermaid-svg-fRXluj0S0WyTcM1K .node ellipse,#mermaid-svg-fRXluj0S0WyTcM1K .node polygon,#mermaid-svg-fRXluj0S0WyTcM1K .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-fRXluj0S0WyTcM1K .rough-node .label text,#mermaid-svg-fRXluj0S0WyTcM1K .node .label text,#mermaid-svg-fRXluj0S0WyTcM1K .image-shape .label,#mermaid-svg-fRXluj0S0WyTcM1K .icon-shape .label{text-anchor:middle;}#mermaid-svg-fRXluj0S0WyTcM1K .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-fRXluj0S0WyTcM1K .rough-node .label,#mermaid-svg-fRXluj0S0WyTcM1K .node .label,#mermaid-svg-fRXluj0S0WyTcM1K .image-shape .label,#mermaid-svg-fRXluj0S0WyTcM1K .icon-shape .label{text-align:center;}#mermaid-svg-fRXluj0S0WyTcM1K .node.clickable{cursor:pointer;}#mermaid-svg-fRXluj0S0WyTcM1K .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-fRXluj0S0WyTcM1K .arrowheadPath{fill:#333333;}#mermaid-svg-fRXluj0S0WyTcM1K .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-fRXluj0S0WyTcM1K .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-fRXluj0S0WyTcM1K .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-fRXluj0S0WyTcM1K .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-fRXluj0S0WyTcM1K .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-fRXluj0S0WyTcM1K .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-fRXluj0S0WyTcM1K .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-fRXluj0S0WyTcM1K .cluster text{fill:#333;}#mermaid-svg-fRXluj0S0WyTcM1K .cluster span{color:#333;}#mermaid-svg-fRXluj0S0WyTcM1K div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-fRXluj0S0WyTcM1K .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-fRXluj0S0WyTcM1K rect.text{fill:none;stroke-width:0;}#mermaid-svg-fRXluj0S0WyTcM1K .icon-shape,#mermaid-svg-fRXluj0S0WyTcM1K .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-fRXluj0S0WyTcM1K .icon-shape p,#mermaid-svg-fRXluj0S0WyTcM1K .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-fRXluj0S0WyTcM1K .icon-shape .label rect,#mermaid-svg-fRXluj0S0WyTcM1K .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-fRXluj0S0WyTcM1K .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-fRXluj0S0WyTcM1K .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-fRXluj0S0WyTcM1K :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

sessions_spawn

sessions_spawn

sessions_spawn

sessions_spawn

sessions_yield

auto-announce

auto-announce

auto-announce

父会话 Main

子 Agent 1depth=0, 叶子节点

子 Agent 2depth=1, 编排节点

孙 Agent 1depth=0, 叶子节点

孙 Agent 2depth=0, 叶子节点

等待子 Agent 结果

7.3 并发消息的队列管理

当 Agent 正在处理一条消息时,新到达的消息不会丢失,而是进入消息队列。OpenClaw 提供了四种队列策略:

  • steer(默认): 当前工具调用执行完毕后,新消息被引导到当前运行中
  • followup: 新消息等待当前轮次结束后再处理
  • collect: 收集所有等待中的消息,合并处理
  • interrupt: 中断当前运行,立即处理新消息

这种队列机制确保了并发消息不会互相干扰,同时提供了灵活的处理策略选择。


八、上下文压缩与剪枝:让对话持续运转

8.1 Pruning(剪枝):轻量级上下文优化

剪枝是内存级的优化,不修改磁盘上的会话转录。它的工作流程是:

  • 等待缓存 TTL 过期(默认 5 分钟)
  • 找到旧的工具结果(对话文本不动)
  • 软裁剪超大结果——保留头尾,中间用 … 替代
  • 硬清除其余内容——用占位符替代
  • 重置 TTL,使后续请求复用新鲜缓存
  • 剪枝特别适合使用 Anthropic Prompt Cache 的场景。缓存过期后重新写入缓存时,剪枝减少了缓存写入大小,直接降低成本。

    8.2 Compaction(压缩):语义级上下文缩减

    当剪枝不足以控制上下文增长时,压缩登场。压缩将旧对话语义化摘要为紧凑的条目:

    #mermaid-svg-4GOoxwCBtxPdBitV{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-4GOoxwCBtxPdBitV .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-4GOoxwCBtxPdBitV .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-4GOoxwCBtxPdBitV .error-icon{fill:#552222;}#mermaid-svg-4GOoxwCBtxPdBitV .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-4GOoxwCBtxPdBitV .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-4GOoxwCBtxPdBitV .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-4GOoxwCBtxPdBitV .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-4GOoxwCBtxPdBitV .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-4GOoxwCBtxPdBitV .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-4GOoxwCBtxPdBitV .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-4GOoxwCBtxPdBitV .marker{fill:#333333;stroke:#333333;}#mermaid-svg-4GOoxwCBtxPdBitV .marker.cross{stroke:#333333;}#mermaid-svg-4GOoxwCBtxPdBitV svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-4GOoxwCBtxPdBitV p{margin:0;}#mermaid-svg-4GOoxwCBtxPdBitV .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-4GOoxwCBtxPdBitV .cluster-label text{fill:#333;}#mermaid-svg-4GOoxwCBtxPdBitV .cluster-label span{color:#333;}#mermaid-svg-4GOoxwCBtxPdBitV .cluster-label span p{background-color:transparent;}#mermaid-svg-4GOoxwCBtxPdBitV .label text,#mermaid-svg-4GOoxwCBtxPdBitV span{fill:#333;color:#333;}#mermaid-svg-4GOoxwCBtxPdBitV .node rect,#mermaid-svg-4GOoxwCBtxPdBitV .node circle,#mermaid-svg-4GOoxwCBtxPdBitV .node ellipse,#mermaid-svg-4GOoxwCBtxPdBitV .node polygon,#mermaid-svg-4GOoxwCBtxPdBitV .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-4GOoxwCBtxPdBitV .rough-node .label text,#mermaid-svg-4GOoxwCBtxPdBitV .node .label text,#mermaid-svg-4GOoxwCBtxPdBitV .image-shape .label,#mermaid-svg-4GOoxwCBtxPdBitV .icon-shape .label{text-anchor:middle;}#mermaid-svg-4GOoxwCBtxPdBitV .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-4GOoxwCBtxPdBitV .rough-node .label,#mermaid-svg-4GOoxwCBtxPdBitV .node .label,#mermaid-svg-4GOoxwCBtxPdBitV .image-shape .label,#mermaid-svg-4GOoxwCBtxPdBitV .icon-shape .label{text-align:center;}#mermaid-svg-4GOoxwCBtxPdBitV .node.clickable{cursor:pointer;}#mermaid-svg-4GOoxwCBtxPdBitV .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-4GOoxwCBtxPdBitV .arrowheadPath{fill:#333333;}#mermaid-svg-4GOoxwCBtxPdBitV .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-4GOoxwCBtxPdBitV .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-4GOoxwCBtxPdBitV .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-4GOoxwCBtxPdBitV .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-4GOoxwCBtxPdBitV .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-4GOoxwCBtxPdBitV .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-4GOoxwCBtxPdBitV .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-4GOoxwCBtxPdBitV .cluster text{fill:#333;}#mermaid-svg-4GOoxwCBtxPdBitV .cluster span{color:#333;}#mermaid-svg-4GOoxwCBtxPdBitV div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-4GOoxwCBtxPdBitV .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-4GOoxwCBtxPdBitV rect.text{fill:none;stroke-width:0;}#mermaid-svg-4GOoxwCBtxPdBitV .icon-shape,#mermaid-svg-4GOoxwCBtxPdBitV .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-4GOoxwCBtxPdBitV .icon-shape p,#mermaid-svg-4GOoxwCBtxPdBitV .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-4GOoxwCBtxPdBitV .icon-shape .label rect,#mermaid-svg-4GOoxwCBtxPdBitV .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-4GOoxwCBtxPdBitV .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-4GOoxwCBtxPdBitV .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-4GOoxwCBtxPdBitV :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    压缩后

    压缩前

    用户消息 1

    助手回复 1

    工具调用 1

    工具结果 1

    用户消息 2

    助手回复 2

    📝 压缩摘要保留了关键决策和上下文

    用户消息 2

    助手回复 2

    压缩与剪枝的关键区别:

    维度Pruning 剪枝Compaction 压缩
    操作对象 工具结果 整个对话
    持久性 仅内存,不保存 保存到转录文件
    触发方式 缓存 TTL 过期 上下文接近限制 / /compact
    信息损失 工具输出被裁剪 旧对话被摘要替代
    成本 无额外 LLM 调用 需要一次摘要调用

    8.3 自动压缩与手动压缩

    自动压缩默认开启,在会话接近上下文限制时触发,或当模型返回上下文溢出错误时自动压缩并重试。

    手动压缩通过 /compact 命令触发,还可以附加指令引导摘要方向:

    /compact 重点关注 API 设计决策

    压缩前,OpenClaw 会自动提醒 Agent 将重要笔记保存到记忆文件,防止上下文丢失。

    8.4 压缩配置进阶

    {
    agents: {
    defaults: {
    compaction: {
    // 使用专用模型进行摘要(节省主模型成本)
    model: "ollama/llama3.1:8b",

    // 压缩时通知用户
    notifyUser: true,

    // 标识符保留策略(默认 strict,防止摘要丢失关键 ID)
    identifierPolicy: "strict",

    // 内存刷新使用本地模型
    memoryFlush: {
    model: "ollama/qwen3:8b"
    },
    },
    },
    },
    }

    代码说明: 这个进阶配置展示了压缩的几个重要选项。model 允许指定专门的摘要模型,而不是使用当前的对话模型——这在对话使用高端模型但摘要可以使用便宜模型时特别有用。notifyUser 会在压缩开始和完成时显示简要状态消息。identifierPolicy: "strict" 确保压缩摘要保留所有不透明标识符(如 session ID、agent ID 等),防止摘要后丢失关键引用。memoryFlush.model 让压缩前的内存刷新步骤使用本地模型,进一步节省成本。


    九、上下文引擎:可插拔的上下文组装

    9.1 上下文引擎的概念

    OpenClaw 引入了上下文引擎(Context Engine)这一可插拔架构,控制每次模型运行时如何组装上下文。默认使用内置的 legacy 引擎,大多数用户不需要修改。

    上下文引擎参与四个生命周期节点:

    生命周期方法职责
    Ingest(摄入) ingest() 新消息到达时存储/索引
    Assemble(组装) assemble() 构建符合 token 预算的消息集
    Compact(压缩) compact() 上下文满时执行摘要
    After Turn(轮次后) afterTurn() 运行后持久化状态或触发后台压缩

    9.2 Legacy 引擎

    内置的 legacy 引擎保持 OpenClaw 的原始行为:

    • Ingest:空操作(会话管理器直接处理消息持久化)
    • Assemble:透传(现有的清理→验证→限制管道处理上下文组装)
    • Compact:委托给内置摘要压缩
    • After Turn:空操作

    9.3 插件引擎

    插件可以注册自定义上下文引擎,实现更智能的上下文管理策略:

    import { buildMemorySystemPromptAddition } from "openclaw/plugin-sdk/core";

    export default function register(api) {
    api.registerContextEngine("my-engine", (ctx) => ({
    info: {
    id: "my-engine",
    name: "My Context Engine",
    ownsCompaction: true, // 引擎自行管理压缩
    },

    async ingest({ sessionId, message, isHeartbeat }) {
    // 将消息存储到自定义数据存储
    return { ingested: true };
    },

    async assemble({ sessionId, messages, tokenBudget, availableTools }) {
    // 返回符合预算的消息集
    return {
    messages: buildContext(messages, tokenBudget),
    estimatedTokens: countTokens(messages),
    systemPromptAddition: buildMemorySystemPromptAddition({
    availableTools: availableTools ?? new Set(),
    }),
    };
    },

    async compact({ sessionId, force }) {
    // 自定义压缩算法
    return { ok: true, compacted: true };
    },
    }));
    }

    代码说明: 这是一个自定义上下文引擎的完整注册示例。ownsCompaction: true 表示引擎自行管理压缩行为,OpenClaw 将禁用内置自动压缩。assemble() 方法是核心——它接收可用的消息列表和 token 预算,返回应该发送给模型的消息子集。systemPromptAddition 允许引擎动态注入系统提示内容,例如检索指引或上下文感知提示,无需修改静态的工作空间文件。

    9.4 故障隔离

    如果非 Legacy 引擎在运行时失败(缺失、合约验证失败、工厂创建异常或生命周期方法抛错),OpenClaw 会将该引擎隔离(Quarantine)当前 Gateway 进程,并降级到内置 Legacy 引擎。这确保了即使插件引擎崩溃,Agent 也不会停止响应。


    十、实战案例 1:用户会话恢复

    10.1 场景描述

    用户在飞书上与 Agent 讨论了一个复杂的系统架构方案,对话持续了 3 小时,涉及多个技术决策。第二天用户回来,希望继续昨天的讨论。

    10.2 会话状态分析

    # 查看当前会话状态
    openclaw status

    # 查看所有会话
    openclaw sessions –json

    # 查看活跃会话(最近 60 分钟有交互)
    openclaw sessions –json –active 60

    代码说明: 这组 CLI 命令用于诊断会话状态。openclaw status 显示会话存储路径和近期活动。openclaw sessions –json 列出所有会话的详细信息(包括关键、agentId、类型、渠道、模型、令牌数和时间戳)。–active 过滤器只显示最近指定分钟内有交互的会话,适合快速找到活跃对话。

    10.3 恢复流程

  • 每日重置已触发:凌晨 4:00 自动创建了新会话,旧对话的历史保存在 JSONL 转录中
  • 压缩摘要:如果昨天的对话触发过压缩,摘要保留了关键决策点
  • 记忆文件:压缩前 Agent 被提醒保存笔记到 memory/2026-06-18.md
  • # 在聊天中查看上下文状态
    /status

    # 查看系统提示中加载的内容
    /context list

    10.4 最佳实践

    对于需要跨天延续的深度讨论,建议:

  • 在对话结束前,明确要求 Agent 保存讨论要点到记忆文件
  • 在新会话开始时,让 Agent 读取昨天的记忆日志
  • 配置 compaction.identifierPolicy: "strict" 确保关键 ID 不被摘要丢失
  • 考虑使用 /compact 带指令进行定向压缩,保留特定主题的上下文

  • 十一、实战案例 2:多任务并行处理

    11.1 场景描述

    一个开发者同时给 Agent 派了三个任务:

    • 📊 分析代码库的性能瓶颈
    • 📝 编写技术文档
    • 🔍 搜索最新的安全漏洞信息

    11.2 并行任务架构

    # 主会话:派发三个子 Agent
    task_1 = sessions_spawn(
    task="分析 src/ 目录下所有 Python 文件的性能瓶颈,重点关注数据库查询和循环优化",
    model="anthropic/claude-sonnet-4", # 使用更强的模型
    )

    task_2 = sessions_spawn(
    task="根据代码库中的 README 和注释,编写 API 使用文档",
    model="ollama/qwen3:8b", # 使用本地模型节省成本
    )

    task_3 = sessions_spawn(
    task="搜索 Python 3.12 最新安全漏洞和修复建议",
    context="fork", # 继承父会话上下文,了解项目技术栈
    )

    # 主 Agent 暂停,等待子 Agent 结果
    sessions_yield()

    代码说明: 这个并行任务架构展示了 OpenClaw 子 Agent 系统的灵活性。每个子 Agent 可以使用不同的模型——性能分析需要强模型,文档编写可以用本地模型,安全搜索需要继承父上下文。sessions_yield() 让主 Agent 结束当前轮次,等待子 Agent 的结果自动推送回来,而不是轮询检查状态。

    11.3 结果收集

    子 Agent 完成后,结果通过 auto-announce 机制自动推送到主会话的渠道。完成投递会保留绑定的线程/话题路由,如果完成来源只标识了一个渠道,OpenClaw 仍可复用请求者会话的存储路由进行直接投递。

    11.4 并行管理的注意事项

    注意点说明
    并发限制 建议同一时间并行子 Agent 不超过 3 个
    模型选择 不同任务可使用不同模型,优化成本
    上下文隔离 默认 isolated 模式最安全,仅在必要时使用 fork
    结果聚合 使用 sessions_yield 等待,而非轮询

    十二、实战案例 3:会话历史分析

    12.1 场景描述

    运维团队需要分析 Agent 过去一周的会话历史,了解用户使用模式、常见的失败场景和资源消耗趋势。

    12.2 数据收集

    # 列出最近 7 天的活跃会话
    sessions = sessions_list(
    activeMinutes=10080, # 7 天 = 7 * 24 * 60 分钟
    )

    # 读取特定会话的完整历史(包含工具调用)
    history = sessions_history(
    sessionKey="main",
    includeTools=True, # 包含工具调用结果
    )

    代码说明: sessions_list 的 activeMinutes 参数过滤最近指定分钟内有活动的会话。sessions_history 默认排除工具结果以减少返回量,传入 includeTools=True 可以获取完整内容。返回的视图经过了安全过滤:凭据类文本会被脱敏,长文本块会被截断,超大历史可能丢弃旧行或替换为占位符。

    12.3 安全过滤机制

    sessions_history 返回的内容经过多层安全处理:

    • 🧹 助手文本中的思考标签(thinking tags)被剥离
    • 🧹 工具调用 XML 负载被剥离
    • 🧹 泄露的模型控制令牌被清除
    • 🔒 凭据/令牌类文本被脱敏
    • ✂️ 长文本块被截断
    • 📊 返回摘要标志(truncated、droppedMessages、contentRedacted 等)

    如果需要精确的字节级转录,应直接检查磁盘上的转录文件,而不是依赖 sessions_history 作为原始转储。

    12.4 分析维度

    分析维度数据来源关键指标
    使用频率 sessions.json 每日会话数、平均对话轮次
    资源消耗 token 计数 每会话 token 使用量、压缩触发频率
    失败模式 工具结果 工具调用失败率、超时率
    用户行为 对话内容 高频请求类型、常见问题

    十三、最佳实践与生产建议

    13.1 会话配置检查清单

    检查项推荐配置优先级
    DM 隔离 per-channel-peer 🔴 必须
    空闲重置 idleMinutes: 120 🟡 建议
    会话清理 pruneAfter: "30d" 🟡 建议
    压缩通知 notifyUser: true 🟢 可选
    剪枝 contextPruning: { mode: "cache-ttl" } 🟢 可选(Anthropic 推荐)
    压缩模型 专用摘要模型 🟢 可选
    记忆刷新 memoryFlush.model 🟢 可选

    13.2 安全审计

    # 验证会话隔离配置
    openclaw security audit

    # 预览会话清理范围
    openclaw sessions cleanup –dry-run

    # 检查会话存储状态
    openclaw status

    13.3 性能优化建议

  • 启用剪枝:如果使用 Anthropic 提供商,剪枝默认启用;其他提供商需要手动开启
  • 配置压缩模型:使用便宜的本地模型进行摘要,节省主模型成本
  • 设置 maxEntries:限制会话存储条目数,防止长期运行后存储膨胀
  • 使用后继转录:truncateAfterCompaction 避免单文件无限增长
  • 避免轮询:使用 sessions_yield 等待子 Agent 结果,而非 subagents list 循环检查
  • 13.4 常见问题排查

    问题可能原因解决方案
    压缩过于频繁 上下文窗口小或工具输出大 启用 Pruning,增大上下文窗口
    压缩后上下文感觉过时 摘要丢失了关键信息 使用 /compact 带指令引导摘要,启用内存刷新
    子 Agent 无响应 模型配置错误或超时 检查模型可用性,增加超时时间
    多用户上下文泄露 dmScope 未配置 设置 per-channel-peer
    会话存储膨胀 清理未配置 配置 pruneAfter 和 maxEntries

    十四、总结

    OpenClaw 的会话管理体系是一个精心设计的多层架构,从消息路由到上下文引擎,每个层次都提供了灵活的配置选项和合理的安全默认值。

    核心要点回顾:

  • 🏗️ 架构清晰:Session / Tool / Agent 三角关系,Gateway 统一持有状态
  • 🔒 隔离完备:从 DM 隔离到子 Agent 上下文模式,提供多级安全保障
  • ♻️ 生命周期完善:每日重置、空闲重置、手动重置三重机制,系统事件不影响过期判定
  • 🧹 上下文优化:Pruning(轻量)+ Compaction(语义)双引擎,配合可插拔的上下文引擎
  • 🧠 记忆持久:会话记忆(短期)+ 文件记忆(长期)分离,压缩前自动保存
  • 🔧 运维友好:CLI 工具完善,dry-run 预览,安全审计
  • 对于正在构建 AI Agent 系统的开发者,理解会话管理是写出可靠、安全、可扩展应用的基础。OpenClaw 的设计提供了一个优秀的参考实现——从单用户开发到多用户生产环境,它的会话管理体系都能胜任。


    📚 参考资料

    • OpenClaw 官方文档 – 会话管理
    • OpenClaw 官方文档 – 会话工具
    • OpenClaw 官方文档 – 会话剪枝
    • OpenClaw 官方文档 – 压缩
    • OpenClaw 官方文档 – 上下文引擎
    • OpenClaw 官方文档 – 代理运行时
    • OpenClaw 官方文档 – 工作空间
    • OpenClaw 官方文档 – 多代理路由

    💡 一句话总结:会话管理不是简单的"保存对话",而是状态机、隔离策略、上下文优化和持久化方案的系统工程——OpenClaw 用 Gateway 所有权模型、三时间戳设计、双引擎上下文优化和可插拔引擎架构,给出了一个值得借鉴的答案。

    赞(0)
    未经允许不得转载:171主机测评 » OpenClaw 会话管理:状态追踪与上下文深度解析
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址