子代理
子代理是在现有代理运行中派生的后台代理实例。它们运行在独立的会话中(agent:<agentId>:subagent:<uuid>),任务完成后,会将结果通报回请求该子代理的聊天频道。
斜杠命令
使用/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(助手回复文本,若助手无回复,则为最新toolResult)Status(成功完成 / 失败 / 超时 / 未知)- 精简的运行时/令牌统计
- 交付指令,告知请求代理以普通助手语气复写回复(而非转发原始内部元数据)
--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.defaults.subagents.model 或针对单个代理覆盖实现。
工具
使用sessions_spawn 工具:
- 启动子代理运行(
deliver: false,全局队列通道:subagent) - 接着执行通报步骤,将结果回复发布至请求聊天频道
- 默认模型:继承调用者模型,除非设置了
agents.defaults.subagents.model(或针对单代理的agents.list[].subagents.model);显式的sessions_spawn.model优先。 - 默认思考级别:继承调用者思考级别,除非设置了
agents.defaults.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)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。
绑定线程的会话
当频道支持线程绑定时,子代理可绑定到某线程,使后续同线程用户消息继续定向该子代理会话。支持线程的频道
- 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。
- 使用
sessions_spawn并设置thread: true(可选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 - 频道覆盖及启动自动绑定键依适配器而异,详见上文支持线程的频道。
agents.list[].subagents.allowAgents:允许通过agentId指定的代理 ID 列表(["*"]允许所有)。默认仅允许请求代理本身。- 沙箱继承限制:请求会话为沙箱环境时,
sessions_spawn会拒绝指向非沙箱运行时的目标。
- 使用
agents_list查询当前被允许用于sessions_spawn的代理 ID。
- 子代理会话会在
agents.defaults.subagents.archiveAfterMinutes(默认 60 分钟)后自动归档。 - 归档过程调用
sessions.delete,并将对话记录重命名为*.deleted.<timestamp>(同目录)。 cleanup: "delete"会在通报完成后立即归档(记录通过重命名保留)。- 自动归档为尽力而为策略,网关重启会丢失待处理定时任务。
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 编排者收到通报,综合结果后完成 → 通报给主代理
- 主代理接收通报并交付给用户
按深度的工具权限策略
- 深度 1(编排者,
maxSpawnDepth >= 2):拥有sessions_spawn、subagents、sessions_list、sessions_history,以便管理其子节点。其他会话/系统工具禁用。 - 深度 1(叶子,
maxSpawnDepth == 1):无会话工具(当前默认行为)。 - 深度 2(叶子工作者):无会话工具,
sessions_spawn始终禁用,无法继续派生。
每代理派生限制
每个代理会话(任意深度)最多可同时拥有maxChildrenPerAgent(默认 5)个活跃子会话,防止单点无限扩展。
级联停止
停止深度 1 编排者会级联停止其所有深度 2 子节点:- 在主聊天执行
/stop停止所有深度 1 子代理及其深度 2 子节点。 /subagents kill <id>停止指定子代理及其子节点。/subagents kill all停止请求者所有子代理并级联。
身份验证
子代理认证基于代理 ID,而非会话类型:- 子代理会话键格式为:
agent:<agentId>:subagent:<uuid>。 - 认证信息从该代理的
agentDir加载。 - 主代理的认证配置作为备用合并:若冲突,代理配置优先。
通报(Announce)
子代理通过通报步骤汇报结果:- 通报步骤运行在子代理会话(非请求者会话)内。
- 若子代理回复精确为
ANNOUNCE_SKIP,则不发送通报。 - 投递策略依请求深度区分:
- 顶层请求会话使用带外投递的
agent跟进调用(deliver=true) - 嵌套请求子代理会话使用内部跟进注入(
deliver=false),便于编排者在会话内综合子结果 - 如果嵌套请求会话不可用,OpenClaw 回退至该会话的请求者(如有)
- 顶层请求会话使用带外投递的
- 汇总子层完成结果限定于当前请求运行,防止旧运行子结果混入。
- 通报回复可保留线程/话题路由信息(若频道适配器支持)。
- 通报上下文标准化为稳定内部事件块,包含:
- 来源(
subagent或cron) - 子会话键/ID
- 通报类型及任务标签
- 状态行,依据运行结果(
success,error,timeout,unknown) - 通报步骤产生的结果内容(缺失则标记
(no output)) - 跟进指令,说明何时回复或保持沉默
- 来源(
Status非模型输出推断,而由运行时信号确定。
- 运行时长(如
runtime 5m12s) - 令牌使用(输入/输出/总计)
- 估算成本(当配置了模型计费信息
models.providers.*.models[].cost) sessionKey、sessionId和记录路径(方便主代理通过sessions_history或本地文件查看)- 内部元数据仅供编排使用,展示给用户的回复应以正常助手语气重写。
工具策略(子代理工具)
默认子代理可用除会话工具和系统工具外所有工具,具体剔除:sessions_listsessions_historysessions_sendsessions_spawn
maxSpawnDepth >= 2,深度 1 编排者子代理额外获得 sessions_spawn、subagents、sessions_list 和 sessions_history 权限以管理子节点。
可通过配置覆写:
并发
子代理使用独立的进程内队列通道:- 通道名:
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)。