“近期将连续发布《从OpenClaw源码分析小龙虾是如何工作的?》,本系列一共十篇文章。 主题为:概览与调试环境搭建->Gateway中央控制器->Session管理分析->提示词上下文分析->ReAct 原理与 pi-mono 源码分析->定时任务与心跳机制->记忆系统分析->Skill 体系分析->Channel 系统分析->自我进化机制。
第3篇:Session 管理分析
一、Session 是什么?
在 OpenClaw 中,Session = 对话上下文(SessionEntry 元数据 + transcript 对话记录)
简单来说,Session 就是一个 KV 数据结构,用于记录和管理每一次对话的完整上下文。每个用户、每个群组、每个私聊窗口都有自己的 Session。
二、Session 整体架构
调用端就是涉及到会话调用的地方,包括回复、pi-agent、CLI、websocket、channel等。 会话管理提供session检索和key管理,key就是用来区分哪个会话的。 session存储引擎提供会话保持、会话存储路径、会话数据结构、转录等功能。 磁盘存储提供会话持久化功能,会话相关数据被保存到磁盘制定文件中。

三、Session Key格式与解析
Session Key 是区分不同会话的唯一标识符,格式为:
[agent]:[agentId]:[scope-specific]Session Key 的处理逻辑如下:
resolveSessionKey(scope, ctx, mainKey) │ ├─ ctx.SessionKey 显式指定? → 直接返回 │ ├─ scope === "global"? → 返回 "global" │ ├─ 群组? (detected by resolveGroupSessionKey) │ ├─ 格式: "agent:{agentId}:{channel}:group:{groupId}" │ ├─ 示例: "agent:main:telegram:group:12345678" │ └─ 组名计算: buildGroupDisplayName() │ └─ 私聊? ├─ normalizeMainKey(mainKey) 默认 "main" └─ buildAgentMainSessionKey(agentId, mainKey) → "agent:main:main" (默认) DM 子模式 (buildAgentPeerSessionKey): ├─ "per-peer": "agent:main:direct:{peerId}" ├─ "per-channel-peer": "agent:main:{channel}:direct:{peerId}" ├─ "per-account-channel-peer": "agent:main:{channel}:{accountId}:direct:{peerId}" └─ "main" (默认): "agent:main:main"
以下是不同场景下的 Session Key 示例。
// 1. Web 聊天(默认)sessionKey = "agent:main:main"// 2. Telegram 群组sessionKey = "agent:main:telegram:group:-1001234567890"// 3. Telegram 私聊(per-peer 模式)sessionKey = "agent:main:direct:123456789"// 4. 飞书群组sessionKey = "agent:main:feishu:group:oc_xxx"// 5. 全局配置会话sessionKey = "global"四、两个核心存储文件
OpenClaw 的 Session 数据分两个文件存储,职责分离。
4.1 sessions.json —— 会话索引
文件路径:~/.openclaw/agents/<agentId>/sessions/sessions.json
特点:
K-V 结构:key 是 sessionKey,value 是 SessionEntry 元数据 轻量级:只存元数据,不存对话内容 频繁读写:每次入站消息都要读(检查是否存在/新鲜度),每次回复完成都要写(更新 token/路由) 文件锁保护:写入时创建 .lock文件防止并发冲突自动维护:写入时自动清理过期条目、控制数量上限、文件轮转
自动维护规则:
.bak 备份 |

4.2 {sessionId}.jsonl —— 对话记录
文件路径:~/.openclaw/agents/<agentId>/sessions/{uuid}.jsonl
特点:
APPEND-ONLY:每次对话轮次追加一行,不修改已有内容 JSONL 格式:每行独立 JSON,方便流式读取和按行解析 由 pi-coding-agent 管理:通过 @mariozechner/pi-coding-agent的SessionManager进行读写用于上下文注入:AI 执行时从这个文件读取历史对话,构建 system prompt 的上下文 IO 频率较低:只有 AI 完成一次回复后才写入
数据结构示例(每一行是一个 JSON 对象):
4.3 两个文件的职责对比
| 存储内容 | ||
| 数据结构 | ||
| 读写模式 | ||
| 读写频率 | ||
| 管理方 | ||
| 用途 |

五、会话新鲜度评估与重置策略
OpenClaw 支持灵活的会话重置策略,避免会话过长导致上下文溢出或行为异常。
5.1 配置示例
{"session": {// 会话重置模式"reset": {"mode": "daily", // daily | idle"atHour": 4, // 每日重置时间(本地时间)"idleMinutes": 60// 空闲多少分钟后重置 },// 按类型覆盖重置策略"resetByType": {"thread": { "mode": "daily", "atHour": 4 },"direct": { "mode": "idle", "idleMinutes": 240 },"group": { "mode": "idle", "idleMinutes": 120 } },// 线程绑定超时"threadBindings": {"enabled": true,"idleHours": 24, // 线程空闲多少小时自动解绑"maxAgeHours": 0// 线程最大存活小时数(0=不限制) } }}
5.2 重置模式详解
daily | ||
idle |
5.3 按类型的策略覆盖
thread | ||
direct | ||
group |
六、会话文件维护机制
6.1 两种维护模式
warn | ||
enforce |
6.2 enforce 模式的具体动作
// 简化代码示意functionenforceSessionMaintenance() {// 1. 删除超过 30 天未更新的 session pruneStaleEntries();// 2. 保留最近活跃的 500 个 session capEntryCount(500);// 3. 文件超过 10 MB 自动轮转,保留 3 个 .bak 备份 rotateSessionFile(10 * 1024 * 1024, 3);}
七、一个请求的会话流转全过程
接收来自任意 Channel Plugin(Telegram、飞书、微信、钉钉、WhatsApp、Slack 等)的原始消息。 dispatchInboundMessage() 负责标准化接收到的信息并进行路由分发。 getReplyFromConfig()先确定消息是谁发的、用什么 agent 处理、模型是什么,这些信息会被带到 session 初始化阶段。 initSessionState()负责初始化会话,包括推导session key,加载磁盘中的会话,评估会话是否过期,构建session元数据,最后持久化到sessions.json中。 runReplyAgent()实际上就是pi-agent负责智能体交互并将相关对话信息转录到uuid.jsonl文件中。 回复投递就是将最终生成的回复返回到相应的channel中。

小结
Session 管理就是 OpenClaw 对会话过程的管理。
灵活的 Key 设计:支持全局、群组、私聊等多种会话隔离策略 双文件存储: sessions.json(元数据索引)+{uuid}.jsonl(对话记录),职责分离自动维护:过期清理、数量上限、文件轮转,无需人工干预 新鲜度评估:支持 daily/idle 两种重置模式,避免上下文过长 完整流转链路:从用户消息到回复返回,Session 贯穿始终
下一篇讲提示词上下文分析。
夜雨聆风