--- summary: "Spawn isolated background agent runs that announce results back to the requester chat" read_when: - You want background or parallel work via the agent - You are changing sessions_spawn or sub-agent tool policy - You are implementing or troubleshooting thread-bound subagent sessions title: "Sub-agents" sidebarTitle: "Sub-agents" --- Sub-agents are background agent runs spawned from an existing agent run. Each one runs in its own session (`agent::subagent:`) and, when finished, **announces** its result back to the requester chat channel. Every sub-agent run is tracked as a [background task](/automation/tasks). Goals: - Parallelize research, long tasks, and slow tool work without blocking the main run. - Keep sub-agents isolated by default (session separation, optional sandboxing). - Keep the tool surface hard to misuse: sub-agents do **not** get session or message tools by default. - Support configurable nesting depth for orchestrator patterns. **Cost note:** each sub-agent has its own context and token usage by default. For heavy or repetitive tasks, set a cheaper model for sub-agents and keep your main agent on a higher-quality model via `agents.defaults.subagents.model` or per-agent overrides. When a child genuinely needs the requester's current transcript, spawn it with `context: "fork"`. Thread-bound subagent sessions default to `context: "fork"` because they branch the current conversation into a follow-up thread. ## Slash command `/subagents` inspects sub-agent runs for the **current session**: ```text /subagents list /subagents log [limit] [tools] /subagents info ``` `/subagents info` shows run metadata (status, timestamps, session id, transcript path, cleanup). `/subagents log` prints recent chat turns for a run; add the `tools` token to include tool-call/result messages (omitted by default). Use `sessions_history` for a bounded, safety-filtered recall view from within an agent turn, or inspect the transcript path on disk for the raw full transcript. In the Control UI, parent sessions with recent child runs have an expandable sidebar row. The nested rows show child status and runtime, and selecting one opens that child's chat while preserving the parent hierarchy. ### Thread binding controls These commands work on channels with persistent thread bindings. See [Thread supporting channels](#thread-supporting-channels) below. ```text /focus /unfocus /agents /session idle /session max-age ``` ### Spawn behavior Agents start background sub-agents with the `sessions_spawn` tool. Completions return as internal parent-session events; the parent/requester agent decides whether a user-facing update is needed. When [execution identity auditing](/gateway/audit#run-identity-inspection) is enabled, each native or ACP child receives a new immutable identity context. Its lineage links the exact parent context/run when available and records bounded references for the parent grant, local policy, runtime assurance, and target policy that constrained the spawn. Neither the private identity token nor task text appears in the tool schema, result, transcript-derived evidence, or public plugin API. External ACP-native actions without a callback remain explicitly unsupported even though the ACP spawn and child are observable. - `sessions_spawn` is non-blocking; it returns a run id immediately. - On completion, the sub-agent reports back to the parent/requester session. - Agent turns that need child results should call `sessions_yield` after spawning required work. That ends the current turn and lets the completion event arrive as the next model-visible message. - Completion is push-based. Once spawned, do **not** poll `/subagents list`, `sessions_list`, or `sessions_history` in a loop just to wait for it to finish; check status on-demand only when debugging. - Child output is a report/evidence for the requester agent to synthesize. It is not user-authored instruction text and cannot override system, developer, or user policy. - On completion, OpenClaw best-effort closes tracked browser tabs/processes opened by that sub-agent session before the announce cleanup flow continues. - OpenClaw hands completions back to the requester session through an `agent` turn with a stable idempotency key. - If the requester run is still active, OpenClaw first tries to wake/steer that run instead of starting a second visible reply path. - If an active requester cannot be woken, OpenClaw falls back to a requester-agent handoff with the same completion context instead of dropping the announce. - A successful parent handoff completes sub-agent delivery even when the parent decides no visible user update is needed. - Native sub-agents do not get the message tool. They return plain assistant text to the parent/requester agent; human-visible replies stay owned by the parent/requester agent's normal delivery policy. - If direct handoff cannot be used, delivery falls back to queue routing. A queued completion remains `session_queued`, rather than delivered, until the durable queue settles. - Automatic completion delivery retries for up to 30 minutes, starting around 15 seconds and capping the backoff at 5 minutes. Permanent failure or deadline expiry leaves the successful child task visibly blocked instead of discarding its result. - Blocked canonical results are retained for 7 days. Operators can retry or intentionally dismiss them from the Tasks page or with `openclaw tasks retry` / `openclaw tasks dismiss`; retry can duplicate a visible result after an ambiguous provider acknowledgement. - Delivery keeps the resolved requester route: thread-bound or conversation-bound completion routes win when available. If the completion origin only provides a channel, OpenClaw fills the missing target/account from the requester session's resolved route (`lastChannel` / `lastTo` / `lastAccountId`) so direct delivery still works. The completion handoff to the requester session is runtime-generated internal context (not user-authored text) and includes: - `Result` — the latest visible `assistant` reply text from the child. Tool/toolResult output is not promoted into child results. Terminal failed runs do not reuse captured reply text. - `Status` — `completed; ready for parent review` / `failed` / `timed out` / `unknown`. - Compact runtime/token stats. - A review instruction telling the requester agent to verify the result before deciding whether the original task is done. - Follow-up guidance telling the requester agent to continue the task or record a follow-up when the child result leaves more action. - A final-update instruction for the no-more-action path, written in normal assistant voice without forwarding raw internal metadata. - `--model` and `--thinking` override defaults for that specific run. - Use `info`/`log` to inspect details and output after completion. - For persistent thread-bound sessions, use `sessions_spawn` with `thread: true` and `mode: "session"`. - If the requester channel does not support thread bindings, use `mode: "run"` instead of retrying an impossible thread-bound combination. - For ACP harness sessions (Claude Code, Gemini CLI, OpenCode, or explicit Codex ACP/acpx), use `sessions_spawn` with `runtime: "acp"` when the tool advertises that runtime. See [ACP delivery model](/tools/acp-agents#delivery-model) when debugging completions or agent-to-agent loops. When the `codex` plugin is enabled, Codex chat/thread control should prefer `/codex ...` over ACP unless the user explicitly asks for ACP/acpx. - OpenClaw hides `runtime: "acp"` until ACP is enabled, the requester is not sandboxed, and a backend plugin such as `acpx` is loaded. `runtime: "acp"` expects an external ACP harness id, or an `agents.entries.*` entry with `runtime.type="acp"`; use the default sub-agent runtime for normal OpenClaw config agents from `agents_list`. ## Context modes Native sub-agents start isolated unless the caller explicitly asks to fork the current transcript. | Mode | When to use it | Behavior | | ---------- | -------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- | | `isolated` | Fresh research, independent implementation, slow tool work, or anything that can be briefed in the task text | Creates a clean child transcript. This is the default and keeps token use lower. | | `fork` | Work that depends on the current conversation, prior tool results, or nuanced instructions already present in the requester transcript | Branches the requester transcript into the child session before the child starts. | Use `fork` sparingly. It is for context-sensitive delegation, not a replacement for writing a clear task prompt. ## Tool: `sessions_spawn` Starts a sub-agent run with `deliver: false` on the global `subagent` lane, then runs an announce step and posts the announce reply to the requester chat channel. Availability depends on the caller's effective tool policy. The built-in `coding` and `messaging` profiles include `sessions_spawn`, `sessions_yield`, and `subagents`; `minimal` does not. `full` allows every tool. Add those tools with `tools.alsoAllow`, or use one of the profiles above, for an agent on a custom narrower profile that should still delegate work. Channel/group, provider, sandbox, and per-agent allow/deny policies can still remove the tool after the profile stage. Use `/tools` from the same session to confirm the effective tool list. **Defaults:** - **Model:** native sub-agents inherit the caller unless you set `agents.defaults.subagents.model` (or per-agent `agents.entries.*.subagents.model`). ACP runtime spawns use the same configured subagent model when present; otherwise the ACP harness keeps its own default. An explicit `sessions_spawn.model` still wins. - **Thinking:** native sub-agents inherit the caller unless you set `agents.defaults.subagents.thinking` (or per-agent `agents.entries.*.subagents.thinking`). ACP runtime spawns also apply `agents.defaults.models["provider/model"].params.thinking` for the selected model. An explicit `sessions_spawn.thinking` still wins. - **Run timeout:** pass `runTimeoutSeconds` to set a timeout for a specific native, ACP, or visible sub-agent run. When omitted, OpenClaw uses `agents.defaults.subagents.runTimeoutSeconds` if configured; otherwise it falls back to `0` (no timeout). An explicit `0` disables the timeout for that run. - **Process lifetime:** a detached OpenClaw sub-agent has its own run lifecycle. A background task created inside an external CLI backend is different: it shares the parent CLI subprocess and stops if that parent reaches `agents.defaults.timeoutSeconds`. - **Task delivery:** native sub-agents receive the delegated task in their first visible `[Subagent Task]` message. The sub-agent system prompt carries runtime rules and routing context, not a hidden duplicate of the task. Accepted native sub-agent spawns include the resolved child model metadata in the tool result: `resolvedModel` contains the applied model ref and `resolvedProvider` contains the provider prefix when the ref has one. ### Delegation prompt mode `agents.defaults.subagents.delegationMode` controls prompt guidance only; it does not change tool policy or enforce delegation. With no explicit setting, OpenClaw uses `prefer` in each agent's main session and `suggest` in every other session. - `suggest`: keep the standard prompt nudge to use sub-agents for larger or slower work. - `prefer`: tell the agent to stay responsive and delegate anything more involved than a direct reply through `sessions_spawn`. An explicit default or per-agent setting always wins, including `suggest` in a main session and `prefer` elsewhere. Per-agent overrides use `agents.entries.*.subagents.delegationMode`. In `prefer` mode, hidden sub-agents are for internal legwork that the user does not need to follow. Work the user will watch or return to, or work with its own deliverable such as a URL, PR, or report, should use `sessions_spawn` with `visible: true` so it remains in the sidebar. ```json5 { agents: { defaults: { subagents: { delegationMode: "prefer", maxConcurrent: 4, }, }, entries: { coordinator: { default: true, subagents: { delegationMode: "prefer" }, }, }, }, } ``` ### Tool parameters The task description for the sub-agent. Optional stable handle for identifying a specific child in later status output. Must match `[a-z][a-z0-9_-]{0,63}` and cannot be a reserved target such as `last` or `all`. Optional short task title shown in UI lists (task ledger, session sidebar). Name the work being done, not the agent; it is set on the child session at run start. Spawn under another configured agent id when allowed by `subagents.allowAgents`. Optional task working directory for the child run. Native sub-agents still load bootstrap files from the target agent workspace; `cwd` only changes where runtime tools and CLI harnesses do the delegated work. For visible sessions, paths outside configured agent workspaces require `operator.admin`; omit `cwd` to use the target agent workspace. `acp` is only for external ACP harnesses (`claude`, `droid`, `gemini`, `opencode`, or explicitly requested Codex ACP/acpx) and for `agents.entries.*` entries whose `runtime.type` is `acp`. ACP-only. Resumes an existing ACP harness session when `runtime: "acp"`; ignored for native sub-agent spawns. ACP-only. Streams ACP run output to the parent session when `runtime: "acp"`; omit for native sub-agent spawns. Override the sub-agent model. Invalid values are skipped and the sub-agent runs on the default model with a warning in the tool result. Override the configured run timeout for this child. Must be a non-negative integer; `0` disables the timeout. Applies to native, ACP, and visible sessions. Override thinking level for the sub-agent run. Not available with `visible: true`. When `true`, requests channel thread binding for this sub-agent session. If `thread: true` and `mode` is omitted, default becomes `session`. `mode: "session"` requires `thread: true`. If thread binding is unavailable for the requester channel, use `mode: "run"` instead. With `visible: true`, omit `mode`; visible sessions are persistent and do not support `mode: "run"`. `"delete"` archives the session immediately after announce (still keeps the transcript via rename). `require` rejects the spawn unless the target child runtime is sandboxed. `fork` branches the requester's current transcript into the child session. Native sub-agents only. Thread-bound spawns default to `fork`; non-thread spawns default to `isolated`. A visible fork must target the same agent as the requester. Create a persistent dashboard session for work the user will watch or return to, or when they ask for a thread. Visible spawns support only `runtime: "subagent"` and always keep the created session. Optional sidebar category for a visible session. Omit it or pass an empty string to leave the session ungrouped. Requires `visible: true`. Provision a managed git worktree for the new dashboard session. Requires `visible: true`. Optional managed-worktree name. Requires `visible: true` and `worktree: true`. Optional git base ref for the managed worktree. Requires `visible: true` and `worktree: true`. `sessions_spawn` does **not** accept channel-delivery params (`target`, `channel`, `to`, `threadId`, `replyTo`, `transport`). Native sub-agents report their latest assistant turn back to the requester; external delivery stays with the parent/requester agent. With `visible: true`, `category`, `model`, `cwd`, and a same-agent `context: "fork"` are supported. Use this durable mode for coding, multi-step work, or results the user may revisit, steer, or keep; it appears in the sidebar when the web UI is available and still works without it. Pass `category` to place the new session in that sidebar group atomically; omission and an empty string leave it ungrouped. A sandboxed target restricts `cwd` to that agent's workspace. Non-admin callers may use `cwd` only inside a configured agent workspace. Omit `cwd` to use the target agent workspace; for another repository, ask the operator to start the session from a registered project. Do not replace a rejected persistent spawn with the synchronous `openclaw agent` CLI, whose command deadline defaults to 600 seconds. Thread binding, `mode`, thinking overrides, `lightContext`, `attachments`, and `attachAs` are unavailable on this path because visible sessions are persistent dashboard sessions created through `sessions.create`. The new dashboard child inherits the requester's effective tool-policy ceiling before its first turn. Session listing and addressing obey `tools.sessions.visibility`; the default `tree` scope covers the current session and its own spawn subtree, while the main session can reach every same-agent session unless `self` or the sandbox spawned-only clamp applies. See [Session tools](/concepts/session-tool#visibility) and [Managed worktrees](/concepts/managed-worktrees). A visible spawn is attributed to the requesting agent: the new session's creator and initial owner is that agent, shown with its configured identity name and avatar in the sidebar. The accepted result doubles as a receipt with `childSessionKey`, `runId`, a Control UI `sessionUrl` (omitted when the Control UI is disabled), and an `owner` record. When acknowledging the spawn in a channel, put the session URL on the first line and `Owner: