Why this matters
AgentTool is where one tool call stops being “do one local action” and starts
becoming “launch a second worker with its own lifecycle.”
Big picture first
Read AgentTool in three passes:
- the input/output schema in
AgentTool.tsx - the long instructional prompt in
AgentTool/prompt.ts - the actual execution path that eventually calls
runAgent(...)
## When to fork
Fork yourself (omit `subagent_type`) when the intermediate tool output isn't worth keeping in your context. Start with the schema
const baseInputSchema = lazySchema(() => z.object({
description: z.string().describe('A short (3-5 word) description of the task'),
prompt: z.string().describe('The task for the agent to perform'),
subagent_type: z.string().optional().describe('The type of specialized agent to use for this task'),
model: z.enum(['sonnet', 'opus', 'haiku']).optional().describe("Optional model override for this agent."),
run_in_background: z.boolean().optional().describe('Set to true to run this agent in the background. You will be notified when it completes.')
}));
const fullInputSchema = lazySchema(() => {
const multiAgentInputSchema = z.object({
name: z.string().optional().describe('Name for the spawned agent. Makes it addressable via SendMessage({to: name}) while running.'),
team_name: z.string().optional().describe('Team name for spawning. Uses current team context if omitted.'),
mode: permissionModeSchema().optional().describe('Permission mode for spawned teammate (e.g., "plan" to require plan approval).')
});
return baseInputSchema().merge(multiAgentInputSchema).extend({
isolation: z.enum(['worktree']).optional().describe('Isolation mode. "worktree" creates a temporary git worktree so the agent works on an isolated copy of the repo.'),
cwd: z.string().optional().describe('Absolute path to run the agent in. Overrides the working directory for all filesystem and shell operations within this agent. Mutually exclusive with isolation: "worktree".')
});
});
This tells you the real surface area. AgentTool is not only “prompt plus
subagent type.” It also covers names, teams, permission mode, backgrounding,
and worktree isolation.
The prompt is part of the tool design
AgentTool/prompt.ts is long because the tool is teaching the model how to
delegate well, not just how to fill out JSON. The most important idea for a
first read is that the prompt distinguishes fresh specialized agents from
forked self-agents and warns the model not to fabricate unfinished results.
Where execution actually starts
export const AgentTool = buildTool({
async prompt({
agents,
tools,
getToolPermissionContext,
allowedAgentTypes
}) {
const toolPermissionContext = await getToolPermissionContext();
return await getPrompt(filteredAgents, isCoordinator, allowedAgentTypes);
},
name: AGENT_TOOL_NAME,
searchHint: 'delegate work to a subagent',
async call({
prompt,
subagent_type,
description,
model: modelParam,
run_in_background,
name,
team_name,
mode: spawnMode,
isolation,
cwd
}: AgentToolInput, toolUseContext, canUseTool, assistantMessage, onProgress?) {
The call(...) path is where delegation becomes real lifecycle management.
AgentTool.tsx does not just emit a prompt. It decides how the agent runs,
whether it should be backgrounded, and whether to use worktree isolation,
then hands execution off to helpers like runAgent(...), async-task
registration, and worktree management.
Takeaways
- AgentTool is a delegation runtime, not just a wrapper around prompts.
- Its prompt file teaches the model how to delegate safely and when to fork.
- The schema already reveals key lifecycle ideas like backgrounding, isolation, and teammate routing.