Skip to main content
Agents can delegate work to other agents. When you pass a subagents array, a task tool is automatically generated that lets the parent agent spawn child agents by name.

Basic Setup

const explore = new Agent({
  name: "explore",
  description: "Read-only codebase exploration. Use for searching and reading files.",
  model: openai("gpt-5.4"),
  tools: { readFile, listFiles, grep },
  maxSteps: 30,
});

const agent = new Agent({
  name: "dev",
  model: openai("gpt-5.4"),
  tools: { ...fsTools, bash },
  subagents: [explore],
});
The parent model sees a task tool with a description listing the available subagents and their descriptions. It can call task with an agent name and a prompt, and the subagent runs to completion autonomously.

Key Behaviors

  • Fresh instance per task — each task call creates a new agent with no shared conversation state
  • No approval — subagents run autonomously without prompting for permission
  • Configurable nesting — by default subagents cannot themselves have subagents (maxSubagentDepth: 1). Set a higher depth to enable nested delegation.
  • Abort propagation — the parent’s abort signal is forwarded to the child
  • Concurrent execution — the model can call task multiple times in one response to run subagents in parallel

Nested Subagents

By default, subagents cannot delegate further. Set maxSubagentDepth to allow nesting:
const search = new Agent({
  name: "search",
  description: "Focused file search",
  model: openai("gpt-5.4"),
  tools: { grep, listFiles },
});

const explore = new Agent({
  name: "explore",
  description: "Read-only codebase exploration",
  model: openai("gpt-5.4"),
  tools: { readFile, listFiles, grep },
  subagents: [search], // explore can delegate to search
});

const agent = new Agent({
  name: "dev",
  model: openai("gpt-5.4"),
  tools: { ...fsTools, bash },
  subagents: [explore],
  maxSubagentDepth: 2, // allow explore -> search nesting
});
The depth decrements at each level: the root agent has depth 2, its child explore gets depth 1 (can use search), and search gets depth 0 (no further delegation).

Live Subagent Events

To observe what subagents are doing in real time, pass an onSubagentEvent callback:
const agent = new Agent({
  name: "dev",
  model: openai("gpt-5.4"),
  tools: { ...fsTools, bash },
  subagents: [explore],
  onSubagentEvent: (path, event) => {
    // path is the ancestry chain, e.g. ["explore"] or ["explore", "search"]
    if (event.type === "tool.done") {
      console.log(`[${path.join(" > ")}] ${event.toolName} completed`);
    }
  },
});
The path parameter is a string[] representing the full ancestry from outermost to innermost agent. Events from nested subagents automatically bubble up through the chain. The callback receives the same AgentEvent types as the parent’s run() generator.

Background Subagents

By default, all subagent calls are synchronous — the parent blocks until the child finishes. Enable subagentBackground to let the parent spawn agents in the background, do other work, and collect results later. This works like JavaScript’s Promise combinators.
const agent = new Agent({
  name: "dev",
  model: openai("gpt-5.4"),
  tools: { ...fsTools, bash },
  subagents: [explore, researcher, coder],
  subagentBackground: true, // enable with defaults
});
When enabled, three things happen:
  1. The task tool gains an optional background parameter. When true, the agent is spawned in the background and the tool returns immediately with an agent ID.
  2. An agent_await tool is registered for waiting on background agents using different strategies.
  3. agent_status and agent_cancel tools are registered for checking on and cancelling background agents.
The model orchestrates everything naturally through tool calls:
// Model spawns two background agents and one foreground agent in one step:
task({ agent: "researcher", prompt: "Find deprecated APIs", background: true })  -> "bg-1"
task({ agent: "researcher", prompt: "Check test coverage", background: true })   -> "bg-2"
task({ agent: "coder", prompt: "Refactor config parser", background: false })    -> (blocks)

// Next step — model has the coder result, now collects background results:
agent_await({ ids: ["bg-1", "bg-2"], mode: "all" })  -> both results

Await Modes

The agent_await tool supports four modes, matching JavaScript’s Promise combinators:
ModeBehavior
allWait for all agents to succeed. Fails fast if any agent fails.
allSettledWait for all agents to finish. Returns results and errors.
anyWait for the first agent to succeed. Only fails if all agents fail.
raceWait for the first agent to settle (succeed or fail).

Configuration

Pass true for sensible defaults, or an object for fine-grained control:
const agent = new Agent({
  name: "dev",
  model: openai("gpt-5.4"),
  tools: { ...fsTools, bash },
  subagents: [explore, researcher],
  subagentBackground: {
    maxConcurrent: 3,           // max simultaneous background agents (default: Infinity)
    timeout: 120_000,           // auto-cancel after 2 minutes (default: none)
    autoCancel: true,           // cancel background agents on agent.close() (default: true)
    tools: {
      status: true,             // register agent_status tool (default: true)
      cancel: true,             // register agent_cancel tool (default: true)
      await: ["all", "race"],   // which await modes to expose (default: all four)
    },
  },
});
OptionDefaultDescription
maxConcurrentInfinityMaximum number of background agents running simultaneously
timeoutAuto-cancel background agents after this many milliseconds
autoCanceltrueCancel all running background agents when agent.close() is called
tools.statustrueRegister the agent_status tool
tools.canceltrueRegister the agent_cancel tool
tools.awaitall four modesWhich await modes to expose (true = all, false = disable, or an array)

Lifecycle Tools

When subagentBackground is enabled, these tools are auto-registered alongside the task tool:
ToolDescription
agent_statusNon-blocking status check. Returns the agent’s current status (running, done, failed, cancelled) and result if available.
agent_cancelCancel a running background agent via its ID.
agent_awaitBlock until background agents complete, using one of the four await modes.

Cleanup

Background agents respect the parent’s abort signal — if the parent is aborted, all background children are cancelled. When autoCancel is true (the default), calling agent.close() cancels any still-running background agents.