概述

Sub-agents 是从现有 Agent 运行中派生的后台 Agent 运行,在独立会话(agent:<agentId>:subagent:<uuid>)中执行,完成后将结果通知回请求方聊天频道。每个 sub-agent 运行作为后台任务追踪。

核心设计目标:

  • 并行化”研究/长任务/慢工具”工作,不阻塞主运行
  • 默认隔离(会话分离 + 可选沙箱)
  • 工具面难以误用:子 Agent 默认不获得 session 工具
  • 支持可配置嵌套深度(编排器模式)

三个核心工具

sessions_spawn

启动一个 sub-agent 运行,立即返回 { status: "accepted", runId, childSessionKey },非阻塞。

可用性:coding 和 full 工具 profile 默认暴露;messaging profile 不包含,需手动添加:

tools: { alsoAllow: ["sessions_spawn", "sessions_yield", "subagents"] }

完整参数:

参数类型默认值说明
taskstring必填子 Agent 的任务描述
taskNamestring—稳定的编排句柄,用于后续 steer/kill 定位,格式 [a-z][a-z0-9_]{0,63}
labelstring—人类可读标签
agentIdstring—目标 Agent ID(受 allowAgents 限制)
runtime"subagent" | "acp""subagent"acp 仅用于外部 ACP harness
resumeSessionIdstring—仅 ACP:恢复已有 ACP 会话
streamTo"parent"—仅 ACP:将输出流式传给父会话
modelstring继承调用方覆盖子 Agent 模型
thinkingstring继承调用方覆盖 thinking 级别
runTimeoutSecondsnumber0(无超时)超时后中止运行
threadbooleanfalse是否绑定 channel 线程
mode"run" | "session""run""session" 需要 thread: true
cleanup"delete" | "keep""keep""delete" 在 announce 后立即归档
sandbox"inherit" | "require""inherit""require" 拒绝非沙箱目标
context"isolated" | "fork""isolated""fork" 将调用方 transcript 分支到子会话

注意:sessions_spawn 不接受投递参数(target、channel、to、threadId 等),投递由子 Agent 自己用 message/sessions_send 完成。

sessions_yield

结束当前 model turn,等待子 Agent 完成事件作为下一条消息到达。

  • 这是等待子 Agent 完成的唯一正确方式,禁止用轮询(subagents、sessions_list、sessions_history、sleep)替代
  • 当有活跃子 Agent 时,OpenClaw 会在普通 turn 中注入 Active Subagents 提示块,无需轮询即可看到状态
  • 某些精简 profile 可能有 sessions_spawn 但没有 sessions_yield,此时不要发明轮询循环

subagents

列出、引导或终止当前请求方会话拥有的子 Agent 运行,作用域限于当前请求方(子 Agent 只能看到/控制自己的子 Agent)。

用于按需状态查看、调试、引导或终止,不用于等待完成。


上下文模式

模式适用场景行为
isolated(默认)新鲜研究、独立实现、慢工具工作,可在 task 文本中简要说明创建干净的子 transcript,token 消耗更低
fork依赖当前对话、已有工具结果或调用方 transcript 中细微指令的工作将调用方 transcript 分支到子会话后再启动

线程绑定的 spawn 默认使用 fork;非线程 spawn 默认使用 isolated。


嵌套 Sub-agents(编排器模式)

默认子 Agent 不能再派生子 Agent(maxSpawnDepth: 1)。设置 maxSpawnDepth: 2 启用一级嵌套:

主 Agent (depth 0)
  └── 编排 sub-agent (depth 1)  ← 可以派生子 Agent
        ├── 工作 sub-sub-agent (depth 2)  ← 不能再派生
        └── 工作 sub-sub-agent (depth 2)

深度层级

深度Session key 格式角色能否派生?
0agent:<id>:main主 Agent始终可以
1agent:<id>:subagent:<uuid>子 Agent(maxSpawnDepth>=2 时为编排器)仅当 maxSpawnDepth >= 2
2agent:<id>:subagent:<uuid>:subagent:<uuid>叶子工作 Agent永不可以

最大嵌套深度为 5(maxSpawnDepth 范围 1–5),推荐 2。

结果回传链

  1. depth-2 工作 Agent 完成 → announce 给 depth-1 编排器
  2. depth-1 编排器收到 announce,综合结果,完成 → announce 给主 Agent
  3. 主 Agent 收到 announce,交付给用户

每层只能看到直接子 Agent 的 announce。

各深度工具策略

  • depth-1(编排器,maxSpawnDepth >= 2):获得 sessions_spawn、subagents、sessions_list、sessions_history
  • depth-1(叶子,maxSpawnDepth == 1):无 session 工具(当前默认)
  • depth-2(叶子工作 Agent):无 session 工具,sessions_spawn 始终拒绝

