子代理
Sub-agents 是从现有 agent 运行中生成的后台 agent 运行。它们在自己的 会话 (agent:<agentId>:subagent:<uuid>) 中运行,并在完成后将其结果通报回请求的聊天渠道。每个 sub-agent 运行都作为后台任务进行跟踪。
使用 /subagents 来检查或控制当前会话的子代理运行:
/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 作为用户命令启动后台子代理,而不是内部中继,并在运行完成时向请求者聊天发送最后一次完成更新。
- 生成命令是非阻塞的;它立即返回一个运行 ID。
- 完成后,子代理会将摘要/结果消息通告回请求者聊天频道。
- 对于手动生成,传递是具有韧性的:
- OpenClaw 首先尝试使用稳定的幂等密钥直接传送
agent。 - 如果直接传送失败,它将回退到队列路由。
- 如果队列路由仍然不可用,则会在最终放弃之前,使用短暂的指数退避重试发送公告。
- OpenClaw 首先尝试使用稳定的幂等密钥直接传送
- 完成后的交接给请求者会话的是运行时生成的内部上下文(不是用户编写的文本),包括:
Result(assistant回复文本,如果助手回复为空,则为最新的toolResult)Status(completed successfully/failed/timed out/unknown)- 紧凑的运行时/token 统计信息
- 一条传送指令,告诉请求者代理以正常的助手语调重写(而不是转发原始的内部元数据)
--model和--thinking会覆盖该特定运行的默认设置。- 使用
info/log在完成后检查详细信息和输出。 /subagents spawn是单次模式(mode: "run")。对于持久的线程绑定会话,请将sessions_spawn与thread: true和mode: "session"一起使用。- 对于 ACP 驱动会话(Codex、Claude Code、Gemini CLI),请将
sessions_spawn与runtime: "acp"结合使用,并参阅 ACP Agents。
主要目标:
- 并行化“研究 / 长任务 / 慢速工具”工作,而不阻塞主运行。
- 默认情况下保持子代理隔离(会话分离 + 可选的沙箱隔离)。
- 使工具表面难以被滥用:子代理默认情况下不会获取会话工具。
- 支持可配置的嵌套深度,以实现编排器模式。
成本说明:每个子代理都有其独立的上下文和令牌使用情况。对于繁重或重复的任务,请为子代理设置更便宜的模型,并将主代理保持在更高质量的模型上。您可以通过 agents.defaults.subagents.model 或每个代理的覆盖配置来设置此选项。
使用 sessions_spawn:
- 启动子代理运行(
deliver: false,全局通道:subagent) - 然后运行宣布步骤,并将宣布回复发布到请求者聊天渠道
- 默认模型:继承调用者,除非您设置了
agents.defaults.subagents.model(或每个代理的agents.list[].subagents.model);显式的sessions_spawn.model仍然优先。 - 默认思考:继承调用者,除非您设置了
agents.defaults.subagents.thinking(或每个代理的agents.list[].subagents.thinking);显式的sessions_spawn.thinking仍然优先。 - 默认运行超时:如果省略了
sessions_spawn.runTimeoutSeconds,OpenClaw 将使用已设置的agents.defaults.subagents.runTimeoutSeconds;否则回退到0(无超时)。
工具参数:
task(必需)label?(可选)agentId?(可选;如果允许,则在另一个代理 ID 下生成)model?(可选;覆盖子代理模型;无效值将被跳过,子代理将在默认模型上运行,并在工具结果中显示警告)thinking?(可选;覆盖子代理运行的思考级别)runTimeoutSeconds?(设置时默认为agents.defaults.subagents.runTimeoutSeconds,否则为0;设置后,子代理运行将在 N 秒后中止)thread?(默认false;当为true时,请求为此子代理会话进行渠道线程绑定)mode?(run|session)- 默认为
run - 如果省略了
thread: true和mode,则默认为session mode: "session"需要thread: true
- 默认为
cleanup?(delete|keep,默认keep)sandbox?(inherit|require,默认inherit;如果目标子运行时未进行沙箱隔离,require将拒绝生成)sessions_spawn不接受渠道传递参数 (target、channel、to、threadId、replyTo、transport)。如需传递,请从生成的运行中使用message/sessions_send。
线程绑定会话
Section titled “线程绑定会话”当为渠道启用了线程绑定时,子代理可以保持与线程的绑定,以便该线程中的后续用户消息继续路由到同一个子代理会话。
支持线程的渠道
Section titled “支持线程的渠道”- Discord(目前唯一支持的渠道):支持持久的线程绑定子代理会话(
sessions_spawn带有thread: true)、手动线程控制(/focus、/unfocus、/agents、/session idle、/session max-age)以及适配器键channels.discord.threadBindings.enabled、channels.discord.threadBindings.idleHours、channels.discord.threadBindings.maxAgeHours和channels.discord.threadBindings.spawnSubagentSessions。
快速流程:
- 使用
thread: true通过sessions_spawn生成(可选mode: "session")。 - OpenClaw 在活动渠道中为该会话目标创建或绑定一个线程。
- 该线程中的回复和后续消息会路由到绑定的会话。
- 使用
/session idle检查/更新不活跃自动取消聚焦,并使用/session max-age控制硬上限。 - 使用
/unfocus手动分离。
手动控制:
/focus <target>将当前线程(或创建一个)绑定到子代理/会话目标。/unfocus移除当前绑定线程的绑定。/agents列出活动运行和绑定状态(thread:<id>或unbound)。/session idle和/session max-age仅适用于聚焦的绑定线程。
配置开关:
- 全局默认:
session.threadBindings.enabled,session.threadBindings.idleHours,session.threadBindings.maxAgeHours - 通道覆盖和生成自动绑定键特定于适配器。请参阅上面的 支持线程的通道。
有关当前适配器的详细信息,请参阅配置参考和 Slash 命令。
允许列表:
agents.list[].subagents.allowAgents:可通过agentId定位的代理 ID 列表(["*"]表示允许任何)。默认值:仅请求者代理。- 沙箱继承保护:如果请求者会话是沙箱隔离的,
sessions_spawn将拒绝以非沙箱隔离方式运行的目标。 agents.defaults.subagents.requireAgentId/agents.list[].subagents.requireAgentId:如果为 true,则阻止省略agentId的sessions_spawn调用(强制显式选择配置文件)。默认值:false。
设备发现:
- 使用
agents_list查看当前允许sessions_spawn使用哪些 agent ID。
自动归档:
- Sub-agent session 会在
agents.defaults.subagents.archiveAfterMinutes后自动归档(默认值:60)。 - 归档使用
sessions.delete并将记录重命名为*.deleted.<timestamp>(同一文件夹)。 cleanup: "delete"在通报后立即归档(仍通过重命名保留记录)。- 自动归档尽力而为;如果网关重启,待处理的定时器将丢失。
runTimeoutSeconds不自动归档;它仅停止运行。Session 将保留直到自动归档。- 自动归档同等地适用于深度 1 和深度 2 的 session。
嵌套 Sub-Agents
Section titled “嵌套 Sub-Agents”默认情况下,sub-agents 无法生成自己的 sub-agents (maxSpawnDepth: 1)。您可以通过设置 maxSpawnDepth: 2 来启用一级嵌套,从而允许编排器模式:主 → 编排器 sub-agent → 工作者 sub-sub-agents。
{ agents: { defaults: { subagents: { maxSpawnDepth: 2, // allow sub-agents to spawn children (default: 1) maxChildrenPerAgent: 5, // max active children per agent session (default: 5) maxConcurrent: 8, // global concurrency lane cap (default: 8) runTimeoutSeconds: 900, // default timeout for sessions_spawn when omitted (0 = no timeout) }, }, },}| 深度 | Session 键形状 | 角色 | 能否生成? |
|---|---|---|---|
| 0 | agent:<id>:main | 主 agent | 始终 |
| 1 | agent:<id>:subagent:<uuid> | Sub-agent(当允许深度 2 时为编排器) | 仅当 maxSpawnDepth >= 2 时 |
| 2 | agent:<id>:subagent:<uuid>:subagent:<uuid> | 子子代理(叶工作器) | 从不 |
结果沿链向上回流:
- 深度 2 工作器完成 → 向其父级(深度 1 编排器)公告
- 深度 1 编排器接收公告,综合结果,完成 → 向主代理公告
- 主代理接收公告并交付给用户
每个层级仅能看到其直接子级的公告。
按深度的工具策略
Section titled “按深度的工具策略”- 角色和控制范围在生成时被写入会话元数据。这可以防止扁平化或还原的会话密钥意外重新获得编排器权限。
- 深度 1(编排器,当
maxSpawnDepth >= 2时):获取sessions_spawn、subagents、sessions_list、sessions_history,以便它可以管理其子级。其他会话/系统工具仍然被拒绝。 - 深度 1(叶,当
maxSpawnDepth == 1时):无会话工具(当前默认行为)。 - 深度 2(叶工作器):无会话工具 ——
sessions_spawn在深度 2 始终被拒绝。无法生成更多子级。
每个代理的生成限制
Section titled “每个代理的生成限制”每个代理会话(在任何深度)一次最多可以有 maxChildrenPerAgent(默认:5)个活动的子级。这可以防止来自单个编排器的失控扩散。
停止深度 1 编排器会自动停止其所有深度 2 子级:
- 主聊天中的
/stop会停止所有深度 1 代理并级联到其深度 2 子级。 /subagents kill <id>停止特定的子代理并级联到其子级。/subagents kill all停止请求者的所有子代理并级联。
子代理身份验证由 代理 ID 解析,而不是由会话类型解析:
- 子代理会话密钥是
agent:<agentId>:subagent:<uuid>。 - 身份验证存储是从该代理的
agentDir加载的。 - 主代理的身份验证配置文件作为 后备 合并进来;代理配置文件在冲突时覆盖主配置文件。
注意:合并是累加的,因此主配置文件始终可作为后备使用。尚不支持每个代理完全隔离的身份验证。
子代理通过公告步骤报告回来:
- 公告步骤在子代理会话内部运行(而不是在请求者会话中)。
- 如果子代理完全回复
ANNOUNCE_SKIP,则不会发布任何内容。 - 否则,传递方式取决于请求者的深度:
- 顶级请求者会话使用带有外部传递 (
deliver=true) 的后续agent调用 - 嵌套请求者子代理会话接收内部后续注入 (
deliver=false),以便编排器可以在会话中综合子结果 - 如果嵌套请求者子代理会话已消失,OpenClaw 会在可用时回退到该会话的请求者
- 顶级请求者会话使用带有外部传递 (
- 在构建嵌套完成发现时,子完成聚合的范围限定于当前请求者运行,从而防止陈旧的先前运行子输出泄漏到当前通告中。
- 通告回复在渠道适配器上可用时会保留线程/主题路由。
- 通告上下文被规范化为一个稳定的内部事件块:
- 来源 (
subagent或cron) - 子会话密钥/ID
- 通告类型 + 任务标签
- 源自运行时结果的状态行 (
success、error、timeout或unknown) - 来自通告步骤的结果内容(如果缺失则为
(no output)) - 描述何时回复与保持静默的后续指令
- 来源 (
Status不是从模型输出推断出来的;它来自运行时结果信号。
通告有效负载在末尾包含一个统计行(即使被包装):
- 运行时(例如
runtime 5m12s) - Token 使用量(输入/输出/总计)
- 配置模型定价时的估算成本 (
models.providers.*.models[].cost) sessionKey、sessionId和脚本路径(以便主代理可以通过sessions_history获取历史记录或在磁盘上检查文件)- 内部元数据仅供编排使用;面向用户的回复应以普通助手语音重写。
工具策略(子代理工具)
Section titled “工具策略(子代理工具)”默认情况下,子代理获得除会话工具和系统工具之外的所有工具:
sessions_listsessions_historysessions_sendsessions_spawn
当 maxSpawnDepth >= 2 时,深度为 1 的编排器子代理还会接收 sessions_spawn、subagents、sessions_list 和 sessions_history,以便管理其子级。
通过配置覆盖:
{ agents: { defaults: { subagents: { maxConcurrent: 1, }, }, }, tools: { subagents: { tools: { // deny wins deny: ["gateway", "cron"], // if allow is set, it becomes allow-only (deny still wins) // allow: ["read", "exec", "process"] }, }, },}子代理使用专用的进程内队列通道:
- 通道名称:
subagent - 并发数:
agents.defaults.subagents.maxConcurrent(默认8)
- 在请求者聊天中发送
/stop会中止请求者会话并停止由其生成的任何活动子代理运行,并级联停止嵌套的子级。 /subagents kill <id>会停止特定的子代理并级联停止其子级。
- 子代理的公告是“尽力而为”的。如果网关重启,挂起的“回传公告”工作将会丢失。
- 子代理仍然共享相同的网关进程资源;请将
maxConcurrent视为安全阀。 sessions_spawn始终是非阻塞的:它会立即返回{ status: "accepted", runId, childSessionKey }。- 子代理上下文仅注入
AGENTS.md+TOOLS.md(不包含SOUL.md、IDENTITY.md、USER.md、HEARTBEAT.md或BOOTSTRAP.md)。 - 最大嵌套深度为 5(
maxSpawnDepth范围:1–5)。对于大多数用例,建议深度为 2。 maxChildrenPerAgent限制每个会话的活动子级数量(默认:5,范围:1–20)。