会话管理
OpenClaw 将每个智能体的一个直接聊天会话视为主要会话。直接聊天折叠为 agent:<agentId>:<mainKey>(默认 main),而群组/频道聊天获得自己的键。session.mainKey 被尊重。
使用 session.dmScope 控制直接消息的分组方式:
main(默认):所有 DM 共享主会话以实现连续性。per-peer:按发送者 ID 跨通道隔离。per-channel-peer:按通道 + 发送者隔离(推荐用于多用户收件箱)。per-account-channel-peer:按账户 + 通道 + 发送者隔离(推荐用于多账户收件箱)。 使用session.identityLinks将提供商前缀的发送者 ID 映射到规范标识,以便在使用per-peer、per-channel-peer或per-account-channel-peer时,同一个人跨通道共享 DM 会话。
网关是真理的来源
所有会话状态由网关拥有("主" OpenClaw)。UI 客户端(macOS 应用、WebChat 等)必须查询网关获取会话列表和令牌计数,而不是读取本地文件。
- 在远程模式中,你关心的会话存储位于远程网关主机上,而不是你的 Mac。
- UI 中显示的令牌计数来自网关的存储字段(
inputTokens、outputTokens、totalTokens、contextTokens)。客户端不会解析 JSONL 记录来"修复"总数。
状态所在位置
- 在网关主机上:
- 存储文件:
~/.openclaw/agents/<agentId>/sessions/sessions.json(每个智能体)。
- 存储文件:
- 记录:
~/.openclaw/agents/<agentId>/sessions/<SessionId>.jsonl(Telegram 主题会话使用.../<SessionId>-topic-<threadId>.jsonl)。 - 存储是
sessionKey -> { sessionId, updatedAt, ... }的映射。删除条目是安全的;它们按需重新创建。 - 群组条目可能包含
displayName、channel、subject、room和space以在 UI 中标记会话。 - 会话条目包含
origin元数据(标签 + 路由提示),以便 UI 可以解释会话的来源。 - OpenClaw 不会读取旧的 Pi/Tau 会话文件夹。
会话修剪
OpenClaw 默认在 LLM 调用之前从内存上下文中修剪旧工具结果。 这不会重写 JSONL 历史。见/concepts/session-pruning。
压缩前内存刷新
当会话接近自动压缩时,OpenClaw 可以运行静默内存刷新轮次,提醒模型将持久笔记写入磁盘。这只在工作区可写时运行。见记忆 和压缩。
传输 → 会话键的映射
- 直接聊天遵循
session.dmScope(默认main)。main:agent:<agentId>:<mainKey>(跨设备/通道的连续性)。- 多个电话号码和通道可以映射到相同的智能体主键;它们作为到一个对话的传输。
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匹配提供商前缀的发送者 ID(例如telegram:123456789),规范键替换<peerId>,以便同一个人跨通道共享会话。
- 群组聊天隔离状态:
agent:<agentId>:<channel>:group:<id>(房间/通道使用agent:<agentId>:<channel>:channel:<id>)。- Telegram 论坛主题追加
:topic:<threadId>到群组 ID 以实现隔离。 - 旧的
group:<id>键仍被识别用于迁移。
- Telegram 论坛主题追加
- 入站上下文可能仍使用
group:<id>;通道从Provider推断并规范化为规范的agent:<agentId>:<channel>:group:<id>形式。 - 其他来源:
- Cron 作业:
cron:<job.id> - Webhook:
hook:<uuid>(除非 hook 明确设置) - 节点运行:
node-<nodeId>
- Cron 作业:
生命周期
- 重置策略:会话被重用直到过期,过期在下一条入站消息时评估。
- 每日重置:默认为网关主机本地时间凌晨 4 点。会话在其最后更新早于最近的每日重置时间时变得陈旧。
- 空闲重置(可选):
idleMinutes添加滑动空闲窗口。当同时配置每日和空闲重置时,无论哪个先过期都会强制创建新会话。 - 旧版仅空闲:如果你设置
session.idleMinutes且没有任何session.reset/resetByType配置,OpenClaw 保持仅空闲模式以实现向后兼容。 - 每类型覆盖(可选):
resetByType允许你覆盖dm、group和thread会话的策略(thread = Slack/Discord 线程、Telegram 主题、提供连接器时 Matrix 线程)。 - 每通道覆盖(可选):
resetByChannel覆盖通道的重置策略(适用于该通道的所有会话类型,优先于reset/resetByType)。 - 重置触发器:精确的
/new或/reset(加上resetTriggers中的任何额外内容)启动新的会话 ID 并传递消息的其余部分。/new <model>接受模型别名、provider/model或提供商名称(模糊匹配)以设置新会话模型。如果单独发送/new或/reset,OpenClaw 运行简短的"你好"问候轮次以确认重置。 - 手动重置:从存储中删除特定键或移除 JSONL 记录;下一条消息会重新创建它们。
- 隔离的 cron 作业始终每次运行生成新的
sessionId(不重用空闲)。
发送策略(可选)
阻止特定会话类型的传递,而无需列出单个 ID。
json5
{
session: {
sendPolicy: {
rules: [
{ action: "deny", match: { channel: "discord", chatType: "group" } },
{ action: "deny", match: { keyPrefix: "cron:" } }
],
default: "allow"
}
}
}运行时覆盖(仅所有者):
/send on→ 允许此会话/send off→ 拒绝此会话/send inherit→ 清除覆盖并使用配置规则 将这些作为独立消息发送以便注册。
配置(可选重命名示例)
json5
// ~/.openclaw/openclaw.json
{
session: {
scope: "per-sender", // 保持群组键分开
dmScope: "main", // DM 连续性(为共享收件箱设置 per-channel-peer/per-account-channel-peer)
identityLinks: {
alice: ["telegram:123456789", "discord:987654321012345678"]
},
reset: {
// 默认:mode=daily,atHour=4(网关主机本地时间)。
// 如果你也设置 idleMinutes,无论哪个过期都获胜。
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",
}
}检查
openclaw status— 显示存储路径和最近会话。openclaw sessions --json— 转储每个条目(用--active <minutes>过滤)。openclaw gateway call sessions.list --params '{}'— 从运行的网关获取会话(对远程网关访问使用--url/--token)。- 在聊天中发送
/status作为独立消息,查看智能体是否可访问、会话上下文使用了多少、当前 thinking/verbose 切换,以及你的 WhatsApp web 凭据最后刷新时间(帮助发现重新链接需求)。 - 发送
/context list或/context detail查看系统提示和注入的工作区文件中的内容(以及最大的上下文贡献者)。 - 发送
/stop作为独立消息以中止当前运行、清除该会话的排队跟进,并停止从它产生的任何子智能体运行(回复包含停止的计数)。 - 发送
/compact(可选说明)作为独立消息以总结较旧的上下文并释放窗口空间。见/concepts/compaction。 - JSONL 记录可以直接打开以查看完整轮次。
提示
- 保持主键专用于 1:1 流量;让群组保持自己的键。
- 自动化清理时,删除单个键而不是整个存储以保留其他地方的上下文。
会话来源元数据
每个会话条目记录它来自哪里(尽力而为)在 origin 中:
label:人类可读标签(从对话标签 + 群组主题/通道解析)provider:规范化通道 ID(包括扩展)from/to:入站信封中的原始路由 IDaccountId:提供商账户 ID(多账户时)threadId:线程/主题 ID(当通道支持时) 来源字段为直接消息、通道和群组填充。如果连接器仅更新传递路由(例如,保持 DM 主会话新鲜),它仍应提供入站上下文,以便会话保留其解释器元数据。扩展可以通过在入站上下文中发送ConversationLabel、GroupSubject、GroupChannel、GroupSpace和SenderName并调用recordSessionMetaFromInbound(或传递相同的上下文给updateLastRoute)来实现这一点。