欢迎光临
我们一直在努力

我和 AI 聊了一晚上,第二天它说“你好,请问有什么可以帮你?“凌晨我的 AI 尽然悄悄把记忆清空了!——OpenClaw Session 完全生存指南:重置、压缩、剪枝、记忆一网打尽

凌晨4点,我的 AI 悄悄把记忆清空了——OpenClaw Session 避坑指南

摘要:用 OpenClaw 搭了个 AI 助手,聊得好的,第二天一早它就"失忆"了?本文从一个真实踩坑出发,系统拆解 OpenClaw 的 Session 机制——重置(Reset)、压缩(Compaction)、剪枝(Pruning)、记忆(Memory)、会话控制(Session Tool)——帮你彻底搞懂"对话为什么会消失"以及"怎么让 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章 实战协同 五个机制怎么配合工作?

第1章 · Session 基础——消息怎么找到"对的对话"

核心概念:两层标识

理解 Session,先搞清楚两个东西:

┌─────────────────────────────────────────────┐
│ Session Key(路由键) │
│ → "这条消息属于哪个对话桶?" │
│ │
│ 例: agent:main:main │
│ agent:main:feishu:group:oc_xxx │
│ cron:job-123 │
│ │
│ ┌─────────────────────────────────────┐ │
│ │ Session ID(对话记录) │ │
│ │ → "当前这轮对话的实际文件" │ │
│ │ │ │
│ │ abc123.jsonl(今天的对话) │ │
│ │ def456.jsonl(昨天的,已归档) │ │
│ └─────────────────────────────────────┘ │
└─────────────────────────────────────────────┘

关键理解:

  • Session Key 是固定的,决定消息路由到哪个"桶"
  • Session ID 会变,每次重置就换一个新的 JSONL 文件
  • 重置 ≠ 删除——旧 JSONL 文件还在磁盘上,只是模型不再读取

Session Key 的生成规则

来源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

私聊的 dmScope 模式

这个配置决定了不同渠道的私聊是否共享同一个 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 话题会话


第2章 · Session 生命周期——什么时候开始、什么时候结束

生命周期全景图

消息到达


┌──────────────┐ 是 ┌──────────────┐
│ 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(全局默认)


第3章 · Compaction(压缩)——上下文满了怎么办

为什么需要压缩?

每个模型有上下文窗口限制(比如 200k tokens)。聊久了,历史消息会撑满窗口。

压缩 = 把旧对话总结成摘要,腾出空间继续聊。

压缩 vs 重置

压缩(Compaction)重置(Reset)
触发 上下文快满时自动触发 到时间/手动触发
效果 旧内容变摘要,对话继续 创建全新 session,从零开始
连续性 ✅ 保留(摘要形式) ❌ 完全断开
持久化 ✅ 摘要写入 JSONL 旧 JSONL 保留但不再使用

自动压缩触发条件

