This implementation analysis is limited to the public mirror snapshot dated March 31, 2026. The mirror is not an official Anthropic source repository and does not establish behavior in later product releases. Source links are pinned to that commit; official documentation supplies product concepts, while feature gates and missing modules are identified separately.
The AgentTool path starts when the model asks to delegate work. From the parent loop's point of view, this is still a tool call. If it is accepted, Claude Code selects an agent, decides which tools that agent may use, creates separate state, and runs a child query loop.
Reading goal: distinguish a normal subagent from the fork path. The normal path rebuilds a focused prompt and tool list; the fork path keeps the parent's system prompt, tools, thinking settings, and message prefix as stable as possible.
AgentTool input
-> select agent definition
-> assembleToolPool() / resolveAgentTools()
-> createSubagentContext(parentContext, workerTools)
-> runAgent() // its own query loop
-> sidechain transcript + parent-visible result
fork path
-> reuse parent system/tools/messages prefix
-> append fork-only suffix
1. AgentTool chooses a concrete execution path
The input schema contains a task description and prompt, plus optional fields such as subagent_type, model, and background execution. When the related features are enabled, it may also accept a teammate name, team name, permission mode, isolation choice, and working directory. These fields decide how and where work runs; they do not create a free-form chat.
A resolved team name, from parameters or context, plus name selects teammate spawning. Otherwise an explicit subagent_type wins; omitting it selects general-purpose when the fork gate is off, and the fork path when the gate is on. The ordinary type branch applies allowedAgentTypes and Agent(name) deny rules. Required MCP servers still pending are polled every 500 ms for up to 30 seconds, with early exit on a required-server failure. The final check looks for matching server names in advertised tool names. It does not execute those tools or prove that every action works.
2. A normal subagent gets a rebuilt tool list
The normal path does not copy the parent's tool array verbatim. It starts from the current permission state and MCP tools, selects the agent's permission mode, and calls assembleToolPool(). resolveAgentTools() then removes tools forbidden to all agents, custom agents, or background agents, and applies the definition's tools and disallowedTools lists.
MCP tools skip the generic agent-category and async filters, but the definition's tools and disallowedTools lists and execution permissions still apply. Ordinary subagents lose the Agent tool; the main thread skips subagent filtering, while enabled in-process teammates have a separate exception for synchronous child tasks. The normal child also receives a system prompt generated from its selected agent definition, environment details, and enabled tools rather than a copy of the parent's rendered prompt.
3. The fork path preserves the parent request prefix
The fork path makes a different tradeoff. It inherits the parent's rendered system prompt and uses buildForkedMessages() to clone the relevant assistant message, placeholder tool results, and a directive for the child. It also enables useExactTools and passes the parent's exact tool list.
This exactness matters because tool definitions and thinking configuration contribute to the prompt-cache key. Rebuilding tools with a different permission mode could invalidate the cache at the first changed schema. Fork children therefore inherit the parent's thinking configuration as well; this snapshot disables thinking by default for ordinary subagents to control output cost. The Agent tool remains in the exact schema list, but a runtime check rejects another fork when the current request is already a fork child, preventing recursive branching.
The fork feature gate requires the FORK_SUBAGENT build feature and excludes coordinator mode and non-interactive sessions. When enabled, it also requests background execution for ordinary named agents, subject to background tasks being enabled. This route differs from a Skill's context: fork and the CLI's --fork-session.
parent history
+ assistant(all tool_use blocks)
+ user(tool_result placeholders for every tool_use, child directive)4. createSubagentContext separates selected state
createSubagentContext() clones file-read state and content-replacement decisions, creates fresh memory and dynamic-Skill trigger sets, and assigns a new agent id and tracking depth. The read cache remains writable by the child. By default, setAppState is a no-op and UI callbacks such as setToolJSX and addNotification are absent. Task registration still reaches the root store through setAppStateForTasks, and attribution updates remain shared. This is selected context isolation, not a process or filesystem sandbox.

In the actual runAgent() call, synchronous agents share setAppState, and both synchronous and background agents contribute to response metrics. The helper's default child abort controller propagates parent cancellation; background execution explicitly supplies an unlinked controller to survive the parent's ESC. Unless the caller overrides getAppState or opts into sharing the interactive controller, the helper sets shouldAvoidPermissionPrompts: true. Background permission behavior must therefore be read with the caller's overrides, not inferred from the helper default alone.
Worktree isolation is a separate option. When requested, AgentTool creates a worktree and runs with an overridden working directory. A normal agent rebuilds its system prompt inside that directory; a fork appends a notice to translate paths and reread potentially stale files while retaining the parent prefix. Completion cleanup checks whether the worktree has changes before removing it.
5. runAgent operates a complete child query loop
runAgent() is an asynchronous generator, not a single provider request. It creates child state, runs SubagentStart hooks, registers declared frontmatter hooks for the agent lifecycle, maps Stop to SubagentStop, preloads declared Skills as meta user messages, connects agent-specific MCP servers, and then enters query(). Child messages are written to a sidechain transcript as the loop continues.
A synchronous agent yields progress records to the parent and eventually returns a tool result. A background agent registers a task and reports completion through a notification or task result. Both paths have their own agent id, transcript, and cleanup behavior; neither is hidden code still running inside the parent turn.
For example, after a parent submits “investigate the failing tests,” status: async_launched acknowledges a started task, not passing tests. A later notification or TaskOutput supplies its completed, failed, or stopped state. Placeholder tool results in a fork prefix only complete the message pairing; they do not prove that other tool calls succeeded.
6. Compare normal, background, and forked work
| Path | System prompt | Tools | Result behavior |
|---|---|---|---|
| Normal synchronous subagent | Generated from the selected agent definition. | Rebuilt and filtered for the worker. | Progress and the final result return to the waiting parent. |
| Normal background subagent | Generated from the selected agent definition. | Further restricted for background execution. | A task continues independently and notifies the parent when complete. |
| Fork child | Inherits the parent's rendered prompt. | Uses the exact parent tool definitions. | Runs a child-specific suffix while reusing the parent's cached prefix. |
| Worktree isolation | Rebuilt for the directory, or a fork notice is appended. | Agent tool rules still apply. | File changes happen in a separate worktree; cleanup depends on remaining changes. |
A useful mental model is a child runtime with explicit inputs and outputs. Claude Code selects an agent, calculates its tools, chooses isolated or forked state, runs a separate query loop, records a transcript, and returns progress or a result to the parent.
Sources
The source-code claims in this article are based on the public mirror and the linked official documentation. Server-side scheduling is not inferred from client-side code.