子 Agent

子 Agent 是从现有 Agent 运行中衍生的后台运行。它们在自己的会话(agent:<agentId>:subagent:<uuid>)中运行,完成后将结果通告回请求者的聊天渠道。

斜杠命令

使用 /subagents 查看或控制当前会话的子 Agent 运行:

  • /subagents list
  • /subagents kill <id|#|all>
  • /subagents log <id|#> [limit] [tools]
  • /subagents info <id|#>
  • /subagents send <id|#> <message>
  • /subagents steer <id|#> <message>
  • /subagents spawn <agentId> <task> [--model <model>] [--thinking <level>]

线程绑定控制:

这些命令在支持持久线程绑定的渠道上工作。参见下方支持线程的渠道

  • /focus <subagent-label|session-key|session-id|session-label>
  • /unfocus
  • /agents
  • /session idle <duration|off>
  • /session max-age <duration|off>

/subagents info 显示运行元数据(状态、时间戳、会话 id、转录路径、清理方式)。

生成行为

/subagents spawn 以用户命令(而非内部中继)的方式启动后台子 Agent,完成后向请求者聊天发送一条最终完成更新。

  • spawn 命令是非阻塞的;立即返回运行 id。
  • 完成后,子 Agent 向请求者聊天渠道通告摘要/结果消息。
  • 手动生成的投递具有弹性:
    • OpenClaw 先尝试带稳定幂等性 key 的直接 agent 投递。
    • 直接投递失败则回退到队列路由。
    • 队列路由也不可用时,在最终放弃前以短指数退避重试。
  • 向请求者会话的完成交接是运行时生成的内部上下文(非用户编写的文本),包含:
    • Resultassistant 回复文本,如果为空则用最新 toolResult
    • Statuscompleted successfully / failed / timed out / unknown
    • 紧凑的运行时/token 统计
    • 投递指令,告诉请求者 Agent 用正常的助手语气改写(不要转发原始内部元数据)
  • --model--thinking 覆盖该次运行的默认值。
  • 完成后用 info/log 查看详情和输出。
  • /subagents spawn 是一次性模式(mode: "run")。需要持久线程绑定会话时,使用 sessions_spawnthread: truemode: "session"
  • ACP 沙箱会话(Codex、Claude Code、Gemini CLI)使用 sessions_spawnruntime: "acp",参见 ACP Agents

核心目标:

  • 将”研究/长任务/慢工具”并行化,不阻塞主运行。
  • 默认隔离子 Agent(会话分离 + 可选沙箱化)。
  • 让工具面难以滥用:子 Agent 默认没有会话工具。
  • 支持可配置的嵌套深度,适应编排者模式。

成本提示:每个子 Agent 有自己的上下文和 token 消耗。对于繁重或重复任务,为子 Agent 设置更便宜的模型,主 Agent 保持更高质量的模型。 可以通过 agents.defaults.subagents.model 或按 Agent 覆盖来配置。

工具

使用 sessions_spawn

  • 启动子 Agent 运行(deliver: false,全局通道:subagent
  • 然后执行通告步骤,将通告回复发到请求者聊天渠道
  • 默认模型:继承调用者,除非设置了 agents.defaults.subagents.model(或按 Agent 的 agents.list[].subagents.model);显式的 sessions_spawn.model 仍然优先。
  • 默认 thinking:继承调用者,除非设置了 agents.defaults.subagents.thinking(或按 Agent 的 agents.list[].subagents.thinking);显式的 sessions_spawn.thinking 仍然优先。
  • 默认运行超时:省略 sessions_spawn.runTimeoutSeconds 时,OpenClaw 在设置了 agents.defaults.subagents.runTimeoutSeconds 时使用该值;否则回退到 0(无超时)。

工具参数:

  • task(必需)
  • label?(可选)
  • agentId?(可选;在允许的情况下在另一个 Agent id 下生成)
  • model?(可选;覆盖子 Agent 模型;无效值被跳过,子 Agent 使用默认模型运行并在工具结果中附带警告)
  • thinking?(可选;覆盖子 Agent 运行的 thinking 级别)
  • runTimeoutSeconds?(默认取 agents.defaults.subagents.runTimeoutSeconds,否则 0;设置后子 Agent 运行在 N 秒后中止)
  • thread?(默认 false;为 true 时请求渠道线程绑定)
  • mode?run|session
    • 默认 run
    • 如果 thread: true 且省略 mode,默认变为 session
    • mode: "session" 需要 thread: true
  • cleanup?delete|keep,默认 keep
  • sandbox?inherit|require,默认 inheritrequire 在目标子运行时未沙箱化时拒绝生成)
  • sessions_spawn 接受渠道投递参数(targetchanneltothreadIdreplyTotransport)。投递请在生成的运行中使用 message/sessions_send

