OpenClaw Session 机制详解:重置、压缩、剪枝与记忆管理
通过实际踩坑案例,解析 OpenClaw 的 Session 机制。主要涵盖 Session 基础标识、生命周期(每日/空闲/手动重置)、上下文压缩(Compaction)、工具结果剪枝(Pruning)以及跨会话记忆(Memory)。重点指出默认每日重置会导致对话历史丢失,并介绍了 Memory Flush 和 Workspace 文件注入等持久化方案,帮助用户配置合理的会话策略以避免 AI 失忆。
通过实际踩坑案例,解析 OpenClaw 的 Session 机制。主要涵盖 Session 基础标识、生命周期(每日/空闲/手动重置)、上下文压缩(Compaction)、工具结果剪枝(Pruning)以及跨会话记忆(Memory)。重点指出默认每日重置会导致对话历史丢失,并介绍了 Memory Flush 和 Workspace 文件注入等持久化方案,帮助用户配置合理的会话策略以避免 AI 失忆。
事情是这样的:
我用 OpenClaw 部署了一个私人 AI 助手,接了飞书和 Web 两个渠道。白天跟它聊了一整天的项目方案,讨论了架构设计、技术选型、排期计划……信息量巨大,我很满意。
第二天早上 9 点,我发了句"继续昨天的讨论"。
它回我:
"你好!请问有什么可以帮你的?"
整个对话历史,没了。干干净净。
我当时的表情:🫠
后来我翻了文档才明白——OpenClaw 默认在凌晨 4 点重置 Session。不是 bug,是 feature。但如果你不了解这套机制,就会像我一样,被"设计如此"四个字暴击。
这篇文章,就是我把 OpenClaw 的 Session 体系从头到尾啃完之后的总结。希望能帮你少走弯路。
| 章节 | 内容 | 解决什么问题 |
|---|---|---|
| 第 1 章 | Session 基础 | 消息怎么找到"对的对话"? |
| 第 2 章 | Session 生命周期 | 什么时候开始、什么时候结束? |
| 第 3 章 | Compaction(压缩) | 上下文满了怎么办? |
| 第 4 章 | Pruning(剪枝) | 怎么省钱? |
| 第 5 章 | Memory(记忆) | 怎么跨 Session 记住东西? |
| 第 6 章 | Session Tool | 运行时怎么控制会话? |
| 第 7 章 | 实战协同 | 五个机制怎么配合工作? |
理解 Session,先搞清楚两个东西:
┌─────────────────────────────────────────────┐
│ Session Key(路由键) │
│ → "这条消息属于哪个对话桶?" │
│ │
│ 例:agent:main:main │
│ agent:main:feishu:group:oc_xxx │
│ cron:job-123 │
│ │
│ ┌─────────────────────────────────────┐ │
│ │ Session ID(对话记录) │
│ │ → "当前这轮对话的实际文件" │
│ │ │
│ │ abc123.jsonl(今天的对话) │
│ │ def456.jsonl(昨天的,已归档) │
│ │ └─────────────────────────────────────┘ │
└─────────────────────────────────────────────┘
关键理解:
| 来源 | Key 格式 | 示例 |
|---|---|---|
| 私聊(默认) | agent:<agentId>:<mainKey> | agent:main:main |
| 群组 | agent:<agentId>:<channel>:group:<id> | agent:main:feishu:group:oc_xxx |
| 频道/房间 | agent:<agentId>:<channel>:channel:<id> | agent:main:discord:channel:123 |
| 定时任务 | cron:<job.id> | cron:daily-report |
| Webhook | hook:<uuid> | hook:abc-def-123 |
这个配置决定了不同渠道的私聊是否共享同一个 Session:
| dmScope | 行为 | 适用场景 |
|---|---|---|
main(默认) | 所有私聊共享一个 session | 个人助手 |
per-peer | 按发送者隔离 | 多用户场景 |
per-channel-peer | 按渠道 + 发送者隔离 | 多渠道多用户 |
per-account-channel-peer | 按账户 + 渠道 + 发送者 | 多账户收件箱 |
💡 如果你用的是默认
main模式,飞书私聊和 webchat 私聊会共享同一个 session。
~/.openclaw/agents/<agentId>/sessions/
├── sessions.json ← Session 元数据(Key → ID 映射)
├── abc123.jsonl ← 当前对话记录
├── def456.jsonl ← 旧对话记录(重置后留下的)
└── ghi789-topic-42.jsonl ← Telegram 话题会话
消息到达 │
▼
┌──────────────┐ 是 ┌──────────────┐
│ Session 过期? │───────→│ 创建新 Session │
│ │ │ ID + JSONL │
└──────┬───────┘ └──────┬───────┘
│ 否 │
▼ ▼
┌──────────────┐ ┌──────────────┐
│ 继续使用当前 │ │ 开始新对话 │
│ Session │ │(旧上下文丢失)│
└──────┬───────┘ └──────────────┘
│
▼
[对话进行中]
│
▼
┌──────────────┐ 是 ┌──────────────┐
│ 上下文快满了? │───────→│ Memory Flush │
│ │ │(静默写日志) │
└──────┬───────┘ └──────┬───────┘
│ 否 │
▼ ▼
[继续对话] ┌──────────────┐
│ │
Auto-Compact │
▼
(压缩旧内容)
┌──────────────┐ └──────────────┘
│ 上下文溢出? │ │
│───→ 强制 Compact → 重试 └──────────────┘
{"session":{"reset":{"mode":"daily","atHour":4}}}
⚠️ 重点来了:不是到凌晨 4 点就立刻清空,而是下一条消息到来时才检查。
23:00 聊天 ──→ 凌晨 4:00(重置边界)──→ 早上 9:00 发消息 ──→ 💥 新 Session!
↑ 这时候才真正重置
这就是我踩坑的根本原因——昨晚聊的内容,在今早第一条消息时被判定为"过期",直接创建了新 Session。
{"session":{"reset":{"mode":"daily","atHour":4,"idleMinutes":120}}}
同时配置每日 + 空闲时,先到期的那个生效。
发送 /new 或 /reset 立即创建新 Session:
/new claude-sonnet → 重置并切换模型/new → 重置并发一条问候确认不同场景可以设不同策略:
{"session":{"resetByType":{"dm":{"mode":"idle","idleMinutes":480},"group":{"mode":"idle","idleMinutes":120},"thread":{"mode":"daily","atHour":4}},"resetByChannel":{"discord":{"mode":"idle","idleMinutes":10080}}}}
优先级:resetByChannel > resetByType > reset(全局默认)
每个模型有上下文窗口限制(比如 200k tokens)。聊久了,历史消息会撑满窗口。
压缩 = 把旧对话总结成摘要,腾出空间继续聊。
| 压缩(Compaction) | 重置(Reset) | |
|---|---|---|
| 触发 | 上下文快满时自动触发 | 到时间/手动触发 |
| 效果 | 旧内容变摘要,对话继续 | 创建全新 session,从零开始 |
| 连续性 | ✅ 保留(摘要形式) | ❌ 完全断开 |
| 持久化 | ✅ 摘要写入 JSONL | 旧 JSONL 保留但不再使用 |
两种情况:
contextTokens > contextWindow - reserveTokens{"compaction":{"enabled":true,"reserveTokens":16384,"keepRecentTokens":20000}}
┌─────────────────────────────────┐
│ [压缩摘要] │
│ "之前讨论了 A、B、C 三个话题..." │
├─────────────────────────────────┤
│ [保留的最近消息] │
│ 用户:xxx │
│ 助手:xxx │
│ 用户:xxx │
│ 助手:xxx │
└─────────────────────────────────┘
💡 手动压缩:发送
/compact即可触发,还可以附带指令,比如/compact 重点保留关于项目架构的讨论
| 剪枝(Pruning) | 压缩(Compaction) | |
|---|---|---|
| 作用对象 | 仅工具调用结果 | 整个对话历史 |
| 持久化 | ❌ 不修改 JSONL | ✅ 写入 JSONL |
| 触发时机 | 每次 LLM 调用前 | 上下文快满时 |
| 目的 | 省钱(减少缓存重写) | 腾空间 |
Anthropic 的提示缓存有 TTL(生存时间)。如果会话空闲超过 TTL,下次请求会重新缓存整个提示,很贵。剪枝在 TTL 过期后裁掉旧的工具结果,减少重新缓存的大小。
工具结果(很大) │
▼
┌──────────────┐
│ 软修剪 │ 保留头尾,中间用 ... 替代 │
(Soft Trim) │
└──────┬───────┘
│ 如果还是太大 ▼
┌──────────────┐
│ 硬清除 │ 整个替换为占位符 │
(Hard Clear) │
"[Old tool result content cleared]" └──────────────┘
{"agent":{"contextPruning":{"mode":"cache-ttl","ttl":"5m","keepLastAssistants":3,"softTrim":{"maxChars":4000,"headChars":1500,"tailChars":1500},"hardClear":{"enabled":true,"placeholder":"[Old tool result content cleared]"}}}}
💡 智能默认值:如果你用的是 Anthropic 的 key,OpenClaw 会自动启用
cache-ttl模式,不需要手动配。
Session 会重置、会压缩,模型的"记忆"是短暂的。Memory 系统就是解决"AI 失忆"的终极方案。
┌─────────────────────────────────────────────┐
│ 第 1 层:Session 上下文(最短暂) │
│ · 当前对话的消息历史 │
│ · 压缩后变摘要,重置后完全丢失 │
└─────────────────────────────────────────────┘
▼
写入文件
┌─────────────────────────────────────────────┐
│ 第 2 层:Workspace 文件(持久) │
│ · MEMORY.md — 长期记忆 │
│ · memory/YYYY-MM-DD.md — 每日日志 │
│ · AGENTS.md, SOUL.md 等 — 注入系统提示 │
└─────────────────────────────────────────────┘
▼
语义搜索
┌─────────────────────────────────────────────┐
│ 第 3 层:Memory Search(语义检索) │
│ · 基于 Embedding 的向量搜索 │
│ · 搜索 MEMORY.md + memory/*.md │
│ · 每次新 session 启动时可自动召回相关记忆 │
└─────────────────────────────────────────────┘
OpenClaw 会自动把 workspace 中的特定文件注入到系统提示中:
workspace/
├── AGENTS.md ← 工作规范(自动注入)
├── SOUL.md ← 人格定义(自动注入)
├── USER.md ← 用户信息(自动注入)
├── TOOLS.md ← 工具笔记(自动注入)
├── MEMORY.md ← 长期记忆(自动注入)
├── HEARTBEAT.md ← 心跳任务(自动注入)
└── memory/
├── 2026-02-07.md ← 每日日志(需搜索读取)
└── 2026-02-08.md
⚠️ 注入的文件会占用上下文窗口!
MEMORY.md太大会挤压对话空间。
上下文使用量 │
███████████████████░░░░░░ ← 软阈值(flush 触发)
████████████████████████░ ← 硬阈值(compaction 触发)
█████████████████████████ ← 上下文窗口上限
流程:
memory/YYYY-MM-DD.md{"agents":{"defaults":{"compaction":{"memoryFlush":{"enabled":true,"softThresholdTokens":4000}}}}}
| 场景 | 会触发 Flush? |
|---|---|
| 压缩前 | ✅ 会 |
| Session 重置前 | ❌ 不会! |
这就是"失忆"的根本原因:凌晨 4 点重置时,没有任何机制把昨晚的对话写入持久记忆。对话就这么没了。
| 命令 | 作用 |
|---|---|
/status | 查看当前 session 状态、token 用量 |
/new | 重置 session(可选指定模型:/new claude-sonnet) |
/compact | 手动压缩(可附带指令) |
/context list | 查看系统提示中注入了什么 |
/context detail | 详细查看上下文组成 |
/stop | 中止当前运行 + 清除队列 |
/send on/off | 控制消息发送策略 |
可以按规则阻止特定 session 的消息投递:
{"session":{"sendPolicy":{"rules":[{"action":"deny","match":{"channel":"discord","chatType":"group"}},{"action":"deny","match":{"keyPrefix":"cron:"}}],"default":"allow"}}}
用户发送消息 │
▼
[1] Session 路由 │
根据来源生成 Session Key │
检查是否过期(每日/空闲/手动重置) │
过期 → 创建新 Session ID ▼
[2] 加载上下文 │
读取 JSONL 对话记录 │
注入 workspace 文件(MEMORY.md 等) │
如果有压缩摘要,从摘要开始 ▼
[3] Session Pruning(剪枝) │
检查缓存 TTL 是否过期 │
过期 → 裁剪旧工具结果(省钱) ▼
[4] 发送给模型 → 生成回复 ▼
[5] 回复后检查 │
接近阈值 → Memory Flush(静默写日志) │
超过阈值 → Auto-Compaction(压缩) ▼
[6] 投递回复 │
检查 Send Policy → 通过则发送 ▼
[7] 写入 JSONL + 更新 sessions.json ▼
✅ 完成
可靠性 ▲
手动写入文件 ────┤ ★★★★★ 最可靠,但需要主动操作
Memory Flush ───────┤ ★★★★ 压缩前自动触发,重置前不触发
Memory Search ──────┤ ★★★ 新 session 可召回,依赖搜索质量
Compaction 摘要 ────┤ ★★ 保留大意,丢失细节
纯靠 Session ───────┤ ★ 重置就没了
└──────────→ 自动化程度
{"session":{"reset":{"mode":"daily","atHour":4,"idleMinutes":480}},"agents":{"defaults":{"compaction":{"memoryFlush":{"enabled":true,"softThresholdTokens":4000}},"memorySearch":{"enabled":true}}}}
| 概念 | 一句话 | 持久化? | 自动? |
|---|---|---|---|
| Session Reset | 创建新对话,旧上下文断开 | 旧 JSONL 保留 | ✅ 每日/空闲 |
| Compaction | 旧对话压缩成摘要 | ✅ 写入 JSONL | ✅ 上下文满时 |
| Pruning | 裁剪旧工具结果省钱 | ❌ 仅内存中 | ✅ 每次调用前 |
| Memory Flush | 压缩前静默写日志 | ✅ 写入文件 | ✅ 接近阈值时 |
| Memory Search | 语义搜索历史记忆 | N/A(读取) | 半自动 |
| Workspace 注入 | 文件内容注入系统提示 | ✅ 文件本身 | ✅ 每次加载 |
OpenClaw 的 Session 体系设计得其实很精巧——重置保证干净、压缩保证连续、剪枝保证省钱、记忆保证持久。但如果你不了解这套机制,就会在某个早晨被"你好,请问有什么可以帮你?"当头一棒。
希望这篇文章能帮你少踩一个坑。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online