子代理是从现有代理运行中生成的后台代理运行。 它们在各自的会话中运行(Documentation Index
Fetch the complete documentation index at: https://openclaw.zhcndoc.com/llms.txt
Use this file to discover all available pages before exploring further.
agent:<agentId>:subagent:<uuid>),并且在完成后,会将结果通知回请求者聊天
频道。每个子代理运行都会被跟踪为一个
后台任务。
主要目标:
- 在不阻塞主运行的情况下,并行化“调研 / 长任务 / 慢工具”工作。
- 默认保持子代理隔离(会话分离 + 可选沙箱)。
- 尽量让工具面不易被滥用:默认情况下,子代理不获得会话工具。
- 支持可配置的嵌套深度,以适配编排器模式。
成本说明: 默认情况下,每个子代理都有自己的上下文和令牌使用量。
对于重型或重复性任务,请为子代理设置更便宜的模型,并让主代理使用更高质量的模型。
可通过
agents.defaults.subagents.model 或按代理覆盖进行配置。
当子代理确实需要请求者当前转录时,代理可以在那次生成中请求
context: "fork"。线程绑定的子代理会话默认使用
context: "fork",因为它们会把当前对话分支到后续线程中。斜杠命令
使用/subagents 来检查或控制当前会话中的子代理运行:
/steer <message> 来引导当前请求者会话中的活动运行。目标是子运行时,请使用 /subagents steer <id|#> <message>。
/subagents info 显示运行元数据(状态、时间戳、会话 id、
转录路径、清理方式)。使用 sessions_history 获取有界的、
经过安全过滤的回忆视图;当你需要原始完整转录时,请检查磁盘上的转录路径。
线程绑定控制
这些命令适用于支持持久线程绑定的频道。 参见下面的支持线程的频道。生成行为
/subagents spawn 会作为用户命令(而不是内部中继)启动一个后台子代理,
并在运行结束时向请求者聊天发送一次最终完成更新。
非阻塞、推送式完成
非阻塞、推送式完成
- 生成命令是非阻塞的;它会立即返回一个运行 id。
- 完成后,子代理会将摘要/结果消息通知回请求者聊天频道。
- 完成采用推送式。生成后,请不要仅为了等待其结束而循环轮询
/subagents list、sessions_list或sessions_history;只在需要调试或干预时按需检查状态。 - 完成时,在通知清理流程继续之前,OpenClaw 会尽力关闭该子代理会话打开的已跟踪浏览器标签页/进程。
手动生成投递韧性
手动生成投递韧性
- OpenClaw 首先尝试使用稳定的幂等键进行直接
agent投递。 - 如果直接投递失败,则回退到队列路由。
- 如果队列路由仍不可用,则会在最终放弃前以短暂的指数退避重试通知。
- 完成投递会保留已解析的请求者路由:当可用时,线程绑定或会话绑定的完成路由优先;如果完成来源只提供了频道,OpenClaw 会使用请求者会话已解析路由(
lastChannel/lastTo/lastAccountId)补全缺失的目标/账户,从而确保直接投递仍可工作。
完成交接元数据
完成交接元数据
发给请求者会话的完成交接是运行时生成的
内部上下文(不是用户编写的文本),并包含:
Result— 最新可见的assistant回复文本;否则为经过清理的最新 tool/toolResult 文本。终态失败的运行不会复用捕获到的回复文本。Status—completed successfully/failed/timed out/unknown。- 紧凑的运行/令牌统计信息。
- 一条投递指令,要求请求者代理以正常助手语气重写内容(不要转发原始内部元数据)。
模式和 ACP 运行时
模式和 ACP 运行时
--model和--thinking会覆盖该特定运行的默认值。- 使用
info/log在完成后检查细节和输出。 /subagents spawn是一次性模式(mode: "run")。对于持久的线程绑定会话,请使用sessions_spawn,并设置thread: true和mode: "session"。- 对于 ACP 宿主会话(Claude Code、Gemini CLI、OpenCode,或显式的 Codex ACP/acpx),当工具声明支持该运行时时,请使用
sessions_spawn并设置runtime: "acp"。在排查完成结果或代理间循环时,请参见 ACP 投递模型。当启用codex插件时,Codex 聊天/线程控制应优先使用/codex ...而不是 ACP,除非用户明确要求 ACP/acpx。 - 在启用 ACP、请求者未处于沙箱中,并且加载了如
acpx之类的后端插件时,OpenClaw 才会隐藏runtime: "acp"。runtime: "acp"需要一个外部 ACP 宿主 id,或一个runtime.type="acp"的agents.list[]条目;对于agents_list中来自 OpenClaw 常规配置的代理,请使用默认子代理运行时。
上下文模式
原生子代理默认会以隔离方式启动,除非调用方明确要求分叉 当前转录。| 模式 | 何时使用 | 行为 |
|---|---|---|
isolated | 全新的调研、独立实现、慢工具工作,或任何可以在任务文本中简要说明的内容 | 创建一个干净的子转录。这是默认模式,并能降低令牌使用量。 |
fork | 依赖当前对话、之前工具结果,或请求者转录中已存在的细微指令的工作 | 在子会话开始前,将请求者转录分支到子会话中。 |
fork。它用于依赖上下文的委派,而不是
对清晰任务提示的替代。
工具:sessions_spawn
以 deliver: false 在全局 subagent 线路上启动一个子代理运行,
然后执行一个通知步骤,并将通知回复发布到请求者
聊天频道。
可用性取决于调用方的有效工具策略。coding 和
full 配置默认暴露 sessions_spawn。messaging 配置不暴露;
为应当委派工作的代理添加 tools.alsoAllow: ["sessions_spawn", "sessions_yield", "subagents"],或者使用 tools.profile: "coding"。频道/组、提供方、沙箱以及按代理的允许/拒绝策略仍然可以在配置文件阶段之后移除此工具。可使用同一会话中的 /tools 来确认实际生效的工具列表。
默认值:
- 模型: 继承调用方,除非你设置了
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(无超时)。
工具参数
子代理的任务描述。
可选的人类可读标签。
当
subagents.allowAgents 允许时,在另一个代理 id 下生成。acp 仅用于外部 ACP 宿主(claude、droid、gemini、opencode,或显式请求的 Codex ACP/acpx)以及 runtime.type 为 acp 的 agents.list[] 条目。仅 ACP。當
runtime: "acp" 时恢复一个已有的 ACP 宿主会话;对原生子代理生成会被忽略。仅 ACP。当
runtime: "acp" 时,将 ACP 运行输出流式发送到父会话;对原生子代理生成请省略。覆盖子代理模型。无效值会被跳过,子代理将在默认模型上运行,并在工具结果中给出警告。
覆盖子代理运行的思考级别。
默认情况下使用
agents.defaults.subagents.runTimeoutSeconds,否则为 0。设置后,子代理运行会在 N 秒后中止。当为
true 时,为该子代理会话请求频道线程绑定。如果
thread: true 且省略 mode,默认值变为 session。mode: "session" 需要 thread: true。"delete" 会在通知后立即归档(仍通过重命名保留转录)。require 会拒绝生成,除非目标子运行时已启用沙箱。fork 会将请求者当前转录分支到子会话中。仅适用于原生子代理。线程绑定生成默认使用 fork;非线程生成默认使用 isolated。线程绑定会话
当为某个通道启用线程绑定时,子代理可以保持与某个线程绑定, 这样该线程中的后续用户消息就会继续路由到同一个子代理会话。支持线程的通道
Discord is currently the only supported channel. It supports persistent thread-bound subagent sessions (sessions_spawn with
thread: true), manual thread controls (/focus, /unfocus, /agents,
/session idle, /session max-age), and adapter keys
channels.discord.threadBindings.enabled,
channels.discord.threadBindings.idleHours,
channels.discord.threadBindings.maxAgeHours, and
channels.discord.threadBindings.spawnSessions.
快速流程
手动控制
| 命令 | 作用 |
|---|---|
/focus <target> | 将当前线程(或创建一个线程)绑定到某个子代理/会话目标 |
/unfocus | 移除当前已绑定线程的绑定关系 |
/agents | 列出活动运行和绑定状态(thread:<id> 或 unbound) |
/session idle | 检查/更新空闲自动取消聚焦(仅限已聚焦的绑定线程) |
/session max-age | 检查/更新硬性上限(仅限已聚焦的绑定线程) |
配置开关
- 全局默认值:
session.threadBindings.enabled、session.threadBindings.idleHours、session.threadBindings.maxAgeHours。 - 通道覆盖和自动绑定的 spawn 键 依赖适配器。参见上方的 支持线程的通道。
白名单
可通过显式
agentId 作为目标的代理 id 列表(["*"] 允许任意)。默认:仅允许请求者代理。如果你设置了列表,但仍希望请求者通过 agentId 自身启动,请将请求者 id 包含在列表中。当请求者代理未自行设置
subagents.allowAgents 时使用的默认目标代理白名单。阻止省略
agentId 的 sessions_spawn 调用(强制显式选择配置文件)。按代理覆盖:agents.list[].subagents.requireAgentId。sessions_spawn 会拒绝那些
会以非沙箱方式运行的目标。
发现
使用agents_list 查看当前允许用于
sessions_spawn 的代理 id。响应会包含每个列出的代理的有效
模型和嵌入式运行时元数据,以便调用方区分 PI、Codex
应用服务器以及其他已配置的原生运行时。
自动归档
- 子代理会话会在
agents.defaults.subagents.archiveAfterMinutes之后自动归档(默认60)。 - 归档会使用
sessions.delete,并将转录重命名为*.deleted.<timestamp>(同一文件夹)。 cleanup: "delete"会在 announce 之后立即归档(但仍通过重命名保留转录)。- 自动归档尽力而为;如果网关重启,待处理的计时器会丢失。
runTimeoutSeconds不会 自动归档;它只会停止运行。会话会一直保留到自动归档为止。- 自动归档同样适用于深度 1 和深度 2 的会话。
- 浏览器清理与归档清理是分开的:在运行结束时,会尽力关闭被跟踪的浏览器标签页/进程,即使转录/会话记录被保留也一样。
嵌套子代理
默认情况下,子代理不能再启动自己的子代理 (maxSpawnDepth: 1)。将 maxSpawnDepth: 2 可启用一层
嵌套——编排器模式:主代理 → 编排器子代理 →
工作子子代理。
深度层级
| 深度 | 会话键形状 | 角色 | 可以启动子级? |
|---|---|---|---|
| 0 | agent:<id>:main | 主代理 | 始终可以 |
| 1 | agent:<id>:subagent:<uuid> | 子代理(当允许深度 2 时为编排器) | 仅当 maxSpawnDepth >= 2 |
| 2 | agent:<id>:subagent:<uuid>:subagent:<uuid> | 子子代理(叶子工作者) | 永远不可以 |
通知链
结果会沿链路向上返回:- 深度 2 的工作者完成 → 通知其父级(深度 1 的编排器)。
- 深度 1 的编排器收到通知,综合结果,完成 → 通知主代理。
- 主代理收到通知并交付给用户。
操作建议: 先启动一次子任务并等待完成
事件,而不是围绕
sessions_list、
sessions_history、/subagents list 或 exec sleep 命令构建轮询循环。
sessions_list 和 /subagents list 会将子会话关系
聚焦于活跃工作——存活的子级保持附着,已结束的子级在短暂的最近窗口内仍可见,而仅存于存储中的过期子级链接会在其新鲜度窗口之后被忽略。这样可以防止旧的 spawnedBy /
parentSessionKey 元数据在重启后复活“幽灵子级”。如果子级完成事件在你已经发送
最终答案之后到达,正确的后续处理是精确的静默标记
NO_REPLY / no_reply。按深度划分的工具策略
- 角色和控制范围会在启动时写入会话元数据。这可以防止扁平或恢复的会话键意外重新获得编排器权限。
- 深度 1(编排器,当
maxSpawnDepth >= 2): 可获得sessions_spawn、subagents、sessions_list、sessions_history,以便管理其子级。其他会话/系统工具仍然被拒绝。 - 深度 1(叶子,当
maxSpawnDepth == 1): 没有会话工具(当前默认行为)。 - 深度 2(叶子工作者): 没有会话工具——
sessions_spawn在深度 2 时始终被拒绝。不能再继续启动子级。
每个代理的启动上限
每个代理会话(任意深度)在同一时间最多只能有maxChildrenPerAgent
(默认 5)个活动子级。这可以防止单个编排器
产生失控的分叉扩散。
级联停止
停止一个深度 1 的编排器会自动停止其所有深度 2 子级:- 在主聊天中执行
/stop会停止所有深度 1 代理,并级联停止其深度 2 子级。 /subagents kill <id>会停止某个特定子代理,并级联停止其子级。/subagents kill all会停止请求者的所有子代理,并级联停止。
认证
子代理认证按代理 id解析,而不是按会话类型:- 子代理会话键为
agent:<agentId>:subagent:<uuid>。 - 认证存储从该代理的
agentDir加载。 - 主代理的认证配置会作为回退合并进来;冲突时以代理配置覆盖主配置。
通知
子代理通过一个 announce 步骤回报:- announce 步骤在子代理会话内部运行(而不是在请求者会话中)。
- 如果子代理恰好回复
ANNOUNCE_SKIP,则不会发布任何内容。 - 如果最新的 assistant 文本恰好是静默标记
NO_REPLY/no_reply,即使之前存在可见进度,也会抑制 announce 输出。
- 顶层请求者会话使用带外部交付的后续
agent调用(deliver=true)。 - 嵌套的请求者子代理会话接收内部后续注入(
deliver=false),这样编排器就可以在会话内综合子级结果。 - 如果嵌套的请求者子代理会话已消失,OpenClaw 会在可用时回退到该会话的请求者。
通知上下文
announce 上下文会被规范化为稳定的内部事件块:| 字段 | 来源 |
|---|---|
| 来源 | subagent 或 cron |
| 会话 ids | 子会话键/id |
| 类型 | announce 类型 + 任务标签 |
| 状态 | 由运行时结果派生(success、error、timeout 或 unknown)——不是从模型文本推断出来的 |
| 结果内容 | 最新可见的 assistant 文本,否则为已清理的最新 tool/toolResult 文本 |
| 后续指令 | 描述何时应回复、何时应保持静默的说明 |
统计行
announce 载荷会在末尾包含一行统计信息(即使已包裹):- 运行时长(例如
runtime 5m12s)。 - 令牌用量(输入/输出/总计)。
- 当已配置模型定价时的估算成本(
models.providers.*.models[].cost)。 sessionKey、sessionId和转录路径,以便主代理可通过sessions_history获取历史或在磁盘上检查文件。
为什么优先使用 sessions_history
sessions_history 是更安全的编排路径:
- assistant 记忆会先被规范化:移除 thinking 标签;移除
<relevant-memories>/<relevant_memories>脚手架;移除纯文本工具调用 XML 载荷块(<tool_call>、<function_call>、<tool_calls>、<function_calls>),包括未能完整闭合的截断载荷;移除降级的工具调用/结果脚手架和历史上下文标记;移除泄露的模型控制标记(<|assistant|>、其他 ASCII<|...|>、全角<|...|>);移除格式损坏的 MiniMax 工具调用 XML。 - 会对凭证/令牌样式文本进行脱敏。
- 长块内容可能会被截断。
- 超大历史记录可能会丢弃较旧行,或将过大的单行替换为
[sessions_history omitted: message too large]。 - 当你需要按字节逐字节查看完整转录时,可回退到原始磁盘转录检查。
工具策略
子代理使用与父代理或目标代理相同的 profile 和工具策略管道。之后,OpenClaw 会应用子代理限制层。 在没有受限tools.profile 的情况下,子代理会获得除会话工具和系统工具之外的所有工具:
sessions_listsessions_historysessions_sendsessions_spawn
sessions_history 在这里仍然是一个有边界、经过清理的回溯视图——它
不是原始转录内容的完整转储。
当 maxSpawnDepth >= 2 时,深度 1 的编排器子代理还会额外获得
sessions_spawn、subagents、sessions_list 和
sessions_history,以便它们管理自己的子级。
通过配置覆盖
tools.subagents.tools.allow 是最终的仅允许过滤器。它可以缩小
已经解析出的工具集,但不能重新添加一个被
tools.profile 移除的工具。例如,tools.profile: "coding" 包含
web_search/web_fetch,但不包含 browser 工具。若要让
使用 coding profile 的子代理能够使用浏览器自动化,请在
profile 阶段添加 browser:
agents.list[].tools.alsoAllow: ["browser"]。
并发
子代理使用专用的进程内队列通道:- 通道名称:
subagent - 并发数:
agents.defaults.subagents.maxConcurrent(默认8)
存活性与恢复
OpenClaw 不会将endedAt 缺失视为子代理仍然存活的永久证据。超过陈旧运行窗口的未结束运行,在 /subagents list、状态摘要、后代完成门控以及按会话的并发检查中,都不再计为活动/待处理。
在网关重启后,陈旧的未结束恢复运行会被清理,除非其子会话被标记为 abortedLastRun: true。这些重启后中止的子会话仍可通过子代理孤儿恢复流程找回;该流程会在清除中止标记之前发送一条合成的恢复消息。
每个子会话的自动重启恢复都有边界。如果同一个子代理子会话在快速重新卡住窗口内被反复接受用于孤儿恢复,OpenClaw 会在该会话上持久化一个恢复墓碑,并在后续重启中停止自动恢复它。运行 openclaw tasks maintenance --apply 以协调任务记录,或运行 openclaw doctor --fix 清除墓碑会话上过期的中止恢复标记。
如果子代理启动因 Gateway
PAIRING_REQUIRED /
scope-upgrade 而失败,请在编辑配对状态之前检查 RPC 调用方。
内部 sessions_spawn 协调应通过直接环回共享令牌/密码认证,以
client.id: "gateway-client" 且 client.mode: "backend" 连接;该路径不依赖
CLI 的已配对设备作用域基线。远程调用方、显式的 deviceIdentity、
显式设备令牌路径,以及浏览器/node 客户端,仍然需要正常的设备批准
才能进行作用域升级。停止
- 在请求者聊天中发送
/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)。