线程绑定会话

启用渠道的线程绑定后,子 Agent 可以保持绑定到一个线程,后续在该线程中的用户消息继续路由到同一个子 Agent 会话。

支持线程的渠道

  • Discord(目前唯一支持的渠道):支持持久的线程绑定子 Agent 会话(sessions_spawnthread: true)、手动线程控制(/focus/unfocus/agents/session idle/session max-age),以及适配器 key channels.discord.threadBindings.enabledchannels.discord.threadBindings.idleHourschannels.discord.threadBindings.maxAgeHourschannels.discord.threadBindings.spawnSubagentSessions

快速流程:

  1. sessions_spawnthread: true(可选 mode: "session")生成。
  2. OpenClaw 在活跃渠道中创建或绑定线程到该会话目标。
  3. 该线程中的回复和后续消息路由到绑定的会话。
  4. /session idle 查看/更新不活跃自动解绑,/session max-age 控制硬性时限。
  5. /unfocus 手动解绑。

手动控制:

  • /focus <target> 将当前线程(或创建一个新线程)绑定到子 Agent/会话目标。
  • /unfocus 移除当前绑定线程的绑定。
  • /agents 列出活跃运行和绑定状态(thread:<id>unbound)。
  • /session idle/session max-age 仅对焦点绑定线程有效。

配置开关:

  • 全局默认:session.threadBindings.enabledsession.threadBindings.idleHourssession.threadBindings.maxAgeHours
  • 渠道覆盖和自动绑定 key 是适配器特定的。参见上方支持线程的渠道

参见 配置参考斜杠命令 了解当前适配器详情。

白名单:

  • agents.list[].subagents.allowAgents:可通过 agentId 定位的 Agent id 列表(["*"] 允许所有)。默认:仅请求者 Agent。
  • 沙箱继承保护:如果请求者会话沙箱化,sessions_spawn 拒绝会导致不在沙箱中运行的目标。

发现:

  • 使用 agents_list 查看当前允许 sessions_spawn 定位的 Agent id。

自动归档:

  • 子 Agent 会话在 agents.defaults.subagents.archiveAfterMinutes(默认 60)后自动归档。
  • 归档使用 sessions.delete,将转录重命名为 *.deleted.<timestamp>(同文件夹)。
  • cleanup: "delete" 在通告后立即归档(仍通过重命名保留转录)。
  • 自动归档是尽力而为;Gateway 重启时待处理的计时器会丢失。
  • runTimeoutSeconds 不会自动归档;它只停止运行。会话保留直到自动归档。
  • 自动归档对深度 1 和深度 2 会话同样适用。

嵌套子 Agent

默认情况下,子 Agent 不能生成自己的子 Agent(maxSpawnDepth: 1)。你可以设置 maxSpawnDepth: 2 来启用一层嵌套,这允许编排者模式:主 Agent → 编排者子 Agent → 工作者子子 Agent。

如何启用

{
  agents: {
    defaults: {
      subagents: {
        maxSpawnDepth: 2, // 允许子 Agent 生成子代(默认 1)
        maxChildrenPerAgent: 5, // 每个 Agent 会话的最大活跃子代数(默认 5)
        maxConcurrent: 8, // 全局并发通道上限(默认 8)
        runTimeoutSeconds: 900, // sessions_spawn 省略时的默认超时(0 = 无超时)
      },
    },
  },
}

深度级别

深度会话 key 格式角色能否生成?
0agent:<id>:main主 Agent始终可以
1agent:<id>:subagent:<uuid>子 Agent(深度 2 允许时为编排者)maxSpawnDepth >= 2
2agent:<id>:subagent:<uuid>:subagent:<uuid>子子 Agent(叶子工作者)永不

通告链

结果沿链路向上传递:

  1. 深度 2 工作者完成 → 向其父级(深度 1 编排者)通告
  2. 深度 1 编排者收到通告,综合结果,完成 → 向主 Agent 通告
  3. 主 Agent 收到通告并投递给用户

每一层只看到来自直接子代的通告。

