# Parallel subagents
[Feature docs index](README.md) ยท [Repository README](../../README.md)
## Purpose
Ask the assistant to delegate independent tasks with the `subagents` tool. Each child gets its own task and bounded inherited context; optional identity profiles supply a persona, model, tool restrictions, or output format.
## Details
### Define independent tasks
| `intent` | Required nonblank objective. |
| `agent` | Optional label/persona only. |
| `identity` | Optional profile ID from the discovered identity list. |
| `context` | Optional self-contained instructions and relevant context. |
| `cwd` | Optional existing child directory; relative paths resolve from parent cwd, absolute paths follow `agent.subagents.execution.absolute_paths`. |
| Tasks per batch | At most `10`. |
| Requested concurrency | `1` to `4`, default `4`; actual workers also cannot exceed task count. |
| Nesting depth | Default `2`; `agent.subagents.execution.max_depth` accepts `1` to `4`. Set `1` for top-level-only delegation. |
The tool waits for completion and returns results in input order. Children inherit provider, tools, auth source, permissions, skills, `AGENTS.md` discovery, context/cache behavior, cwd policy, concurrency, and effective tool settings unless task context narrows work or an identity explicitly overrides supported settings. Primary-agent selection does not change child prompts.
At the depth limit, child schemas omit `subagents` and dispatch rejects direct recursive calls. Activity metadata includes depth so Mission Control can show nesting.
### Create an identity profile
Put profiles in `~/.magi-code/subagents/*.md` or `$MC_HOME/subagents/*.md`. The filename stem is the stable ID, limited to ASCII letters, digits, `_`, and `-`. Files must be UTF-8 Markdown, no more than 64 KiB, with non-empty frontmatter `name`/`description` and a non-empty prompt body. Direct profile symlinks are rejected.
For example, save this as `frontend-dev.md`:
```md
---
name: Frontend Developer
description: Use for focused browser-facing UI implementation, DOM behavior, and accessibility.
model: openai-codex/gpt-5.5
reasoning: high
disabled_tools: ['web']
output_schema:
type: object
required: [summary]
properties:
summary:
type: string
---
You are a frontend development specialist. Prioritize user-visible behavior, accessibility, small components, and browser validation when UI behavior changes.
```
Select it by `frontend-dev`, not its display name. Its body uses the same exact wrapper as primary profiles:
```text
<Your-Role Persona=Frontend Developer>
You must always follow the instructions of your assigned persona:
You are a frontend development specialist. Prioritize user-visible behavior, accessibility, small components, and browser validation when UI behavior changes.
</Your-Role>
```
Nested identities append their wrapper after inherited ancestor profiles; ancestor blocks remain in the prompt.
`model` uses `provider/model-name`, including custom IDs such as `local-ai/gpt-test`. `reasoning` accepts `default`, `low`, `medium`, or `high`; unsupported models fall back to default behavior. Mission Control's `/subagents` modal enables or disables profiles.
### Restrict tools
`disabled_tools` accepts a strict YAML-like subset: block lists or inline lists of unquoted names or simple fully single/double-quoted names. Comments and backslash escapes inside the list are unsupported. Unsupported syntax or unknown names makes the profile unavailable.
Aliases `shell`, `ffgrep`, and `fffind` become `bash`, `grep`, and `find`. Qualified `mcp__server__tool` names are accepted. Restrictions apply to child schemas and dispatch, add to inherited restrictions, and cannot be re-enabled by children or siblings. Siblings have isolated restriction sets. The shared `<Tools>` guidance remains unfiltered.
This is not a sandbox: allowed bash, MCP, browser, or hook routes may still produce equivalent effects. Parent auth, permissions, skills, cwd, concurrency, and nesting limits remain in force.
### Require structured output
Profiles can declare `output_schema` as JSON Schema. On completion, valid output returns a structured object to the parent. Invalid output returns structured validation details to the same child for retry. `agent.subagents.schema_validation_max_retries` defaults to `2` and accepts `0` to `5`. Custodian phases have built-in Plan, Research, Implement, Review, and Document schemas.
Persisted launches append a local-only `subagent_session` event with the child's `session_id` to the immediate parent before child execution. This lets the summarizer follow running children, including nested children, without scanning unrelated sessions or waiting for tool results. If the link cannot be written, the child fails before provider work starts.
### Understand retries and compaction
A retryable transport/stream error or HTTP `408`, `425`, `429`, `500`, `502`, `503`, or `504` gets one retry in the same child run after a 2 s backoff. Persisted runs retain their child session; `--no-session` repeats the original prompt. No retry occurs after a committed `write`/`hash_edit` filesystem change or batch cancellation. Final failure text starts with `[provider retry exhausted after N attempts]`.
Persisted children share the main agent's one-shot incomplete-stream and reasoning-only continuation behavior. With `agent.compaction.auto` enabled, eligible children also use hard-budget preflight and clean-boundary compaction with their selected model and context budget. See [Sessions, context, and cache](sessions-context-cache.md) for triggers and recovery.
Each automatic child compaction includes a provider-visible JSON scope document containing the complete original task and a fixed instruction to treat it as authoritative, summarize only that task, and exclude unrelated work. A prefix states that the document extends to the end of the instruction, keeping framing-like task text as data. It counts toward budget; if it makes the request too large, compaction stops before provider use or checkpoint writes.
The per-run compaction cap applies independently to each child: default `4`, with `0` removing only the count cap. Compaction rotates only the child's JSONL under `sessions/subagents/`, never the parent. Only that child receives the automatic `continue` after its checkpoint. Children without persistence cannot auto-compact. Mission Control shows attempted child compactions as nested activities with threshold and before/after token counts.
### Understand token totals
- Main and child totals include compaction summary requests and reported usage from retries, including schema retries. Each request uses its reported total, or normalized input plus output when both are known and no total was reported. Repeated usage snapshots replace earlier values for that request.
- Without a reported or derivable total, usage remains unknown; explicitly reported zero remains `0`. Missing usage is not estimated, so reported totals can be incomplete.
- Failed children retain any known request totals. The batch total is available only when every child result has a known total.
- Child totals exclude independently accounted nested children. Compaction usage uses the compaction provider's normalization and does not replace the active conversation's context-size estimate.
### Use hooks safely
Enabled, non-inert parent hook configuration is inherited. Parent hooks may match the top-level `subagents` call and record lifecycle events in the parent session. Child hooks run with each child's cwd and tool/root constraints; their lifecycle/diagnostic records stay only in child JSONL under `sessions/subagents/`.
Child hook internals never enter parent results, provider continuation, replay, recent context, or cache material. A hook-policy failure produces generic sanitized parent failure text; the child session holds the durable diagnostics.
With `automation.hooks.show_in_tui=true`, inherited hooks may appear under child task/tool activities. This display-only data is not provider-visible or replayed through parent results. There is no separate subagent hook configuration or UI. Concurrent children can run hooks concurrently, so scripts must coordinate shared external resources themselves.