Session Management

Session Management

适用范围

在以下情况使用此页面:

  • 修改会话处理或存储

Moltbot 将每个代理一个直接聊天会话视为主会话。直接聊天折叠到 agent:<agentId>:<mainKey>(默认 main),而群组/通道聊天获得自己的键。session.mainKey 受到尊重。

使用 session.dmScope 来控制直接消息如何分组:

  • main(默认):所有 DM 共享主会话以保持连续性。
  • per-peer:按通道的发送者 ID 隔离。
  • per-channel-peer:按通道 + 发送者隔离(推荐用于多用户收件箱)。 使用 session.identityLinks 将带提供程序前缀的对等 ID 映射到规范身份,以便同一个人在使用 per-peerper-channel-peer 时在通道之间共享 DM 会话。

网关是真实来源

所有会话状态都由网关拥有(“主” Moltbot)。UI 客户端(mac 应用、WebChat 等)必须查询网关以获取会话列表和令牌计数,而不是读取本地文件。

  • 远程模式中,您关心的会话存储位于远程网关主机上,而不是您的 Mac 上。
  • UI 中显示的令牌计数来自网关的存储字段(inputTokensoutputTokenstotalTokenscontextTokens)。客户端不解析 JSONL 记录来"修复"总数。

状态所在位置

  • 网关主机上:
    • 存储文件:~/.moltbot/agents/<agentId>/sessions/sessions.json(每个代理)。
  • 记录:~/.moltbot/agents/<agentId>/sessions/<SessionId>.jsonl(Telegram 主题会话使用 .../<SessionId>-topic-<threadId>.jsonl)。
  • 存储是映射 sessionKey -> { sessionId, updatedAt, ... }。删除条目是安全的;它们按需重新创建。
  • 群组条目可能包括 displayNamechannelsubjectroomspace 以在 UI 中标记会话。
  • 会话条目包括 origin 元数据(标签 + 路由提示),以便 UI 可以解释会话的来源。
  • Moltbot 读取传统的 Pi/Tau 会话文件夹。

会话修剪

默认情况下,Moltbot 在 LLM 调用之前从内存上下文中修剪旧工具结果。 这不会重写 JSONL 历史记录。请参阅 /concepts/session-pruning

压缩前内存刷新

当会话接近自动压缩时,Moltbot 可以运行静默内存刷新轮次,提醒模型将持久的笔记写入磁盘。这仅在工作空间可写时运行。请参阅 内存压缩

映射传输 → 会话键

  • 直接聊天遵循 session.dmScope(默认 main)。
    • mainagent:<agentId>:<mainKey>(跨设备/通道的连续性)。
      • 多个电话号码和通道可以映射到同一个代理主键;它们充当一个对话的传输。
    • per-peeragent:<agentId>:dm:<peerId>
    • per-channel-peeragent:<agentId>:<channel>:dm:<peerId>
    • 如果 session.identityLinks 匹配带提供程序前缀的对等 ID(例如 telegram:123),规范键将替换 <peerId>,以便同一个人在通道之间共享会话。
  • 群聊隔离状态:agent:<agentId>:<channel>:group:<id>(房间/通道使用 agent:<agentId>:<channel>:channel:<id>)。
    • Telegram 论坛主题将 :topic:<threadId> 附加到群组 ID 以进行隔离。
    • 传统的 group:<id> 键仍被识别以进行迁移。
  • 入站上下文可能仍使用 group:<id>;通道从 Provider 推断并规范化为规范的 agent:<agentId>:<channel>:group:<id> 形式。
  • 其他来源:
    • Cron 作业:cron:<job.id>
    • Webhooks:hook:<uuid>(除非由挂钩明确设置)
    • 节点运行:node-<nodeId>