级联停止

  • /stop 停止请求方会话及其所有子 Agent(级联到 depth-2)
  • /subagents kill <id> 停止指定子 Agent 及其子 Agent
  • /subagents kill all 停止所有子 Agent

Slash 命令

/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>]

/subagents spawn 是一次性模式(mode: "run")。持久线程绑定会话用 sessions_spawn 加 thread: true 和 mode: "session"。


线程绑定会话

目前仅 Discord 支持持久线程绑定 sub-agent 会话。

流程:

  1. sessions_spawn 加 thread: true
  2. OpenClaw 在当前 channel 创建或绑定线程到该会话
  3. 该线程中的后续消息路由到绑定会话
  4. /session idle 查看/更新空闲自动解绑;/session max-age 控制硬上限
  5. /unfocus 手动解绑

线程绑定控制命令:

命令效果
/focus <target>绑定当前线程到子 Agent/会话目标
/unfocus移除当前绑定线程的绑定
/agents列出活跃运行和绑定状态
/session idle查看/更新空闲自动解绑
/session max-age查看/更新硬上限

Announce 机制

子 Agent 完成后通过 announce 步骤回报:

  • announce 在子 Agent 会话内运行(不在请求方会话)
  • 子 Agent 回复精确字符串 ANNOUNCE_SKIP → 不发布任何内容
  • 最新 assistant 文本为精确 NO_REPLY / no_reply → 抑制 announce 输出

Announce 上下文字段:

字段来源
Sourcesubagent 或 cron
Session ids子会话 key/id
Typeannounce 类型 + 任务标签
Status从运行时结果派生(success/error/timeout/unknown),不从模型文本推断
Result content最新可见 assistant 文本,否则为净化后的工具/工具结果文本
Follow-up说明何时回复 vs 保持静默的指令

Stats 行(每个 announce payload 末尾):运行时长、token 用量(输入/输出/总计)、估算费用、sessionKey/sessionId/transcript 路径。


工具策略

子 Agent 默认获得除 session 工具外的所有工具:

被拒绝的工具:sessions_list、sessions_history、sessions_send、sessions_spawn

覆盖配置:

{
  tools: {
    subagents: {
      tools: {
        deny: ["gateway", "cron"],
        // allow 设置后变为 allow-only(deny 仍优先)
      },
    },
  },
}

tools.subagents.tools.allow 只能收窄已解析的工具集,不能添加被 tools.profile 移除的工具。


完整配置参考

{
  agents: {
    defaults: {
      subagents: {
        delegationMode: "prefer",       // "suggest"(默认)或 "prefer"
        maxSpawnDepth: 2,               // 嵌套深度,默认 1,最大 5
        maxChildrenPerAgent: 5,         // 每个会话最大活跃子 Agent 数,默认 5,范围 1-20
        maxConcurrent: 8,               // 全局并发 lane 上限,默认 8
        runTimeoutSeconds: 900,         // sessions_spawn 省略时的默认超时(0=无超时)
        announceTimeoutMs: 120000,      // 每次 announce 投递超时(毫秒)
        archiveAfterMinutes: 60,        // 自动归档时间,默认 60 分钟
        model: "anthropic/claude-haiku-4-5", // 子 Agent 默认模型
        thinking: "fast",               // 子 Agent 默认 thinking 级别
        allowAgents: ["*"],             // 允许 agentId 目标列表
        requireAgentId: false,          // 强制 sessions_spawn 必须指定 agentId
      },
    },
  },
}

认证

子 Agent 认证按 agent id 解析,不按会话类型:

  • 从该 agent 的 agentDir 加载 auth store
  • 主 Agent 的 auth profiles 作为回退合并进来(agent profiles 在冲突时优先)

限制

  • Announce 是尽力而为的,网关重启会丢失待处理的 announce
  • 子 Agent 共享同一网关进程资源,maxConcurrent 是安全阀
  • sessions_spawn 始终非阻塞,立即返回
  • 子 Agent 上下文只注入 AGENTS.md、TOOLS.md、SOUL.md、IDENTITY.md、USER.md(不含 MEMORY.md、HEARTBEAT.md、BOOTSTRAP.md)
  • runTimeoutSeconds 只停止运行,不自动归档;归档由 archiveAfterMinutes 控制

相关页面

  • concepts/tool-acp-agents — ACP agents(外部 harness 运行时:Claude Code/Cursor/Gemini CLI 等)
  • concepts/tool-agent-send — Agent Send(CLI 触发 Agent 运行)
  • concepts/tool-multi-agent-sandbox-tools — 多 Agent 沙箱与工具策略(8 层过滤优先级)
  • multi-agent — 多 Agent 路由与 binding 规则
  • queue — 命令队列与并发控制(subagent lane)