Session 管理(Session Management)
Moltbot 将 每个 agent 的一条私聊(direct-chat)主会话视为主路径。私聊默认会折叠为 agent:<agentId>:<mainKey>(默认 main),而群聊/频道聊天会拥有各自独立的 keys。session.mainKey 会被遵循。
使用 session.dmScope 控制**私信(direct messages)**如何分组:
main(默认):所有私信共享主 session,以保证连续性。per-peer:按发送者 id 在跨渠道范围内隔离。per-channel-peer:按 channel + sender 隔离(推荐用于多用户收件箱)。per-account-channel-peer:按 account + channel + sender 隔离(推荐用于多账号收件箱)。
使用 session.identityLinks 将带 provider 前缀的 peer id 映射到一个规范化身份,这样在 per-peer、per-channel-peer 或 per-account-channel-peer 下,同一个人可以跨渠道共享同一条 DM session。
Gateway 是唯一事实来源
所有 session 状态都 由 gateway 持有(“主” Moltbot)。UI clients(macOS app、WebChat 等)必须向 gateway 查询 session 列表与 token 计数,而不是读取本地文件。
- 在 remote mode 下,你关心的 session store 位于远端 gateway host 上,而不是你的 Mac。
- UI 中展示的 token 计数来自 gateway store 的字段(
inputTokens、outputTokens、totalTokens、contextTokens)。clients 不会解析 JSONL transcripts 去“修正”总计。
状态存放位置
- 在 gateway host 上:
- Store 文件:
~/.openclaw/agents/<agentId>/sessions/sessions.json(每个 agent 一份)。
- Store 文件:
- Transcripts:
~/.openclaw/agents/<agentId>/sessions/<SessionId>.jsonl(Telegram topic sessions 使用.../<SessionId>-topic-<threadId>.jsonl)。 - Store 是一个
sessionKey -> { sessionId, updatedAt, ... }的 map。删除条目是安全的;需要时会按需重建。 - Group 条目可能包含
displayName、channel、subject、room、space,用于在 UI 中标记 sessions。 - Session 条目包含
origin元数据(label + 路由提示),便于 UI 解释 session 的来源。 - Moltbot 不会读取旧版 Pi/Tau 的 session 目录。
Session pruning
Moltbot 默认会在每次 LLM 调用之前,针对内存上下文裁剪(trim)旧的 tool results。 这不会重写 JSONL 历史。参见 /concepts/session-pruning。
Compaction 前的 memory flush
当 session 接近自动 compaction 时,Moltbot 可以运行一次静默的 memory flush回合,提醒模型把可持久化的笔记写入磁盘。该步骤仅在 workspace 可写时运行。参见 Memory 与 Compaction。
Transport → session keys 映射
- 私聊遵循
session.dmScope(默认main)。main:agent:<agentId>:<mainKey>(跨设备/渠道保持连续性)。- 多个电话号码与渠道可以映射到同一个 agent main key;它们相当于同一对话的多条“传输通道”。
per-peer:agent:<agentId>:dm:<peerId>。per-channel-peer:agent:<agentId>:<channel>:dm:<peerId>。per-account-channel-peer:agent:<agentId>:<channel>:<accountId>:dm:<peerId>(accountId默认default)。- 如果
session.identityLinks命中某个带 provider 前缀的 peer id(例如telegram:123),则会用规范化 key 替换<peerId>,从而让同一个人跨渠道共享 session。
- 群聊会隔离状态:
agent:<agentId>:<channel>:group:<id>(rooms/channels 使用agent:<agentId>:<channel>:channel:<id>)。- Telegram forum topics 会在 group id 末尾追加
:topic:<threadId>用于隔离。 - 旧版
group:<id>keys 仍会被识别以支持迁移。
- Telegram forum topics 会在 group id 末尾追加
- 入站上下文仍可能使用
group:<id>;channel 会从Provider推断并规范化为agent:<agentId>:<channel>:group:<id>。 - 其他来源:
- Cron jobs:
cron:<job.id> - Webhooks:
hook:<uuid>(除非 hook 显式设置) - Node runs:
node-<nodeId>
- Cron jobs:
生命周期(Lifecycle)
- 重置策略:session 会一直复用直到过期;是否过期会在下一条入站消息到来时评估。
- 每日重置:默认是 gateway host 本地时间的凌晨 4:00。当 session 上次更新时间早于最近一次“每日重置时间点”时,该 session 视为 stale。
- 空闲重置(可选):
idleMinutes提供一个滑动空闲窗口。当同时配置了 daily 与 idle 时,先过期的那条规则会强制创建新 session。 - 仅空闲(legacy):如果你只设置了
session.idleMinutes而没有任何session.reset/resetByType配置,Moltbot 会保持 idle-only 模式以兼容旧行为。 - 按类型覆盖(可选):
resetByType允许你分别为dm、group与threadsessions 覆盖策略(thread = Slack/Discord threads、Telegram topics、Matrix threads(当 connector 提供时))。 - 按渠道覆盖(可选):
resetByChannel覆盖某个 channel 的重置策略(对该 channel 的全部 session types 生效,并优先于reset/resetByType)。 - 重置触发:精确匹配的
/new或/reset(以及resetTriggers中额外的触发词)会创建新的 session id,并将消息余下部分继续传入。/new <model>支持 model alias、provider/model或 provider 名称(模糊匹配)来设置新 session 的模型。如果/new或/reset单独发送(没有附加文本),Moltbot 会运行一段简短的 “hello” 问候回合以确认重置。 - 手动重置:从 store 中删除指定 keys,或移除 JSONL transcript;下一条消息会重建它们。
- 隔离的 cron jobs 总是每次 run 生成新的
sessionId(不复用 idle session)。
发送策略(Send policy,可选)
无需列举具体 id,也可以按 session 类型阻止投递。
{
session: {
sendPolicy: {
rules: [
{ action: "deny", match: { channel: "discord", chatType: "group" } },
{ action: "deny", match: { keyPrefix: "cron:" } }
],
default: "allow"
}
}
}运行时覆盖(仅 owner):
/send on→ 对当前 session 允许发送/send off→ 对当前 session 禁止发送/send inherit→ 清除覆盖并回退到配置规则
请把它们作为独立消息发送,以便正确注册。
配置(可选:重命名示例)
// ~/.openclaw/moltbot.json
{
session: {
scope: "per-sender", // keep group keys separate
dmScope: "main", // DM continuity (set per-channel-peer/per-account-channel-peer for shared inboxes)
identityLinks: {
alice: ["telegram:123456789", "discord:987654321012345678"]
},
reset: {
// Defaults: mode=daily, atHour=4 (gateway host local time).
// If you also set idleMinutes, whichever expires first wins.
mode: "daily",
atHour: 4,
idleMinutes: 120
},
resetByType: {
thread: { mode: "daily", atHour: 4 },
dm: { mode: "idle", idleMinutes: 240 },
group: { mode: "idle", idleMinutes: 120 }
},
resetByChannel: {
discord: { mode: "idle", idleMinutes: 10080 }
},
resetTriggers: ["/new", "/reset"],
store: "~/.openclaw/agents/{agentId}/sessions/sessions.json",
mainKey: "main",
}
}如何检查(Inspecting)
moltbot status— 显示 store 路径与最近 sessions。moltbot sessions --json— 输出所有条目(可用--active <minutes>过滤)。moltbot gateway call sessions.list --params '{}'— 从运行中的 gateway 拉取 sessions(remote gateway 时使用--url/--token)。- 在聊天中单独发送
/status,查看 agent 是否可达、session context 使用量、当前 thinking/verbose 开关,以及 WhatsApp web 凭据最近刷新时间(便于发现需要重新绑定)。 - 发送
/context list或/context detail查看 system prompt 与注入的 workspace files(以及最大的 context 贡献者)。 - 单独发送
/stop中止当前 run,清除该 session 的排队 followups,并停止由它派生的所有子 agent runs(回复会包含停止数量)。 - 单独发送
/compact(可附加说明)以总结旧上下文并释放窗口空间。参见 /concepts/compaction。 - 可以直接打开 JSONL transcripts 来审阅完整回合。
小贴士
- 保持主 key 专用于 1:1;让群聊保留自己的 keys。
- 做自动化清理时,优先删除单个 key,而不是整个 store,以保留其他对话上下文。
Session origin 元数据
每个 session 条目会尽力在 origin 中记录来源信息:
label:给人看的标签(由 conversation label + group subject/channel 解析)provider:规范化后的 channel id(含扩展)from/to:入站 envelope 中的原始路由 idsaccountId:provider account id(多账号时)threadId:渠道支持 threads/topics 时的 thread/topic id
这些 origin 字段会为私信、channels 与 groups 填充。如果某个 connector 只更新了投递路由(例如,为了让 DM main session 保持活跃),它仍应提供入站上下文,以便 session 保留其“解释性”元数据。扩展可以在入站上下文中发送 ConversationLabel、GroupSubject、GroupChannel、GroupSpace 与 SenderName,并调用 recordSessionMetaFromInbound(或把相同的上下文传给 updateLastRoute)来做到这一点。