生命周期

  • 重置策略:会话被重复使用直到过期,过期在下一条入站消息时评估。
  • 每日重置:默认为网关主机本地时间凌晨 4:00。一旦会话的最后更新早于最近的每日重置时间,会话就会过时。
  • 空闲重置(可选):idleMinutes 添加滑动空闲窗口。当同时配置了每日和空闲重置时,首先过期的那个强制新会话。
  • 传统仅空闲:如果您在没有 session.reset/resetByType 配置的情况下设置 session.idleMinutes,Moltbot 会保持仅空闲模式以实现向后兼容。
  • 每类型覆盖(可选):resetByType 允许您覆盖 dmgroupthread 会话的策略(thread = Slack/Discord 线程、Telegram 主题、连接器提供的 Matrix 线程)。
  • 每通道覆盖(可选):resetByChannel 覆盖通道的重置策略(适用于该通道的所有会话类型,优先于 reset/resetByType)。
  • 重置触发器:精确的 /new/reset(加上 resetTriggers 中的任何额外内容)开始一个新的会话 ID 并传递消息的剩余部分。/new <model> 接受模型别名、provider/model 或提供程序名称(模糊匹配)来设置新会话模型。如果单独发送 /new/reset,Moltbot 会运行一个简短的"你好"问候轮次以确认重置。
  • 手动重置:从存储中删除特定键或删除 JSONL 记录;下一条消息重新创建它们。
  • 隔离的 cron 作业每次运行总是铸造新的 sessionId(没有空闲重用)。

发送策略(可选)

阻止特定会话类型的传递而无需列出单个 ID。

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

运行时覆盖(仅所有者):

  • /send on → 允许此会话
  • /send off → 拒绝此会话
  • /send inherit → 清除覆盖并使用配置规则 将这些作为独立消息发送,以便它们注册。

配置(可选重命名示例)

// ~/.moltbot/moltbot.json
{
  session: {
    scope: "per-sender",      // keep group keys separate
    dmScope: "main",          // DM continuity (set per-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: "~/.moltbot/agents/{agentId}/sessions/sessions.json",
    mainKey: "main",
  }
}

检查

  • moltbot status — 显示存储路径和最近的会话。
  • moltbot sessions --json — 转储每个条目(使用 --active <minutes> 过滤)。
  • moltbot gateway call sessions.list --params '{}' — 从运行的网关获取会话(使用 --url/--token 进行远程网关访问)。
  • 在聊天中发送 /status 作为独立消息,以查看代理是否可访问、使用了多少会话上下文、当前的思考/详细切换以及 WhatsApp web 凭据最后刷新的时间(有助于发现重新链接的需求)。
  • 发送 /context list/context detail 以查看系统提示和注入的工作空间文件中的内容(以及最大的上下文贡献者)。
  • 发送 /stop 作为独立消息以中止当前运行,清除该会话的排队后续,并停止从它生成的任何子代理运行(回复包括停止的计数)。
  • 发送 /compact(可选说明)作为独立消息以总结较旧的上下文并释放窗口空间。请参阅 /concepts/compaction
  • 可以直接打开 JSONL 记录以查看完整的轮次。

提示

  • 将主键专用于 1:1 流量;让群组保持自己的键。
  • 自动化清理时,删除单个键而不是整个存储以保留其他地方的上下文。

会话来源元数据

每个会话条目在 origin 中记录其来源(尽力而为):

  • label:人类标签(从对话标签 + 群组主题/通道解析)
  • provider:规范通道 ID(包括扩展)
  • from/to:来自入站信封的原始路由 ID
  • accountId:提供程序帐户 ID(多帐户时)
  • threadId:通道支持时的线程/主题 ID 来源字段为直接消息、通道和群组填充。如果连接器仅更新传递路由(例如,为了保持 DM 主会话新鲜),它仍应提供入站上下文,以便会话保留其解释器元数据。扩展可以通过在入站上下文中发送 ConversationLabelGroupSubjectGroupChannelGroupSpaceSenderName 并调用 recordSessionMetaFromInbound(或将相同的上下文传递给 updateLastRoute)来做到这一点。