代理协作
子智能体
子智能体是从现有智能体运行中派生的后台智能体运行。
它们在自己的会话(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>]
使用顶层 /steer <message> 来 Steer 当前请求方会话的活跃运行。当目标是子运行时,使用 /subagents steer <id|#> <message>。
/subagents info 会显示运行元数据(状态、时间戳、会话 ID、
转录记录路径、清理)。使用 sessions_history 获取有界、
经过安全过滤的回忆视图;当你需要原始完整转录记录时,请检查磁盘上的转录记录路径。
线程绑定控制
这些命令适用于支持持久线程绑定的渠道。 请参见下方的支持线程的渠道。
/focus <subagent-label|session-key|session-id|session-label>
/unfocus
/agents
/session idle <duration|off>
/session max-age <duration|off>
派生行为
/subagents spawn 会作为用户命令(而不是内部中继)启动一个后台子智能体,
并在运行完成时向请求方聊天发送一次最终完成更新。
Non-blocking, push-based completion
- 派生命令是非阻塞的;它会立即返回一个运行 ID。
- 完成时,子智能体会向请求方聊天渠道通知一条摘要/结果消息。
- 完成是基于推送的。派生后,不要仅仅为了等待其完成而循环轮询
/subagents list、sessions_list或sessions_history;只在调试或干预需要时按需检查状态。 - 完成时,OpenClaw 会尽力关闭该子智能体会话打开并被跟踪的浏览器标签页/进程,然后继续执行通知清理流程。
Manual-spawn delivery resilience
- OpenClaw 会通过带有稳定幂等键的
agent轮次,把完成结果交回请求方会话。 - 如果请求方运行仍处于活跃状态,OpenClaw 会先尝试唤醒/Steer 该运行,而不是启动第二条可见回复路径。
- 如果请求方智能体的完成交接失败,或没有产生可见输出,OpenClaw 会将投递视为失败,并回退到队列路由/重试。它不会把子运行结果直接原样发送到外部聊天。
- 如果无法使用直接交接,则会回退到队列路由。
- 如果队列路由仍不可用,通知会在最终放弃前使用短暂的指数退避进行重试。
- 完成投递会保留已解析的请求方路由:当线程绑定或对话绑定的完成路由可用时优先使用;如果完成来源只提供了渠道,OpenClaw 会从请求方会话已解析路由(
lastChannel/lastTo/lastAccountId)中补齐缺失的目标/账号,因此直接投递仍然可用。
Completion handoff metadata
交接给请求方会话的完成信息是运行时生成的 内部上下文(不是用户编写的文本),并包含:
Result— 最新可见的assistant回复文本;否则为经过净化的最新工具/toolResult 文本。终止失败的运行不会复用已捕获的回复文本。Status—completed successfully/failed/timed out/unknown。- 紧凑的运行时/token 统计信息。
- 一条投递指令,要求请求方智能体用正常助手语气改写(而不是转发原始内部元数据)。
Modes and ACP runtime
--model和--thinking会覆盖该特定运行的默认值。- 使用
info/log在完成后检查详情和输出。 /subagents spawn是一次性模式(mode: "run")。对于持久线程绑定会话,请使用带有thread: true和mode: "session"的sessions_spawn。- 对于 ACP harness 会话(Claude Code、Gemini CLI、OpenCode,或显式 Codex ACP/acpx),当工具声明支持该运行时时,请使用带有
runtime: "acp"的sessions_spawn。调试完成结果或智能体到智能体循环时,请参见 ACP 投递模型。启用codex插件时,除非用户明确要求 ACP/acpx,否则 Codex 聊天/线程控制应优先使用/codex ...而不是 ACP。 - OpenClaw 会隐藏
runtime: "acp",直到启用 ACP、请求方未处于沙箱隔离状态,并且加载了诸如acpx的后端插件。runtime: "acp"需要一个外部 ACP harness ID,或一个带有runtime.type="acp"的agents.list[]条目;对于来自agents_list的普通 OpenClaw 配置智能体,请使用默认子智能体运行时。
上下文模式
原生子智能体会以隔离方式启动,除非调用方明确要求 fork 当前转录记录。
| 模式 | 使用场景 | 行为 |
|---|---|---|
isolated |
全新研究、独立实现、慢速工具工作,或任何可在任务文本中简要说明的事项 | 创建干净的子转录记录。这是默认值,并会降低 token 使用量。 |
fork |
依赖当前对话、先前工具结果,或请求方转录记录中已有的细微指令的工作 | 在子智能体启动前,把请求方转录记录分支到子会话中。 |
请谨慎使用 fork。它用于对上下文敏感的委派,
而不是替代清晰任务提示的写法。
工具:sessions_spawn
在全局 subagent 通道上以 deliver: false 启动子智能体运行,
然后运行通知步骤,并将通知回复发布到请求方
聊天渠道。
可用性取决于调用方的有效工具策略。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(无超时)。
工具参数
taskstringrequired子智能体的任务描述。
labelstring可选的人类可读标签。
agentIdstring当 subagents.allowAgents 允许时,在另一个智能体 ID 下派生。
runtime"subagent" | "acp"acp 仅用于外部 ACP harness(claude、droid、gemini、opencode,或明确请求的 Codex ACP/acpx),以及 runtime.type 为 acp 的 agents.list[] 条目。
resumeSessionIdstring仅限 ACP。当 runtime: "acp" 时恢复现有 ACP harness 会话;对于原生子智能体派生会被忽略。
streamTo"parent"仅限 ACP。当 runtime: "acp" 时,将 ACP 运行输出流式传输到父会话;对于原生子智能体派生请省略。
modelstring覆盖子智能体模型。无效值会被跳过,子智能体会在默认模型上运行,并在工具结果中给出警告。
thinkingstring覆盖子智能体运行的思考级别。
runTimeoutSecondsnumber已设置时默认为 agents.defaults.subagents.runTimeoutSeconds,否则为 0。设置后,子智能体运行会在 N 秒后中止。
threadboolean当为 true 时,为此子智能体会话请求渠道线程绑定。
mode"run" | "session"如果 thread: true 且省略 mode,默认值会变为 session。mode: "session" 要求 thread: true。
cleanup"delete" | "keep""delete" 会在通知后立即归档(仍通过重命名保留转录记录)。
sandbox"inherit" | "require"require 会拒绝派生,除非目标子运行时处于沙箱隔离状态。
context"isolated" | "fork"fork 会把请求方当前转录记录分支到子会话中。仅限原生子智能体。线程绑定派生默认为 fork;非线程派生默认为 isolated。
线程绑定会话
当某个渠道启用线程绑定时,子智能体可以保持绑定到 某个线程,使该线程中的后续用户消息继续路由到 同一个子智能体会话。
支持线程的渠道
Discord 目前是唯一受支持的渠道。它支持
持久线程绑定的子智能体会话(带有
thread: true 的 sessions_spawn)、手动线程控制(/focus、/unfocus、/agents、
/session idle、/session max-age),以及适配器键
channels.discord.threadBindings.enabled、
channels.discord.threadBindings.idleHours、
channels.discord.threadBindings.maxAgeHours 和
channels.discord.threadBindings.spawnSessions。
快速流程
生成
使用带有 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。 - 渠道覆盖和生成自动绑定键 特定于适配器。参见上方的 支持线程的渠道。
允许列表
agents.list[].subagents.allowAgentsstring[]可通过显式 agentId 定位的智能体 id 列表(["*"] 允许任意智能体)。默认值:仅请求方智能体。如果你设置了列表,并且仍希望请求方通过 agentId 生成自身,请将请求方 id 包含在列表中。
agents.defaults.subagents.allowAgentsstring[]当请求方智能体未设置自己的 subagents.allowAgents 时使用的默认目标智能体允许列表。
agents.defaults.subagents.requireAgentIdboolean阻止省略 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"会在公告后立即归档(仍会通过重命名保留转录)。- 自动归档是尽力而为;如果 Gateway 网关重启,待处理的计时器会丢失。
runTimeoutSeconds不会自动归档;它只会停止运行。会话会保留到自动归档为止。- 自动归档同样适用于深度 1 和深度 2 会话。
- 浏览器清理与归档清理相互独立:跟踪的浏览器标签页/进程会在运行结束时尽力关闭,即使转录/会话记录被保留。
嵌套子智能体
默认情况下,子智能体不能生成自己的子智能体(maxSpawnDepth: 1)。设置 maxSpawnDepth: 2 可启用一层嵌套,即 编排器模式:主智能体 → 编排器子智能体 → 工作子子智能体。
{
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)
},
},
},
}
深度级别
| 深度 | 会话键形状 | 角色 | 能生成吗? |
|---|---|---|---|
| 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在深度 2 始终被拒绝。不能继续生成子级。
按智能体的生成限制
每个智能体会话(任意深度)同一时间最多可以有 maxChildrenPerAgent 个活动子级(默认 5)。这可以防止单个编排器失控扇出。
级联停止
停止深度 1 编排器会自动停止其所有深度 2 子级:
- 主聊天中的
/stop会停止所有深度 1 智能体,并级联停止它们的深度 2 子级。 /subagents kill <id>会停止特定子智能体,并级联停止其子级。/subagents kill all会停止请求方的所有子智能体并级联。
身份验证
子智能体身份验证按 智能体 id 解析,而不是按会话类型解析:
- 子智能体会话键是
agent:<agentId>:subagent:<uuid>。 - 身份验证存储从该智能体的
agentDir加载。 - 主智能体的身份验证配置文件会作为 回退 合并进来;冲突时,智能体配置文件会覆盖主配置文件。
合并是增量式的,因此主配置文件始终可用作回退。尚不支持按智能体完全隔离的身份验证。
公告
子智能体通过公告步骤回报:
- 公告步骤在子智能体会话内运行(不是请求方会话)。
- 如果子智能体精确回复
ANNOUNCE_SKIP,则不会发布任何内容。 - 如果最新助手文本是精确的静默令牌
NO_REPLY/no_reply,即使之前存在可见进度,也会抑制公告输出。
交付取决于请求方深度:
- 顶层请求方会话使用带外部交付的后续
agent调用(deliver=true)。 - 嵌套请求方子智能体会话会收到内部后续注入(
deliver=false),以便编排器可在会话内综合子级结果。 - 如果嵌套请求方子智能体会话已消失,OpenClaw 会在可用时回退到该会话的请求方。
对于顶层请求方会话,完成模式直接交付会先解析任何已绑定的对话/线程路由和钩子覆盖,然后从请求方会话存储的路由中填充缺失的渠道目标字段。这样即使完成来源只标识了渠道,也能让完成内容进入正确的聊天/主题。
在构建嵌套完成发现时,子级完成聚合会限定到当前请求方运行,防止过期的先前运行子级输出泄漏到当前公告中。公告回复会在渠道适配器可用时保留线程/主题路由。
公告上下文
公告上下文会归一化为稳定的内部事件块:
| 字段 | 来源 |
|---|---|
| 来源 | subagent 或 cron |
| 会话 id | 子会话键/id |
| 类型 | 公告类型 + 任务标签 |
| Status | 从运行时结果派生(success、error、timeout 或 unknown)— 不是从模型文本推断 |
| 结果内容 | 最新可见助手文本,否则为经过清理的最新工具/toolResult 文本 |
| 后续 | 描述何时回复与何时保持静默的指令 |
终止时失败的运行会报告失败状态,而不会重放已捕获的回复文本。超时时,如果子级只执行到工具调用,公告可以将该历史折叠为简短的部分进度摘要,而不是重放原始工具输出。
统计行
公告载荷末尾包含统计行(即使被包装):
- 运行时(例如
runtime 5m12s)。 - 令牌用量(输入/输出/总计)。
- 配置了模型定价时的估算成本(
models.providers.*.models[].cost)。 sessionKey、sessionId和转录路径,以便主智能体可通过sessions_history获取历史,或检查磁盘上的文件。
内部元数据仅用于编排;面向用户的回复应改写为正常的助手语气。
为什么优先使用 sessions_history
sessions_history 是更安全的编排路径:
- 助手回忆会先被归一化:剥离思考标签;剥离
<relevant-memories>/<relevant_memories>脚手架;剥离纯文本工具调用 XML 载荷块(<tool_call>、<function_call>、<tool_calls>、<function_calls>),包括永远无法干净闭合的截断载荷;剥离降级的工具调用/结果脚手架和历史上下文标记;剥离泄漏的模型控制令牌(<|assistant|>、其他 ASCII<|...|>、全角<|...|>);剥离格式错误的 MiniMax 工具调用 XML。 - 类似凭证/令牌的文本会被脱敏。
- 长块可能被截断。
- 非常大的历史可能会丢弃较旧行,或将超大的行替换为
[sessions_history omitted: message too large]。 - 当你需要完整逐字节转录时,原始磁盘转录检查是回退方案。
工具策略
子智能体首先使用与父级或目标智能体相同的配置档案和工具策略流水线。之后,OpenClaw 会应用子智能体限制层。
在没有限制性 tools.profile 的情况下,子智能体会获得除会话工具和系统工具以外的所有工具:
sessions_listsessions_historysessions_sendsessions_spawn
sessions_history 在这里也仍然是一个有界、经过清理的回忆视图,不是原始转录文本转储。
当 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"]
},
},
},
}
tools.subagents.tools.allow 是最终的仅允许过滤器。它可以缩窄已经解析出的工具集,但不能重新加入被 tools.profile 移除的工具。例如,tools.profile: "coding" 包含 web_search/web_fetch,但不包含 browser 工具。若要让使用编码配置档案的子智能体使用浏览器自动化,请在配置档案阶段添加 browser:
{
tools: {
profile: "coding",
alsoAllow: ["browser"],
},
}
当只有一个智能体应获得浏览器自动化能力时,使用按智能体配置的 agents.list[].tools.alsoAllow: ["browser"]。
并发
子智能体使用专用的进程内队列通道:
- 通道名称:
subagent - 并发数:
agents.defaults.subagents.maxConcurrent(默认8)
存活性和恢复
OpenClaw 不会把缺少 endedAt 视为子智能体仍然存活的永久证明。早于陈旧运行窗口且尚未结束的运行,在 /subagents list、状态摘要、后代完成门控和按会话并发检查中不再计为活跃/待处理。
Gateway 网关重启后,陈旧且尚未结束的已恢复运行会被修剪,除非其子会话被标记为 abortedLastRun: true。这些因重启而中止的子会话仍可通过子智能体孤儿恢复流程恢复;该流程会先发送一条合成恢复消息,然后清除中止标记。
自动重启恢复按每个子会话设有边界。如果同一个子智能体子级在快速重复卡住窗口内反复被接受进行孤儿恢复,OpenClaw 会在该会话上持久化一个恢复墓碑,并在后续重启时停止自动恢复它。运行 openclaw tasks maintenance --apply 来协调任务记录,或运行 openclaw doctor --fix 清除已墓碑化会话上的陈旧中止恢复标志。
停止
- 在请求方聊天中发送
/stop会中止请求方会话,并停止从该会话生成的任何活跃子智能体运行,同时级联到嵌套子级。 /subagents kill <id>会停止特定子智能体,并级联到其子级。
限制
- 子智能体公告是尽力而为的。如果 Gateway 网关重启,待处理的“公告返回”工作会丢失。
- 子智能体仍共享同一个 Gateway 网关进程资源;请将
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)。