会话工具

目标:提供一组小巧、不易误用的工具,让 agent 可以列出会话、获取历史记录,以及向其他会话发送消息。

工具名称

  • sessions_list
  • sessions_history
  • sessions_send
  • sessions_spawn

Key 模型

  • 主直聊 bucket 始终使用字面值 "main"(解析为当前 agent 的 main key)。
  • 群聊使用 agent:<agentId>:<channel>:group:<id>agent:<agentId>:<channel>:channel:<id>(传完整 key)。
  • 定时任务使用 cron:<job.id>
  • Hook 使用 hook:<uuid>(除非显式指定)。
  • 节点会话使用 node-<nodeId>(除非显式指定)。

globalunknown 是保留值,不会出现在列表中。如果 session.scope = "global",所有工具会将其别名为 main,调用方永远看不到 global

sessions_list

以数组形式列出会话。

参数:

  • kinds?: string[] 过滤器:"main" | "group" | "cron" | "hook" | "node" | "other" 中的任意组合
  • limit?: number 最大行数(默认:服务端默认值,上限如 200)
  • activeMinutes?: number 仅返回 N 分钟内有更新的会话
  • messageLimit?: number 0 = 不包含消息(默认 0);>0 = 包含最后 N 条消息

行为:

  • messageLimit > 0 时会为每个会话拉取 chat.history,并包含最后 N 条消息。
  • 列表输出中会过滤掉工具结果;要查看工具消息请用 sessions_history
  • 沙箱 agent 会话中运行时,会话工具默认为仅限已创建子会话的可见性(见下文)。

行格式(JSON):

  • key:会话 key(字符串)
  • kindmain | group | cron | hook | node | other
  • channelwhatsapp | telegram | discord | signal | imessage | webchat | internal | unknown
  • displayName(如有,群组显示名称)
  • updatedAt(毫秒)
  • sessionId
  • modelcontextTokenstotalTokens
  • thinkingLevelverboseLevelsystemSentabortedLastRun
  • sendPolicy(如已设置,会话级覆盖)
  • lastChannellastTo
  • deliveryContext(标准化的 { channel, to, accountId },可用时提供)
  • transcriptPath(根据 store 目录 + sessionId 推导的最佳路径)
  • messages?(仅当 messageLimit > 0 时返回)

sessions_history

获取单个会话的对话记录。