按深度的工具策略

  • 角色和控制范围在生成时写入会话元数据。这防止扁平或恢复的会话 key 意外重新获得编排者权限。
  • 深度 1(编排者,当 maxSpawnDepth >= 2:获得 sessions_spawnsubagentssessions_listsessions_history,以便管理子代。其他会话/系统工具仍被拒绝。
  • 深度 1(叶子,当 maxSpawnDepth == 1:没有会话工具(当前默认行为)。
  • 深度 2(叶子工作者):没有会话工具 — sessions_spawn 在深度 2 始终被拒绝。不能生成更多子代。

按 Agent 的生成限制

每个 Agent 会话(任何深度)最多有 maxChildrenPerAgent(默认 5)个活跃子代。这防止单个编排者的失控扇出。

级联停止

停止深度 1 的编排者会自动停止其所有深度 2 子代:

  • 主聊天中的 /stop 停止所有深度 1 Agent 并级联到其深度 2 子代。
  • /subagents kill <id> 停止特定子 Agent 并级联到其子代。
  • /subagents kill all 停止请求者的所有子 Agent 并级联。

认证

子 Agent 认证按 Agent id 解析,而非会话类型:

  • 子 Agent 会话 key 是 agent:<agentId>:subagent:<uuid>
  • 认证存储从该 Agent 的 agentDir 加载。
  • 主 Agent 的认证配置文件作为备选合并;Agent 配置文件在冲突时覆盖主配置文件。

注意:合并是追加式的,所以主配置文件始终可作为备选。目前尚不支持完全隔离的按 Agent 认证。

通告

子 Agent 通过通告步骤汇报:

  • 通告步骤在子 Agent 会话内运行(不是请求者会话)。
  • 如果子 Agent 精确回复 ANNOUNCE_SKIP,则不会发布任何内容。
  • 否则投递取决于请求者深度:
    • 顶层请求者会话使用带外部投递的后续 agent 调用(deliver=true
    • 嵌套请求者子 Agent 会话接收内部后续注入(deliver=false),以便编排者可以在会话内综合子代结果
    • 如果嵌套请求者子 Agent 会话已不存在,OpenClaw 在可用时回退到该会话的请求者
  • 构建嵌套完成发现时,子代完成聚合限定在当前请求者运行范围内,防止之前运行的陈旧子代输出泄漏到当前通告中。
  • 通告回复在渠道适配器可用时保留线程/主题路由。
  • 通告上下文被标准化为稳定的内部事件块:
    • 来源(subagentcron
    • 子会话 key/id
    • 通告类型 + 任务标签
    • 从运行时结果推导的状态行(successerrortimeoutunknown
    • 通告步骤的结果内容(缺失时为 (no output)
    • 描述何时回复 vs 保持沉默的后续指令
  • Status 不从模型输出推断;它来自运行时结果信号。

通告载荷末尾包含统计行(即使被包装时也是):

  • 运行时(如 runtime 5m12s
  • Token 使用量(输入/输出/总计)
  • 配置了模型定价时的估算成本(models.providers.*.models[].cost
  • sessionKeysessionId 和转录路径(便于主 Agent 通过 sessions_history 获取历史或在磁盘上检查文件)
  • 内部元数据仅用于编排;面向用户的回复应以正常助手语气改写。

工具策略(子 Agent 工具)

默认情况下,子 Agent 获得除会话工具外的所有工具和系统工具:

  • sessions_list
  • sessions_history
  • sessions_send
  • sessions_spawn

maxSpawnDepth >= 2 时,深度 1 的编排者子 Agent 额外获得 sessions_spawnsubagentssessions_listsessions_history,以便管理子代。

通过配置覆盖:

{
  agents: {
    defaults: {
      subagents: {
        maxConcurrent: 1,
      },
    },
  },
  tools: {
    subagents: {
      tools: {
        // deny 优先
        deny: ["gateway", "cron"],
        // 如果设置了 allow,变为仅允许模式(deny 仍然优先)
        // allow: ["read", "exec", "process"]
      },
    },
  },
}

并发

子 Agent 使用专用的进程内队列通道:

  • 通道名称:subagent
  • 并发数:agents.defaults.subagents.maxConcurrent(默认 8

停止

  • 在请求者聊天中发送 /stop 会中止请求者会话并停止从中衍生的所有活跃子 Agent 运行,级联到嵌套子代。
  • /subagents kill <id> 停止特定子 Agent 并级联到其子代。

限制

  • 子 Agent 通告是尽力而为的。Gateway 重启时,待处理的”通告回去”工作会丢失。
  • 子 Agent 仍然共享同一个 Gateway 进程资源;将 maxConcurrent 视为安全阀。
  • sessions_spawn 始终非阻塞:立即返回 { status: "accepted", runId, childSessionKey }
  • 子 Agent 上下文只注入 AGENTS.md + TOOLS.md(不含 SOUL.mdIDENTITY.mdUSER.mdHEARTBEAT.mdBOOTSTRAP.md)。
  • 最大嵌套深度为 5(maxSpawnDepth 范围 1–5)。大多数场景推荐深度 2。
  • maxChildrenPerAgent 限制每个会话的活跃子代数(默认 5,范围 1–20)。