概述
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"] }完整参数:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
task | string | 必填 | 子 Agent 的任务描述 |
taskName | string | — | 稳定的编排句柄,用于后续 steer/kill 定位,格式 [a-z][a-z0-9_]{0,63} |
label | string | — | 人类可读标签 |
agentId | string | — | 目标 Agent ID(受 allowAgents 限制) |
runtime | "subagent" | "acp" | "subagent" | acp 仅用于外部 ACP harness |
resumeSessionId | string | — | 仅 ACP:恢复已有 ACP 会话 |
streamTo | "parent" | — | 仅 ACP:将输出流式传给父会话 |
model | string | 继承调用方 | 覆盖子 Agent 模型 |
thinking | string | 继承调用方 | 覆盖 thinking 级别 |
runTimeoutSeconds | number | 0(无超时) | 超时后中止运行 |
thread | boolean | false | 是否绑定 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 格式 | 角色 | 能否派生? |
|---|---|---|---|
| 0 | agent:<id>:main | 主 Agent | 始终可以 |
| 1 | agent:<id>:subagent:<uuid> | 子 Agent(maxSpawnDepth>=2 时为编排器) | 仅当 maxSpawnDepth >= 2 |
| 2 | agent:<id>:subagent:<uuid>:subagent:<uuid> | 叶子工作 Agent | 永不可以 |
最大嵌套深度为 5(maxSpawnDepth 范围 1–5),推荐 2。
结果回传链
- depth-2 工作 Agent 完成 → announce 给 depth-1 编排器
- depth-1 编排器收到 announce,综合结果,完成 → announce 给主 Agent
- 主 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 会话。
流程:
sessions_spawn加thread: true- OpenClaw 在当前 channel 创建或绑定线程到该会话
- 该线程中的后续消息路由到绑定会话
/session idle查看/更新空闲自动解绑;/session max-age控制硬上限/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 上下文字段:
| 字段 | 来源 |
|---|---|
| Source | subagent 或 cron |
| Session ids | 子会话 key/id |
| Type | announce 类型 + 任务标签 |
| 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)