参数:

  • sessionKey(必填;接受会话 key 或 sessions_list 返回的 sessionId
  • limit?: number 最大消息数(服务端有上限)
  • includeTools?: boolean(默认 false)

行为:

  • includeTools=false 时过滤 role: "toolResult" 消息。
  • 返回原始对话格式的消息数组。
  • 传入 sessionId 时,OpenClaw 会将其解析为对应的会话 key(找不到会报错)。

sessions_send

向另一个会话发送消息。

参数:

  • sessionKey(必填;接受会话 key 或 sessions_list 返回的 sessionId
  • message(必填)
  • timeoutSeconds?: number(默认 >0;0 = 发出即忘)

行为:

  • timeoutSeconds = 0:入队并返回 { runId, status: "accepted" }
  • timeoutSeconds > 0:等待最多 N 秒,然后返回 { runId, status: "ok", reply }
  • 等待超时时:{ runId, status: "timeout", error }。运行会继续;稍后调用 sessions_history 查看结果。
  • 运行失败时:{ runId, status: "error", error }
  • 广播投递在主运行完成后执行,属于尽力而为;status: "ok" 不保证广播已送达。
  • 通过 gateway agent.wait(服务端)等待,重连不会丢失等待状态。
  • Agent 间消息上下文会注入到主运行中。
  • 跨会话消息持久化时带有 message.provenance.kind = "inter_session",这样对话记录的读取方可以区分路由的 agent 指令和外部用户输入。
  • 主运行完成后,OpenClaw 会执行回复循环
    • 第 2 轮及以后,请求方和目标 agent 交替进行。
    • 回复 REPLY_SKIP 可以中止乒乓循环。
    • 最大轮数由 session.agentToAgent.maxPingPongTurns 控制(0–5,默认 5)。
  • 循环结束后,OpenClaw 执行 agent 间广播步骤(仅目标 agent):
    • 回复 ANNOUNCE_SKIP 可以保持静默。
    • 其他回复会发送到目标渠道。
    • 广播步骤包含原始请求 + 第 1 轮回复 + 最新的乒乓回复。

Channel 字段

  • 群聊中,channel 取自会话条目中记录的渠道。
  • 直聊中,channellastChannel 映射。
  • 定时任务/Hook/节点运行中,channelinternal
  • 缺失时,channelunknown

安全 / 发送策略

基于渠道/聊天类型的策略性拦截(不按会话 ID)。

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

运行时覆盖(按会话条目):

  • sendPolicy: "allow" | "deny"(未设置 = 继承配置)
  • 可通过 sessions.patch 或仅限所有者的 /send on|off|inherit(作为独立消息发送)设置。

执行点:

  • chat.send / agent(gateway)
  • 自动回复投递逻辑

sessions_spawn

在隔离会话中启动子 agent 运行,并将结果广播回请求方聊天渠道。

参数:

  • task(必填)
  • label?(可选;用于日志/UI)
  • agentId?(可选;在允许的情况下使用其他 agent ID 创建子任务)
  • model?(可选;覆盖子 agent 模型;无效值会报错)
  • thinking?(可选;覆盖子 agent 运行的思考级别)
  • runTimeoutSeconds?(默认为 agents.defaults.subagents.runTimeoutSeconds(如已设置),否则为 0;设置后 N 秒后中止子 agent 运行)
  • thread?(默认 false;为此次 spawn 请求线程绑定路由,需渠道/插件支持)
  • mode?run|session;默认 run,但 thread=true 时默认 sessionmode="session" 要求 thread=true
  • cleanup?delete|keep,默认 keep
  • sandbox?inherit|require,默认 inheritrequire 在目标子运行时未沙箱化时拒绝 spawn)
  • attachments?(可选的内联文件数组;仅限 subagent 运行时,ACP 会拒绝)。每个条目:{ name, content, encoding?: "utf8" | "base64", mimeType? }。文件会被写入子工作空间的 .openclaw/attachments/<uuid>/ 目录。返回包含每个文件 sha256 的回执。
  • attachAs?(可选;{ mountPath? } 提示,预留给未来的挂载实现)

允许列表:

  • agents.list[].subagents.allowAgents:通过 agentId 允许的 agent ID 列表(["*"] 允许所有)。默认:仅限请求方 agent。
  • 沙箱继承守卫:如果请求方会话是沙箱化的,sessions_spawn 会拒绝目标为非沙箱运行的请求。

发现:

  • 使用 agents_list 查看 sessions_spawn 允许的 agent ID。

行为:

  • 启动一个新的 agent:<agentId>:subagent:<uuid> 会话,deliver: false
  • 子 agent 默认拥有完整工具集但去掉会话工具(可通过 tools.subagents.tools 配置)。
  • 子 agent 不能调用 sessions_spawn(不允许子 agent → 子 agent 的嵌套创建)。
  • 始终非阻塞:立即返回 { status: "accepted", runId, childSessionKey }
  • 使用 thread=true 时,渠道插件可以将投递/路由绑定到线程目标(Discord 支持由 session.threadBindings.*channels.discord.threadBindings.* 控制)。
  • 完成后,OpenClaw 执行子 agent 广播步骤并将结果发布到请求方聊天渠道。
    • 如果助手的最终回复为空,会将子 agent 历史中最新的 toolResult 作为 Result 包含进去。
  • 在广播步骤中回复 ANNOUNCE_SKIP 可以保持静默。
  • 广播回复会标准化为 Status/Result/NotesStatus 来自运行时结果(而非模型文本)。
  • 子 agent 会话在 agents.defaults.subagents.archiveAfterMinutes 后自动归档(默认:60)。
  • 广播回复包含统计行(运行时间、token 数、sessionKey/sessionId、对话记录路径,以及可选的费用)。

沙箱会话可见性

会话工具可以设置作用域来限制跨会话访问。

默认行为:

  • tools.sessions.visibility 默认为 tree(当前会话 + 已创建的子 agent 会话)。
  • 对于沙箱化会话,agents.defaults.sandbox.sessionToolsVisibility 可以硬性限制可见性。

配置:

{
  tools: {
    sessions: {
      // "self" | "tree" | "agent" | "all"
      // default: "tree"
      visibility: "tree",
    },
  },
  agents: {
    defaults: {
      sandbox: {
        // default: "spawned"
        sessionToolsVisibility: "spawned", // or "all"
      },
    },
  },
}

说明:

  • self:仅当前会话 key。
  • tree:当前会话 + 由当前会话创建的子会话。
  • agent:属于当前 agent ID 的所有会话。
  • all:所有会话(跨 agent 访问仍需 tools.agentToAgent 权限)。
  • 当会话处于沙箱模式且 sessionToolsVisibility="spawned" 时,即使你设置了 tools.sessions.visibility="all",OpenClaw 也会将可见性限制为 tree