Two Ecosystems: Claude Code and OpenAI Codex
Claude Subagents: A Separate Context for a Delegated Task
How Claude Code subagents give a delegated task its own context window, what that boundary does and does not isolate, and how a main agent writes the…
Snapshot of fast-changing documentation: 10 October 2026.
Picture the work that sometimes has to happen before a change ships: reading several thousand lines of logs, checking three independent modules, or tracing a requirement through to the files and tests that implement it. If the main conversation absorbs all of that intermediate material, the context that actually matters gets buried in detail. Claude Code can hand this kind of work to a subagent, a helper agent that runs inside the same session. The subagent gets its own context window, carries out a bounded task, and returns its result to the main agent.
A subagent does not automatically see the main conversation's history. At the same time, a separate context is not a separate machine. In a normal launch a subagent often works in the same repository and may have the same tools and the same access to external systems. The context boundary reduces noise; it does not guarantee safety, independence or correctness. Files, the network, permissions and external side effects all have boundaries of their own.
Everything below is about Claude Code specifically, not every Anthropic product. The documentation and the public bug reports cited here were checked on 10 October 2026. On that date the latest release on the Claude Code Releases page was v2.1.296, published on 9 October; among other things it added the autoCompactWindow field to subagent configuration. Treat this as a snapshot in time, not a promise about every version. Configuration fields and client behaviour change, so check your Claude Code version and the matching documentation before relying on any of this in practice. [9]
What gets delegated and what comes back
In the usual model a subagent is not an independent worker that decides the team's goal for itself. The main agent or the user assigns it a specific piece of work. The subagent receives its own context and whatever tools it is allowed, does the work, and hands the result back to whoever called it. The main agent coordinates, decides what to accept, and composes the answer for the user.
For example, the main agent might ask one subagent to find out where an error originates and another to find every place that calls a suspicious function. Each should return not just a conclusion but evidence: the file, the exact line or excerpt, the condition under which the problem appears, and what remains unknown. The main agent then compares the results and checks the important points itself before calling a change done.
Claude Code ships with built-in agent types: Explore for investigation, Plan for planning, a General-purpose type, and several helper types. The built-in Explore and Plan are meant for reading and analysis; their Write and Edit tools are denied. General-purpose can carry out multi-step work, including both research and changes, provided it has the necessary tools and permissions. You can also configure a custom subagent for a recurring role. Do not treat the names of the built-in types as a universal list of every agent: which types exist depends on the current session, version and settings. [1]
It helps to keep five separate events apart:
- Task assignment. The main agent decided to delegate the work and composed the message for the subagent.
- Start. The environment found the agent type, applied its configuration and created the worker.
- Execution. The subagent read the context available to it, called tools and received their actual results.
- End of the call. The tool reported that the run finished, was stopped, or failed.
- Acceptance of the result. The main agent checked whether the returned evidence is sufficient for the original task.
These are not the same thing. A delegation request appearing in the transcript does not prove that the agent started. A successful call to the agent-creation tool does not prove that the delegated task was carried out. And a subagent finishing is not automatic confirmation that its conclusion is right.
The context boundary: what the agent knows and what it does not
An ordinary, non-forked subagent starts with a fresh context window. It does not see the main agent's earlier dialogue, does not know which files the main agent has already read, and does not automatically receive every intermediate observation. What it gets is the system instruction for its type, the message describing the delegated task, environment details, and whatever files or tools it can reach on its own. The exception is fork mode, which takes the earlier dialogue as its starting context; do not confuse it with the default launch of a new subagent. [1]
For an ordinary subagent, Claude Code composes the initial message. That is why the main agent has to pass enough context: the name and scope of the task, the requirement, the important findings so far, the version or revision of the code, the source of truth, and the completion criterion. Do not expect a new agent to guess which sentence in an earlier conversation "the thing we just discussed" refers to. If critical context does not fit in the prompt, name the specific file, issue or resource the agent should open, and make sure it has the tool and access to do so.
In project sessions a subagent usually loads the CLAUDE.md hierarchy and the other instructions the main conversation would load for that environment. The built-in Explore and Plan types have exceptions, and the omitClaudeMd field can change this behaviour. These are instructions and context, not an automatic transfer of the conversation. The full file may be too long, or may not contain a specific fact that was only ever stated in the chat. Check that an important rule really applies to this session. [1]
A fork is a separate option: it starts from a copy of the main agent's conversational context instead of a fresh context plus a delegation message. That is useful when the agent needs a broad history. But a long context reduces the noise-isolation benefit, can carry along data the task does not need, and does not make the fork an independent observer. In Claude Code the /subtask command creates such a background fork of the current conversation (available since v2.1.212); it is not the name of a type defined in .claude/agents/. The context: fork field in a Skill is yet another, separate way to run a Skill in a forked context. Separate Claude Code sessions that exchange messages with each other are a different mechanism again. A fork, a subagent, a Skill with a fork context and a separate session have different state boundaries and are not synonyms. [1]
The minimum delegation contract
Before calling a subagent, write the contract down as a short technical brief:
| Part | What to pass on |
|---|---|
| Result | An answer to one question, a report, a recommendation, or changes in precisely named files. |
| Scope | The repository and directories, issue, diff, branch or component to cover. |
| Exclusions | What is outside the task: do not edit files, do not run the migration, do not write to Jira, and so on. |
| Source of truth | Which criterion, document or system state takes precedence, and how to flag contradictions. |
| Inputs | The starting revision, exact task keys, links, available logs, files and constraints. |
| Evidence | For every conclusion: the source, an excerpt or coordinates, the condition, and the level of uncertainty. |
| Access and side effects | Which tools are allowed; whether the agent may edit, run shell commands or touch external services. |
| Response format | For example, a table of "requirement → file/test → observation → gap". |
| Completion criterion | Exactly which questions must be closed, what to mark as not done, and when to stop. |
A role such as "you are a testing expert" is not a substitute for a contract. "Check the code" defines neither the boundary of the check, nor the requirement, nor what counts as evidence, and "investigate everything" invites excessive scope. A good assignment lets you read the response and tell what was checked, what is still needed, and what the result means.
For work that involves changes, it helps to split two permissions. Permission to investigate covers reading a defined area and running safe checks. Permission to change names the specific files and the acceptable diff. Writing a local file is a side effect too; running a shell command can be a much broader one. Changing Jira, sending an email, publishing a release or applying a migration have consequences outside the file system. If the worker does not explicitly need a power, the contract should forbid it.
When a subagent helps and when it creates extra work
A subagent is a good fit when the result is local and can be verified on its own: investigating one subsystem; scanning a large directory and returning a few coordinates; comparing several independent sources; analysing logs and producing a timeline; independently checking individual acceptance criteria; or doing work with a narrowly restricted set of tools. It is also useful when the detailed intermediate results do not need to live in the main context.
The main conversation is usually better for a small change, for frequent back-and-forth clarification, for work that keeps using the same body of context, for sequential dependent steps, or when it matters to see the whole picture from start to finish. If you have to keep re-teaching a subagent the history or feeding it one new fact at a time, the savings can disappear. A subagent call also adds latency and its own token costs. Anthropic recommends using subagents for self-contained work, for tasks that produce large output, or where separate access restrictions are needed, and keeping short iterative tasks in the main conversation. [1]
A separate limit applies to parallelism: it only speeds up work that is genuinely independent. If one agent must first find the criteria and the next must apply them to a specific diff, that is a sequence. If two agents change the same file, they may conflict. It is better to split tasks by file, module, source or question than to multiply workers for the sake of numbers.
How a subagent differs from related mechanisms
| Mechanism | What it is for | How it relates to the main context |
|---|---|---|
| One-off prompt | A single message with an instruction for the current turn | Runs in the main conversation unless the host launches it some other way. |
| Subagent | A delegated, bounded piece of work within the same Claude Code session | A normal launch has a fresh context window and returns its result to whoever called it. |
| Skill | Reusable instructions, reference material or a procedure for a class of tasks | In Claude Code it can be loaded into the main context, or run as a fork/subagent if configured that way. By default a Skill is not a different worker. |
| Separate session / cross-session messaging | Another self-contained Claude Code conversation that can exchange messages with other sessions in a supported setup | Has its own session lifetime; it is not a short child call within the current tree. |
| Agent team | Several Claude Code sessions coordinating as a team | Members have their own contexts, can message each other and use a shared task list. |
| Tool or MCP (Model Context Protocol) | A specific machine action or integration with external data | Can be called by the main agent or by a subagent, if available and permitted. |
An agent team is not just a name for a group of subagents. A team coordinates separate sessions through messages and a shared task list; subagents, in the normal case, return their results to the main agent, which distributes and consolidates the work. Teams carry more overhead and use more tokens; they suit independent parts of a large piece of work better than sequential steps or edits to a single file. The Claude Code documentation marks agent teams as an experimental feature that is off by default; check the official reference for the current way to enable it and its limitations. The documentation describes agent teams and cross-session messaging separately. [2]
A Skill is not an "agent with knowledge" either. For instance, a Skill might hold a recurring review checklist, while a subagent uses that checklist to investigate a particular module and return a concise report. The body of a Skill does not, by itself, create a tool, grant access or provide an isolated working environment. Claude Code can run a Skill in its own subagent context, but that is a separately configured capability, not a property of every Skill. [1]
The current documentation uses a new name for the delegation tool: Task became Agent in Claude Code v2.1.63, and the old Task(...) references in settings and definitions still work as a compatible alias. If the documentation, a session transcript and the interface name the operation differently, check the version rather than concluding that they must be different capabilities. [1]
Claude Code configuration: what an agent file describes
A custom subagent is defined by a Markdown file with YAML frontmatter (YAML Ain't Markup Language, a data-serialisation format): a block of settings between --- lines, followed by a Markdown body that becomes the subagent's system instruction. Project definitions live in .claude/agents/; personal ones in ~/.claude/agents/. There are also managed definitions, plugin definitions, and one-off definitions passed through the command-line interface (CLI). The location determines scope and precedence, and the name field provides the identifier. name and description are required for a file-based definition. Unknown frontmatter fields may be ignored without any error, which makes a typo in a key dangerous: the restriction you expected simply does not take effect. [1]
Invocation can be automatic: Claude takes its cue from how the task is phrased, the subagent's description and the context. You can also name the type in a natural-language request, write it as an @-mention, ask the main agent to call the Agent tool with a specific type, or make the whole session run as that subagent through --agent or the agent setting. A natural mention is only a hint; an explicit @-mention assigns the type for one task, but it does not determine the full prompt the main agent will compose for it. The session-level --agent changes the role of the session's main thread; it is not a child call. [1]
The type name in the example below refers to an application programming interface (API). In simplified form, a definition file might look like this:
---
name: api-contract-reader
description: Compares API changes against the given contract; does not edit files.
tools: Read, Grep, Glob
model: sonnet
maxTurns: 12
---
Find contract changes in the given module. For each deviation,
give the path, line, expected rule and the actual code.
Do not run the shell, do not edit files, and do not change external state.
If the contract or a required path is missing, name the gap.
This is an example configuration, not a guarantee that the model name, available tools or restrictions in a particular installation match it. The body text provides instructions. What tools and actions are actually available is decided by the configuration fields and by Claude Code's policy.
The main fields supported by the current documentation [1]:
| Field | What it sets | Limits |
|---|---|---|
name |
The identifier of the subagent type | Must be unique among the available configurations; the file itself can have a different name. |
description |
When Claude should choose this type | Helps delegation, but does not guarantee the type is invoked for every matching task. |
tools |
The allowed list of available tools | If the field is absent, the subagent inherits the tools available to subagents. Inheritance is broader than minimal safe access. |
disallowedTools |
Tools to remove from the list | Does not replace separate rules for shell commands or an external sandbox. |
model |
A model or a model-selection rule | For example sonnet, opus, haiku, fable, a full model identifier, or inherit; availability and the actual choice depend on the environment and other configuration. |
permissionMode |
The permission mode for the subagent | The documented modes include default, acceptEdits, auto, dontAsk, bypassPermissions and plan; manual is an alias for default from v2.1.200. If the main session is in bypassPermissions, acceptEdits or auto, the subagent runs in the session's mode and this field is ignored. For default, dontAsk or plan the mode from the definition is used, but the subagent cannot switch itself into bypassPermissions; that exception requires v2.1.267+. [1] |
maxTurns |
The maximum number of agentic turns | When the limit is reached a partial result may come back; this is no guarantee that the task is complete. |
skills |
Skills whose full text is preloaded | Merely listing a Skill among the tools does not preload it in the same way. |
mcpServers |
MCP servers for the subagent | Can reference a configured server or describe a server inline; this creates or exposes a possible path to external actions. |
hooks |
Event rules active while this subagent runs | These are executable settings; you need to understand which events they control. |
memory |
Personal, project or local long-term memory | Memory persists across conversations and may update files; it is separate state, not the history of the current task. |
background |
A preference for running in the background | Background mode affects when the result comes back and how permission prompts are shown; it does not mean isolation from files. |
omitClaudeMd |
Whether to skip some project instructions | Exact availability depends on the version and the kind of definition. |
initialPrompt |
The opening message for the agent when its definition is launched as the main agent via --agent or the agent setting |
Not a substitute for the subagent's body prompt; ignored for plugin subagents. |
effort |
The model effort level for this type | Allowed values depend on the model and version. |
autoCompactWindow |
Compacting this subagent's context automatically earlier than the main conversation's | Available from v2.1.296; reduces the context size, but does not guarantee that every intermediate detail survives into the later summary. |
isolation |
For shell/PowerShell, a temporary Git worktree | Not a full sandbox and not network isolation. |
color |
The colour that marks the agent in the task list and transcript | A visual cue only; it does not affect access. |
experimental |
A map of experimental options; the use described in the current documentation is cacheTtl: 5m or 1h for the prompt-cache lifetime |
Requires v2.1.248 or later; 1h is ignored when usage credits are being used on a Claude subscription, and other unknown values are also ignored. This is a changing feature, not a stable universal field. [1] |
The --agents command-line flag can define subagents in JSON (JavaScript Object Notation, a text format for exchanging structured data) for the current session only. There the instruction is passed in a prompt field rather than as the body of a separate file, and the available fields may differ somewhat. Do not copy a CLI example into file frontmatter without checking the relevant section of the documentation. A definition in .claude/agents/ is meant for the project and can be committed to Git so that colleagues see it. [1]
The documentation says definitions are normally picked up during a session, but there are cases where a newly created agents directory, or a path added through --add-dir, is only read after a restart. Separately, there is a GitHub issue from 7 August 2026 reporting that the file .claude/agents/architect.md in Claude Code 2.1.222 on macOS was not immediately visible to the Agent tool and only appeared a few minutes later. As of 10 October 2026, GitHub shows the issue as closed with the reason "not planned" and an inactivity label; that administrative closure does not confirm that the behaviour was fixed. It is a single report, not proof of universal behaviour, but it shows why you should confirm that an agent type is actually available before assuming its restrictions already apply. The reporter also warns that falling back to a general-purpose type with the charter written into the prompt does not carry over the undiscovered agent's tool allowlist. Do not substitute a broader type and assume that charter text restricts its tools. [1, 5]
In Claude Code v2.1.198 and later, the /agents command no longer opens the old interactive editor/wizard; instead it reminds you to ask Claude to create a definition or to edit the file yourself. That is a useful version note for instructions that still promise a setup wizard. [1]
Tools, permissions, memory and the real isolation boundary
By default, subagents can inherit the built-in and MCP tools of the main conversation, after which some tools are filtered out depending on the type or on background launch. A custom tools list is an allowlist, the set of tools that remain available; disallowedTools removes tools. If the agent only needs to read code, list the reading tools it needs (for example Read, Grep and Glob) and do not add Bash, Write or Edit without a reason. Do not assume that the absence of an explicit permission in the prompt body takes a tool away from the agent: if tools is not specified, it may inherit a broad set. [1]
The Bash tool means the ability to run commands, not just "read a test result". A shell can change files, run programs, read environment variables, talk to the network or use whatever credentials are available. A textual request to "change nothing" is a useful instruction but not a technical boundary. Even a permission pattern for a specific command can have gaps for variants of that command. Anthropic explicitly warns that a WebFetch permission does not, by itself, block network access for curl or other programs if Bash is available. Security requirements need tool allowlists and denylists, permission rules, hooks and appropriate sandboxing, not just hope placed in the prompt. [3]
Integration rights are a separate boundary. If a subagent has a Jira, GitHub or database MCP tool, its capabilities are determined by that tool and the connected credentials. "Let it only read" has to be enforced by an available read-only variant of the tool or by an authorisation policy, not just by the role description. When reviewing a configuration, keep in mind that an attached server may only be available while the agent runs, but data visibility or a completed write can remain in the external service after the session ends.
There is one more important gap: context is not the file system. When a subagent works in the same checkout, a file change becomes part of the state shared with the main session. Two parallel agents can overwrite a file or see a half-finished change. To ease concurrency, Claude Code offers isolation: worktree: a shell/PowerShell subagent is launched in a temporary Git worktree. The documentation says it branches from the default branch by default, not necessarily from the main session's current HEAD, and that the worktree is removed automatically if the agent left no changes. Check the base revision and how the result will be collected before you use it. Such a worktree isolates the Git working copy, but it does not turn the environment into a full sandbox and does not block the network or external systems. [1, 8]
A subagent's memory is a different kind of state. The memory field enables a memory folder with user, project or local scope. The first 200 lines or 25 KB of MEMORY.md (whichever comes first) may be loaded on the agent's later runs, and the subagent itself is able to read and edit the memory files. This state outlives the current delegation, and project memory can end up under version control. So treat it as mutable data with a provenance, which may be stale or unwanted, not as the system's truth. The documentation distinguishes auto memory from CLAUDE.md: the former accumulates learned patterns, the latter holds rules set by a person. Both end up in the context, but neither enforces anything by itself. [4]
Before giving a subagent access to files or tools, check:
- The data boundary: which parts of the code, repositories, attachments and memory can it read?
- The write boundary: which checkout, worktree or external service can it write to?
- The network: can it reach an arbitrary website, or only explicitly allowed services?
- Secrets: can a tool read environment variables, tokens, Secure Shell (SSH) keys, configuration files, or logs containing personal data?
- Side effects: can it create or close an issue, leave a comment, push a branch, run a migration or send a message?
- Persistence: what remains after the session closes: a Git diff, memory, a shell process, a message, or a record in a service?
In day-to-day practice it is often safer to delegate reading and analysis with an explicit ban on changes, and to make the needed diff separately within a defined scope. If the agent does need to make an edit, name its files and conditions; afterwards, compare the actual diff with the contract. Large system actions are better gated behind a separate approval or a control that lives outside the model.
Completion, consolidating evidence, and failures
When the work is finished, the main agent receives the subagent's report and, for launches that support it, an identifier (ID) that allows the work to be continued. Some built-in agents, such as Explore and Plan, may be one-shot and have no ID for continuation. If maxTurns is reached, Claude Code may mark the response as partial and allow continuation by sending the agent a message. Check the partial flag; do not turn "limit reached" into "done". [1]
A background launch is a way to let work continue while the main conversation does something else. According to the current documentation, a background subagent's permission prompts may appear in the main session, and the tool set available in the background differs from the foreground one. This behaviour depends on the fork mode, the session settings and how the agent was launched. "Sent to the background" only means the work may still be running, not that the result is ready. Check the task line or the actual completion message in the interface you have. [1]
If the call returned a timeout, a network or application programming interface (API) error, a spending limit, an interruption or an empty result, mark the status unknown or incomplete until there is evidence of completion. An empty response is not evidence that the agent changed nothing: an external operation may have completed and only the response was lost. Before retrying, check the file diff or the state of the external system to avoid a duplicate write. If the subagent has an ID and its context is still available, continuing it may be better than redoing the work; if a retry is unavoidable, use an idempotent method wherever the system supports one.
For each subagent, it is convenient to keep a summary table:
| Field | Question |
|---|---|
| Status | Did it finish, finish partially, fail, get interrupted, or is it still running? |
| Question | Which specific part of the original task did it check? |
| Evidence | Which files, lines, logs, links, test results or records did it actually read? |
| Conclusion | What does it claim, and to what scope does the claim apply? |
| Unknowns | What was missing, where did sources disagree, or what could not be checked? |
| Side effects | What was changed in the working copy or in an external system? |
| Acceptance | Did the main agent check the key finding and the original criterion? |
A closed call only means the tool stopped running. A completed task means the required scope was checked, the evidence is sufficient, the result matches the contract, and the side effects are known. The main agent is responsible for the second.
If two agents disagree, do not mechanically pick the more confident answer. Compare their sources and conditions: one may have read a stale branch, the other the wrong test file; one conclusion may apply only to a particular example. Re-read the source of truth. If the disagreement remains, put both versions in the summary, with their evidence and what still needs clarifying. The absence of a shared conclusion is a result to be preserved, not hidden.
Several subagents do not mean several independent pieces of evidence. They may have received the same task, used the same document, the same model, the same set of tools, or inherited the same earlier assumptions. If three workers retell one source, that is one source with three retellings. Independence grows when the questions are genuinely different, the sources are separate and the verification conditions are formulated separately. Even then, the conclusion has to be checked against the primary artefact.
A public bug report as a lesson in reliability
Issue #84927 in the anthropics/claude-code repository describes a reporter's experience: a newly created definition, .claude/agents/architect.md, did not immediately appear in the Agent tool in Claude Code 2.1.222 on macOS 26.5.2. A few minutes later the agent became available. GitHub closed the issue as "not planned" on 5 October after a period of inactivity, and the issue contains no confirmed fix. It describes a single reproduction, not a guarantee that the current version always behaves this way. The practical lesson for delegation: before using a narrow type, make sure that type is the one actually selected. The reporter describes trying a general-purpose agent with a charter in the prompt as a temporary substitute; however, the tools restriction from the unused definition does not carry over to the fallback type. A prompt that says "read-only" is not a substitute for an actual tool allowlist. [1, 5]
Worked example: a read-only search for API call sites
This case is entirely fictional. The paths, lines and commit come from a teaching repository; they do not describe a real service.
The coordinator's request. A hypothetical service is preparing to replace its invoice-voiding route. The coordinator asks to establish exactly where the code calls POST /v2/invoices/{invoice_id}/void, whether there are calls through the client wrapper, and what must be checked before a decision about the migration. The starting revision is the fictional commit 7f3a91c.
The subagent contract.
Goal: produce a read-only list of calls to POST /v2/invoices/{invoice_id}/void.
Check only revision 7f3a91c and the paths src/billing/, src/jobs/ and
src/admin/. Allowed: read files and search for text and symbols in these
directories. Forbidden: running the shell or tests, editing files,
checking other branches, sending requests to the service, or changing external
state. For each match, give the path, line, the method or wrapper called,
and a short evidence excerpt. Distinguish the exact route from similar ones.
Finish by naming the single safest next check and explaining why;
do not propose a code change until the coordinator confirms the inventory is complete.
Part of this restriction can be fixed in the subagent definition's frontmatter:
---
name: route-inventory
description: Find API route call sites and report file-level evidence.
tools: Read, Grep, Glob
---
According to the current Claude Code documentation, the tools field works as an allowlist: this agent has the named reading and search tools, but not Bash, Edit, Write, or any MCP tools that are not on the list. The list restricts the kinds of actions available, but it does not pin down the permitted paths src/billing/, src/jobs/ and src/admin/. In this example that boundary is set by the contract. If you need a technically enforced directory boundary, provide it through separate permission rules or environment isolation. Nor would the contract text itself be a technical prohibition if the agent had access to a more dangerous tool. [1]
Evidence from the fictional checkout. The agent returns three separate observations:
| Location | Observation | Why it matters |
|---|---|---|
src/billing/invoices.ts:44 |
billingClient.post(`/v2/invoices/${id}/void`, body): the exact route, through the shared client. |
This is a direct call, but it may not be the only entry point. |
src/jobs/retry-void.ts:71 |
voidInvoice(invoiceId, reason) calls the wrapper from src/billing/invoices.ts; the job retries it after a transient error. |
Retries and the client's behaviour must be taken into account during the migration. |
src/admin/refund.ts:29 |
billingClient.post(`/v2/invoices/${id}/refund`, body): a different route. |
A similar name does not make a refund the same as voiding an invoice. |
This inventory is limited to the named directories and revision. It does not prove that there are no other calls in test fixture files, generated code, other services or configuration. Nor does the report confirm the behaviour of the remote API, and it does not treat a single text match as proof of execution in production.
Deciding the next step. The coordinator confirms that all three references belong to commit 7f3a91c, opens the wrapper being called, and checks only its local semantics: whether retrying the request is safe and whether the client hides a different route. It assigns this as the next narrow read-only check, because retry-void.ts turned out to be an indirect path that is easy to miss when looking only at the direct call. No API or code change is proposed yet: first every point of use and the retry requirements must be established.
Outcome. The coordinator returns a short list: two call sites that lead to voiding, one similar but different route, the boundaries of the check, and the next safe step. This is a complete decision for the research stage, not permission to change the contract.
Worked example: three separate Jira requirements before a release
All keys and data in this example are fictional. They demonstrate a way of working; they do not refer to real tasks or course criteria.
Situation. A team is preparing an update to a learning platform. There are three Jira tasks, and before planning only a readiness check is needed:
DEMO-COURSE-41: every published lesson page must display its heading and text on a narrow screen.DEMO-COURSE-42: pressing "Send" twice must not create a duplicate message.DEMO-COURSE-43: an editor can recover a draft after reloading the page.
The illustrative acceptance criteria are given in full so that the subagent does not have to guess their content. In a real session the main agent would first read the three named issues through an available read-only Jira connector, check their keys and last update, and only then pass the agents the exact text and links to the files. If the connector failed to return a task or showed a contradiction, work on that task would not start.
Problem. One big "check Jira" request can merge independent requirements into a single conclusion. It is also easy to confuse "no test found" with "the system definitely does not support the behaviour", or to let an agent quietly change a status in Jira.
Alternatives. The main agent could read the code and all three criteria sequentially in one context. That makes sense if the modules are tightly coupled. Here the requirements concern different components and the first stage is purely investigative, so three independent read-only checks can be delegated. A separate agent team would be overkill: the coordinator only needs to assemble a simple matrix, and the members have no need to talk to each other. A permanent custom subagent is not necessary for a one-off task either; a clear prompt and the right type are enough.
The contract for each of the three subagents.
Goal: check one Jira requirement for release planning.
Source of the requirement: the full acceptance-criteria text below and
the link to DEMO-COURSE-41 / DEMO-COURSE-42 / DEMO-COURSE-43.
Check only the named requirement in the current commit <identifier>.
Allowed: read the specified module and its tests; run an explicitly named
local read-only test if it is already available.
Forbidden: editing files, creating a commit, changing Jira,
commenting, or moving on to another agent's task.
Return: (a) fulfilment: confirmed / refuted / unknown;
(b) exact paths, lines and test evidence; (c) cases not checked;
(d) reasons for uncertainty. Do not claim a test you did not run.
If you find an interdependency or a contradiction, flag it; do not resolve it
outside the scope of your task.
One agent analyses DEMO-COURSE-41 in the page template and the responsive-layout tests; the second analyses DEMO-COURSE-42 in the send handler and the repeated-request tests; the third analyses DEMO-COURSE-43 in draft saving and state restoration. Each gets the same rule about Jira state, but its own requirement and file scope. The tool settings leave only reading, search and the named safe check. Write access to Jira is not needed for a research report.
Comparison. The illustrative results might look like this:
| Jira | Subagent result | Basis | What remains unknown |
|---|---|---|---|
DEMO-COURSE-41 |
Partially confirmed | The template renders the heading; the text test passes at a 360 px viewport. | The test does not check that images or long code blocks will not cause horizontal scrolling. |
DEMO-COURSE-42 |
Gap found | The handler checks a request identifier; the test covers a sequential retry but not two concurrent requests. | The uniqueness guarantee in the production database was not investigated. |
DEMO-COURSE-43 |
Unknown | The component was found to write the draft to local storage. | The agent could not read the storage migration, and the test environment has no page-reload scenario. |
Consolidation by the main agent. The coordinator must not turn three rows into "everything is ready". It checks whether each report refers to the same commit and to actual files; whether it is the exact Jira task; whether guesswork has been substituted for evidence; and whether one agent is hiding a critical gap. The state of the first requirement does not close the gaps in the second, and being denied access to the third's test proves neither the presence nor the absence of the feature.
Outcome. The main agent produces a read-only matrix with three different statuses: one requirement partially confirmed, the second with an unchecked concurrency case, the third still unknown for lack of evidence. It does not change Jira and does not declare the release ready. The owner can decide separately what still needs to be built or checked.
Why this approach fits. The criteria are independent enough to be read in parallel, and each check is small with its own sources. The tool restrictions match the risk: the task calls for analysis, not writing. The result format makes it easy for the main agent to collect the findings without absorbing all the intermediate output into the main conversation.
Limits. The example does not show a real product, real Jira keys, an executed test or a real integration. Even splitting the work across three workers does not guarantee independent conclusions if they all read the same stale code or the same incorrect requirement text. Before a decision is made, the currency of the Jira tasks, the commit and the test output must be confirmed.
Worked example: the cause of an error is not yet proven
Situation. After a deployment of a hypothetical service, some requests fail with a "session expired" error. The team has logs for the hour of the incident, a dependency map and several plausible theories: a faulty cache, a sharp clock skew, or a change in token validation. All the examples below are fictional.
Problem. Given a broad request such as "find the cause and fix it", a single model may lock onto the first hypothesis, push a change to a shared branch and declare the incident closed before it has been verified. What this phase needs is a comparison of explanations, not writes to production.
Alternatives. The repair should not be delegated to several authors at once: before changing code, the facts have to be established. In the main conversation each theory could be checked in turn if there is not much data. If the logs and code paths are large, three narrow read-only subtasks make sense: each checks one hypothesis and reports specific timestamps, lines and alternatives.
Action. The main agent phrases the request the same way for the three different questions: "Check hypothesis X against the timeline <time and service>. Read only the named logs and files. Do not change the checkout, do not run network commands, and do not touch the deployment environment. List the events that support and that weaken the hypothesis; give the timestamp, the source and an exact quotation or coordinates. Do not draw conclusions beyond the data you checked." The reading tools restrict access; Bash, writing tools and the incident environment's MCP are not provided.
The cache investigator finds that latency rose during the same interval, but does not see a cache miss preceding the authorisation error. The clock investigator finds a discrepancy of about one minute between two nodes, but the log timestamps from different systems are stored in different time zones. The token investigator finds a validation change in the current commit, but the test log does not say which configuration variant the affected client was using.
Consolidation. The coordinator builds the timeline only after normalising the time zones, keeps links to the primary sources, distinguishes observations from hypotheses, and notes what supports or weakens each version. In this illustration it concludes that the token-validation change has a strong correlational signal but the client configuration is missing; that is not yet proof of cause. The three subagents do not "vote" on a culprit, because they investigated different hypotheses rather than independently checking the same experiment.
Outcome. The report contains the best next safe observation: obtain a masked copy of the client's configuration and check the exact path of its request in a reproducible environment. Production, code, secrets and access were not changed. The task "explain the incident" remains partly open, even though all three subagent calls finished.
Why this approach fits. Large logs and different modules would have put too much noise into the main context; the questions could be framed in isolation; and the risk of mass writes was high. Parallel readers helped compare independent sources quickly while keeping each conclusion's limits intact.
Limits. Parallelism does not replace time normalisation or complete logging. Access to hidden or deleted logs does not appear just because work was delegated. A commit that was found does not prove causation. If the next check involves changes or interaction with production, that is a new contract, with different access and separate approval rules.
Worked example: a reviewer finds data loss in a migration
This case is entirely fictional. It shows how to separate implementation from independent review; it does not describe a real database.
Context and invariant. A team is moving accounts.external_ref into an account_identifiers table. Under the requirements, every account's reference must be kept for 90 days after a soft delete, because the account can be restored during that period. The migration's invariant: for every such account, the same external reference remains after the move. The proposed Structured Query Language (SQL) backfill query selects only rows with deleted_at IS NULL, after which the old column is dropped.
Division of roles. The implementer is allowed to change only the migration file and its tests, on their own branch. The reviewer works read-only from the same base revision and is given the invariant, the migration SQL and the test data. The reviewer does not change code and does not connect to production. Both report with exact evidence, not just a conclusion.
The disagreement. The reviewer reports data loss. The implementer objects: "rows with a deletion date are no longer active, so they don't need to be moved". The coordinator does not choose between confident answers; it checks the restoration requirement and the behaviour of the restore endpoint, which reads the external identifier.
Counterexample and evidence. The fictional test snapshot contains a row acct-17, with external_ref = partner-004 and deleted_at = 2026-09-10. On the migration date it is still within the 90 days. Before the backfill the row exists; after running the query on an isolated copy, there is no row for acct-17 in account_identifiers. The restore test for this record then returns an empty external reference. This concretely violates the invariant; the word "deleted" does not cancel a documented restoration period.
Decision and human checkpoint. The implementer accepts the counterexample and changes the backfill to move all rows within the restoration period, adding tests for an active record and a soft-deleted one. The reviewer reruns the check on the same snapshot, confirms both values were moved, and marks the finding as resolved. The coordinator prepares the corrected migration as a pull request (PR) but does not run it in production. Before it is applied, a responsible person (the data owner or a database administrator) must separately confirm the retention rule, the backup, the rollback plan and the run window. In this teaching case the data owner confirms the 90-day invariant; the production run stays blocked until the backup and rollback have been checked.
Outcome. The reviewer's objection was resolved by a tested counterexample and the requirement, not by a vote among agents. The code can go through human PR review; the decision to apply the migration stays with the responsible person.
Worked example: two changes to the same file conflict
This case is entirely fictional. Two subagents have separate context windows and separate worktrees created from the same commit C0, but both were given permission to edit knowledge/units/claude-subagents/en.md.
What happened. The first agent rewrites the paragraph about shared file state to add a warning about partially written changes. The second, unable to see the first agent or its worktree, rewrites the same paragraph for the example about worktree boundaries. Each sees only C0 and assumes its own fragment is the only current version. When the coordinator applies both changes to the integration branch, Git marks the same span of lines as conflicting; the separate contexts did not synchronise the files. Had one agent instead saved an entire stale snapshot over a shared checkout, its write could have erased the other's edit.
Evidence and stopping. The coordinator does not accept "last write wins". It stops the merge, keeps both patches, checks that both descend from C0, and compares the conflicting fragment with the original assignments. That shows which claims each agent meant to add and whether any other content was lost.
Replanning, checkpoint and outcome. From now on one author owns the whole file; the other becomes a read-only reviewer and returns suggestions with exact locations, without writing in parallel. The author, in a dedicated worktree, integrates both needed points, checks the diff from C0 after changing the paragraph, and saves a separate checkpoint before the next edit. The reviewer checks the final diff against both assignments; the coordinator verifies that both claims survived and that there are no conflict markers and no accidentally lost text. In this example the diff has been checked and the integration is ready for human review; only a responsible person decides whether to merge it into the main branch. For the next round of parallel work, the file's owner is assigned in advance, and other agents are given read-only checks or files that do not overlap.
Costs, timeouts and the risk of an incomplete result
A subagent has its own work and context, but it consumes the shared resources of the session and the model. Parallel launches can shorten calendar time only when they do not depend on each other. They increase the total volume of reading, tool calls, returned reports and tokens. The more agents return detailed text, the more the main agent has to read and verify. A short report format and clear boundaries are a way to control costs, not an economic bonus that the architecture guarantees automatically.
As a concrete example, the anthropics/claude-code repository has GitHub issue #78231 from 16 July 2026. The reporter described a Cowork environment on Windows with four concurrent subagents which, according to the report, were terminated when a spending limit was reached and returned short, fragmentary lines instead of their results. The issue page lists the version as Claude 1.21459.0, and the issue is marked closed as "not planned". This is a user report, not a confirmed general defect or proof that all current versions lose results this way. It illustrates a practical risk: if an external limit cuts parallel work short, do not automatically count progress you cannot see. Check the actual state and repeat only what is needed. [6]
When planning, take into account:
- Context set-up time. A new subagent has to re-read the named sources; for a quick answer the main context may be faster.
- Coordinator overhead. The results have to be collected, compared, checked and written up.
- Turn and depth limits.
maxTurnscan stop a particular agent before it finishes; the depth of nested subagents is also limited by configuration. - Concurrency limit. The Claude Code documentation gives a default limit of 20 parallel subagents for the current product; once it is reached, an error may be returned. This is a launch ceiling, not a recommendation to always run twenty. [1]
- Network or API errors. An agent may receive partial text or an error, or stop with a failed status; do not extract a claim of success from a failure message. [1]
- Token budget and context. A short task and a compact report reduce the risk that important evidence drowns in unnecessary intermediate results.
- Cancellation. A request to stop execution does not undo a change that has already been written or an action in an external service; check the state before retrying.
The documentation describes nesting up to three levels below the main conversation with default settings, and the CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH variable changes that limit. Once the depth is exhausted, the Agent tool may be unavailable or return an error for a fork. Do not count on an unlimited delegation tree: every level adds a context hand-off and makes it harder to tell who actually verified the result. [1]
A brief comparison with Codex
Codex has its own implementation of multi-agent work, but you should not carry Claude Code's .claude/agents/ configuration, frontmatter field names or Agent behaviour over to it. In OpenAI's current documentation for the Agents API, a coordinator creates subagents for independent tasks; they have their own context, can work in parallel, and the coordinator combines the results. In this particular API configuration, agent.multi_agent.enabled turns orchestration on and max_concurrent_subagents sets the limit, documented as six by default, not counting the coordinator. When the agents need files or command execution, the coordinator and the subagents share the same environment filesystem; creating a subagent does not by itself create a new environment. Available tools and credentials can also be inherited, so the same check of shared data and powers is needed there too. This comparison applies specifically to the Agents API documentation and does not describe every Codex interface or configuration. The mechanisms are compared in detail in the unit on Codex subagents and orchestration. [7]
A heuristic for the main agent
Before delegating, ask:
- Does the work have a distinct result that can be described and verified?
- What exact context must be passed on, and how will the agent find its source?
- Which data, files and services does it actually need?
- Is it safe to delegate reading only, or is a shell command or a write required?
- Could two agents conflict over a shared file, branch or external state?
- Which artefacts will demonstrate success, a partial result, a timeout or a failure?
- How will the main agent reconcile conflicting results and check the primary sources?
- Do the savings in context and time justify the cost of start-up and consolidation?
- What is the point beyond which the main agent must not automatically continue or change the system?
If there is no clear answer to these questions, keep the work in the main conversation or first sharpen its contract. If a subagent is needed, delegate the smallest self-contained fragment of work. The strongest useful guarantee does not come from the number of parallel agents. It comes from each agent receiving the context it needs and no more access than it needs, and from the main agent accepting only a verified result.
Sources and further reading
The fast-changing Claude Code pages and the status of the public examples were checked on 10 October 2026. That is the access date of the current online content, not a publication date and not a guarantee that the behaviour will stay the same.
- Anthropic, Create custom subagents — Claude Code Docs, current online documentation, accessed 2026-10-10. Used for subagent types, configuration and frontmatter, the context boundary, tools, models, memory, hooks, worktrees, invocation, background mode, errors, limits and continuation.
- Anthropic, Orchestrate teams of Claude Code sessions, current online documentation, accessed 2026-10-10. Used only for the difference between subagents, agent teams and separate sessions, messaging, the shared task list and overhead.
- Anthropic, Configure permissions — Claude Code Docs, current online documentation, accessed 2026-10-10. Used for tool and command permissions, the fragility of Bash patterns, file access, and the difference between a textual policy and a technical restriction.
- Anthropic, How Claude remembers your project — Claude Code Docs, current online documentation, accessed 2026-10-10. Used for the difference between
CLAUDE.mdand auto memory, the load limits, and the point that textual memory is not an enforced policy. anthropics/claude-code, Issue #84927: New subagent definition temporarily unavailable, opened 2026-08-07, Claude Code 2.1.222, macOS 26.5.2. GitHub closed the issue as "not planned" on 5 October 2026 due to inactivity. The described delay in the definition becoming available, and the dangerous widening of access when falling back to a general-purpose type, remain an individual report rather than a claim about all configurations; the closure itself does not confirm that the behaviour was fixed.anthropics/claude-code, Issue #78231: Subagent output discarded when spend limit terminates fanout, opened 2026-07-16; the environment is described as Cowork on Windows; the issue page lists Claude 1.21459.0 and the status "closed as not planned". An individual report, used only as an example of the risk of costs and incomplete results, not as confirmation of the state of current installations.- OpenAI, Multi-agent — Agents API, current API documentation, accessed 2026-10-10. Used for the brief comparison: the coordinator, separate contexts, parallel work, the maximum number of subagents and the shared execution environment.
- Anthropic, Configure the sandboxed Bash tool — Claude Code Docs, current online documentation, accessed 2026-10-10. Used to distinguish a Git worktree from a sandbox, and for the file-system and network boundaries of shell command execution.
- Anthropic, Claude Code releases, checked 2026-10-10; the latest release shown on the page that day was v2.1.296 from 2026-10-09. Used to anchor the fast-changing details and version boundaries in time.