两种情况:

  • 溢出恢复:模型返回上下文溢出错误 → 压缩 → 重试
  • 阈值维护:成功回复后检查 contextTokens > contextWindow – reserveTokens
  • 配置

    {
    "compaction": {
    "enabled": true,
    "reserveTokens": 16384,
    "keepRecentTokens": 20000
    }
    }

    压缩后模型看到什么?

    ┌─────────────────────────────────┐
    │ [压缩摘要] │
    │ "之前讨论了 A、B、C 三个话题…" │
    ├─────────────────────────────────┤
    │ [保留的最近消息] │
    │ 用户: xxx │
    │ 助手: xxx │
    │ 用户: xxx │
    │ 助手: xxx │
    └─────────────────────────────────┘

    💡 手动压缩:发送 /compact 即可触发,还可以附带指令,比如 /compact 重点保留关于项目架构的讨论


    第4章 · Session Pruning(剪枝)——省钱的隐形优化

    剪枝 vs 压缩

    剪枝(Pruning)压缩(Compaction)
    作用对象 仅工具调用结果 整个对话历史
    持久化 ❌ 不修改 JSONL ✅ 写入 JSONL
    触发时机 每次 LLM 调用前 上下文快满时
    目的 省钱(减少缓存重写) 腾空间

    为什么需要剪枝?

    Anthropic 的提示缓存有 TTL(生存时间)。如果会话空闲超过 TTL,下次请求会重新缓存整个提示,很贵。剪枝在 TTL 过期后裁掉旧的工具结果,减少重新缓存的大小。

    两个级别

    工具结果(很大)


    ┌──────────────┐
    │ 软修剪 │ 保留头尾,中间用 … 替代
    │ (Soft Trim) │
    └──────┬───────┘
    │ 如果还是太大

    ┌──────────────┐
    │ 硬清除 │ 整个替换为占位符
    │ (Hard Clear) │ "[Old tool result content cleared]"
    └──────────────┘

    什么不会被剪枝?

    • ❌ 用户消息——永不修改
    • ❌ 助手消息——永不修改
    • ❌ 包含图片的工具结果——跳过
    • ❌ 最近 N 条助手消息之后的工具结果——受保护

    配置

    {
    "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 模式,不需要手动配。


    第5章 · Memory(记忆)——跨 Session 的持久化方案

    核心问题

    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 启动时可自动召回相关记忆 │
    └─────────────────────────────────────────────┘

    Workspace 文件注入

    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 太大会挤压对话空间。

    压缩前记忆刷新(Memory Flush)⭐ 最聪明的设计

    上下文使用量
    │ ████████████████████░░░░░░ ← 软阈值(flush 触发)
    │ █████████████████████████░ ← 硬阈值(compaction 触发)
    │ ██████████████████████████ ← 上下文窗口上限

    流程:

  • 上下文接近压缩阈值(但还没到)
  • OpenClaw 静默运行一轮,让模型把重要内容写入 memory/YYYY-MM-DD.md
  • 用户看不到这个过程
  • 然后正常触发压缩
  • {
    "agents": {
    "defaults": {
    "compaction": {
    "memoryFlush": {
    "enabled": true,
    "softThresholdTokens": 4000
    }
    }
    }
    }
    }

    ⚠️ Memory Flush 的致命盲区

    场景会触发 Flush?
    压缩前 ✅ 会
    Session 重置前 ❌ 不会!

    这就是"失忆"的根本原因:凌晨4点重置时,没有任何机制把昨晚的对话写入持久记忆。对话就这么没了。


    第6章 · Session Tool——运行时的会话控制

    常用命令

    命令作用
    /status 查看当前 session 状态、token 用量
    /new 重置 session(可选指定模型:/new claude-sonnet)
    /compact 手动压缩(可附带指令)
    /context list 查看系统提示中注入了什么
    /context detail 详细查看上下文组成
    /stop 中止当前运行 + 清除队列
    /send on/off 控制消息发送策略

    Send Policy(发送策略)

    可以按规则阻止特定 session 的消息投递:

    {
    "session": {
    "sendPolicy": {
    "rules": [
    { "action": "deny", "match": { "channel": "discord", "chatType": "group" } },
    { "action": "deny", "match": { "keyPrefix": "cron:" } }
    ],
    "default": "allow"
    }
    }
    }


    第7章 · 实战:五个机制如何协同工作

    一条消息的完整旅程

    用户发送消息


    [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 体系设计得其实很精巧——重置保证干净、压缩保证连续、剪枝保证省钱、记忆保证持久。但如果你不了解这套机制,就会在某个早晨被"你好,请问有什么可以帮你?"当头一棒。

    希望这篇文章能帮你少踩一个坑。

    如果对你有帮助,点个赞收个藏,我后续还会更新 OpenClaw 的其他深度拆解。


    📌 声明:本文基于个人学习和实践整理,如有错误欢迎指正。


    赞(0)
    未经允许不得转载:171主机测评 » 我和 AI 聊了一晚上,第二天它说“你好,请问有什么可以帮你?“凌晨我的 AI 尽然悄悄把记忆清空了!——OpenClaw Session 完全生存指南:重置、压缩、剪枝、记忆一网打尽
    分享到: 更多 (0)

    评论 抢沙发

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