# How to Spawn Subagents Using the spawn_agents Tool in Codebuff

> Learn to spawn subagents in Codebuff using the spawn_agents tool. Effortlessly launch child agents in parallel with built-in permission checks, schema validation, and cost tracking.

- Repository: [Codebuff/codebuff](https://github.com/CodebuffAI/codebuff)
- Tags: how-to-guide
- Published: 2026-03-08

---

**The `spawn_agents` tool enables parent agents to launch multiple child agents in parallel with automatic permission checks, schema validation, and cost tracking.**

Codebuff is an open-source AI agent framework that treats every agent as a lightweight runtime capable of delegating tasks to specialized subagents. The `spawn_agents` tool, defined in [`common/src/tools/params/tool/spawn-agents.ts`](https://github.com/CodebuffAI/codebuff/blob/main/common/src/tools/params/tool/spawn-agents.ts) and implemented in [`packages/agent-runtime/src/tools/handlers/tool/spawn-agents.ts`](https://github.com/CodebuffAI/codebuff/blob/main/packages/agent-runtime/src/tools/handlers/tool/spawn-agents.ts), provides a safe, version-aware mechanism for parallel agent execution with proper state management and ancestry tracking.

## Understanding the spawn_agents Architecture

### Tool Schema and Parameters

The tool’s input contract is defined by `spawnAgentsParams` in the common package. This schema specifies the JSON structure that the LLM must provide when invoking the tool.

```typescript
// common/src/tools/params/tool/spawn-agents.ts
export const spawnAgentsParams = {
  toolName,
  endsAgentStep,
  description,
  inputSchema,          // ← agents: [{agent_type, prompt?, params?}]
  outputSchema,
} satisfies $ToolParams

```

The `inputSchema` expects an `agents` array where each element contains `agent_type` (required), an optional `prompt`, and optional `params` that must conform to the child agent’s input schema.

### Handler Entry Point

The `handleSpawnAgents` function in the agent-runtime package serves as the orchestration layer. It receives the parsed tool call, extracts the parent runtime context, and loops over each requested child agent.

```typescript
// packages/agent-runtime/src/tools/handlers/tool/spawn-agents.ts
export const handleSpawnAgents = async (params) => {
  const { agents } = toolCall.input;
  const results = await Promise.allSettled(
    agents.map(async ({ agent_type, prompt, params: spawnParams }) => {
      // 1️⃣ Validate & fetch child template
      const { agentTemplate, agentType } = await validateAndGetAgentTemplate({
        ...params,
        agentTypeStr: agent_type,
        parentAgentTemplate,
      });

      // 2️⃣ Validate prompt/params against child schema
      validateAgentInput(agentTemplate, agentType, prompt, spawnParams);

      // 3️⃣ Build a fresh AgentState for the sub‑agent
      const subAgentState = createAgentState(agentType, agentTemplate,
                                            parentAgentState, {});

      // 4️⃣ Execute the sub‑agent and forward chunks
      const result = await executeSubagent({
        ...extractSubagentContextParams(params),
        ancestorRunIds: parentAgentState.ancestorRunIds,
        userInputId: `${userInputId}-${agentType}${subAgentState.agentId}`,
        prompt: prompt || '',
        spawnParams,
        agentTemplate,
        parentAgentState,
        agentState: subAgentState,
        onResponseChunk,
      });

      return { …result, agentType, agentName: agentTemplate.displayName };
    })
  );
  // …aggregate costs & build JSON tool result
};

```

## Permission and Validation Flow

### Agent Template Validation

Before spawning, the system verifies that the parent agent is authorized to create the requested child type. The `validateAndGetAgentTemplate` function checks the parent’s `spawnableAgents` list.

Base agents such as `base`, `base-free`, and `base-parallel` can spawn any agent type. Non-base agents must explicitly declare allowed children in their template configuration. If the child type is not permitted, the runtime throws an error:

```

Agent type parent-id is not allowed to spawn child agent type codebuff/thinker@2.0.0.

```

### Input Schema Validation

Once permissions are confirmed, `validateAgentInput` runs the child agent’s Zod `inputSchema` against the provided `prompt` and `params`. This ensures that subagents receive only valid inputs before execution begins.

## Creating and Executing Subagents

### Agent State Creation

The `createAgentState` function initializes a fresh `AgentState` for each subagent. This state includes:

- A unique `agentId`
- Ancestry tracking via `ancestorRunIds`
- Filtered message history (removing unfinished tool calls)
- Optional system messages indicating the subagent was spawned

### Subagent Execution Loop

The `executeSubagent` function manages the runtime lifecycle:

1. Emits a `subagent_start` chunk to the UI
2. Invokes `loopAgentSteps` to run the child agent’s logic
3. Streams response chunks back to the parent in real-time
4. Emits `subagent_finish` when complete
5. Returns the final result and `creditsUsed` for cost aggregation

After all subagents complete, `handleSpawnAgents` sums the `creditsUsed` from each child into the parent’s credit counter and returns a JSON-encoded report to the calling LLM.

## Practical Examples of spawn_agents Usage

### Spawning Multiple Agents in Parallel

To delegate tasks to multiple specialized agents simultaneously, provide an array of agent configurations:

```json
{
  "tool_name": "spawn_agents",
  "tool_call_id": "spawn‑001",
  "input": {
    "agents": [
      {
        "agent_type": "commander",
        "prompt": "Run the project’s test suite",
        "params": { "command": "npm test" }
      },
      {
        "agent_type": "code-searcher",
        "params": {
          "searchQueries": [{ "pattern": "authenticate", "flags": "-g *.ts" }]
        }
      }
    ]
  }
}

```

The handler validates that the parent’s `spawnableAgents` list contains both `commander` and `code-searcher`, creates two `AgentState` instances, runs them concurrently via `Promise.allSettled`, and returns a JSON array:

```json
[
  { "agentName": "Commander", "agentType": "commander", "value": { "type": "lastMessage", "value": [...] } },
  { "agentName": "Code‑Searcher", "agentType": "code-searcher", "value": { "type": "lastMessage", "value": [...] } }
]

```

### Using Versioned Agent Types

Parent agents may restrict children to specific versions using publisher-scoped IDs like `codebuff/thinker@1.0.0`. When the LLM sends `"thinker"`, the runtime resolves it via `getMatchingSpawn` in [`spawn-agent-utils.ts`](https://github.com/CodebuffAI/codebuff/blob/main/spawn-agent-utils.ts) and automatically matches the allowed version.

```json
{
  "tool_name": "spawn_agents",
  "input": {
    "agents": [
      { "agent_type": "thinker", "prompt": "Explain the algorithm" }
    ]
  }
}

```

If the parent’s `spawnableAgents` contains `"codebuff/thinker@1.0.0"`, the call succeeds. A version mismatch (e.g., requesting `@2.0.0` when only `@1.0.0` is allowed) yields an error:

```

Agent type parent-id is not allowed to spawn child agent type codebuff/thinker@2.0.0.

```

### Inline Spawning with spawn_agent_inline

For scenarios requiring direct output rather than a JSON array, use `spawn_agent_inline`. This variant executes the same validation pipeline (`validateAndGetAgentTemplate`, `validateAgentInput`, `executeSubagent`) but returns the child’s output directly to the parent context.

```json
{
  "tool_name": "spawn_agent_inline",
  "input": { "agent_type": "commander-lite", "prompt": "List files" }
}

```

## Key Implementation Files

| File | Purpose |
|------|---------|
| [`common/src/tools/params/tool/spawn-agents.ts`](https://github.com/CodebuffAI/codebuff/blob/main/common/src/tools/params/tool/spawn-agents.ts) | Zod schema describing the tool’s input and output format. |
| [`packages/agent-runtime/src/tools/handlers/tool/spawn-agents.ts`](https://github.com/CodebuffAI/codebuff/blob/main/packages/agent-runtime/src/tools/handlers/tool/spawn-agents.ts) | Main handler orchestrating validation, state creation, and subagent execution. |
| [`packages/agent-runtime/src/tools/handlers/tool/spawn-agent-utils.ts`](https://github.com/CodebuffAI/codebuff/blob/main/packages/agent-runtime/src/tools/handlers/tool/spawn-agent-utils.ts) | Utility functions for context extraction, permission matching, template validation, state creation, and execution. |
| [`packages/agent-runtime/src/__tests__/spawn-agents-permissions.test.ts`](https://github.com/CodebuffAI/codebuff/blob/main/packages/agent-runtime/src/__tests__/spawn-agents-permissions.test.ts) | Test suite demonstrating permission checks and version handling. |
| [`packages/agent-runtime/src/__tests__/spawn-agents-message-history.test.ts`](https://github.com/CodebuffAI/codebuff/blob/main/packages/agent-runtime/src/__tests__/spawn-agents-message-history.test.ts) | Tests verifying message history filtering and propagation. |
| [`packages/agent-runtime/src/__tests__/spawn-agents-image-content.test.ts`](https://github.com/CodebuffAI/codebuff/blob/main/packages/agent-runtime/src/__tests__/spawn-agents-image-content.test.ts) | Tests ensuring image content handling in subagents. |

## Summary

- The `spawn_agents` tool enables parallel delegation by accepting an array of agent configurations and executing them via `Promise.allSettled`.
- Permission checks in `validateAndGetAgentTemplate` ensure parents can only spawn explicitly allowed child types, with base agents having unrestricted access.
- Input validation via `validateAgentInput` guarantees that prompts and parameters conform to each child agent’s Zod schema before execution begins.
- The `executeSubagent` function manages the full lifecycle, emitting `subagent_start` and `subagent_finish` chunks while streaming intermediate responses back to the parent.
- Cost aggregation automatically sums `creditsUsed` from all children into the parent’s credit counter upon completion.

## Frequently Asked Questions

### What is the difference between `spawn_agents` and `spawn_agent_inline`?

The `spawn_agents` tool returns a JSON array containing results from all spawned children, making it suitable for parallel task delegation where the parent needs to process multiple outputs simultaneously. In contrast, `spawn_agent_inline` returns the child’s output directly to the parent context as if it were the parent’s own response, which is useful for simple delegation scenarios requiring immediate consumption of the result.

### How does Codebuff prevent unauthorized agents from spawning children?

Codebuff implements permission checks in `validateAndGetAgentTemplate` within [`spawn-agent-utils.ts`](https://github.com/CodebuffAI/codebuff/blob/main/spawn-agent-utils.ts). Base agents such as `base`, `base-free`, and `base-parallel` possess unrestricted spawning capabilities, while all other agent types must explicitly declare allowed children in their `spawnableAgents` configuration. When a spawn request occurs, the system validates the child type against this whitelist and rejects unauthorized attempts with a descriptive error message.

### Can subagents spawn their own child agents?

Yes, Codebuff supports nested agent hierarchies through ancestry tracking. When `createAgentState` initializes a subagent, it copies the parent’s `ancestorRunIds` and establishes the new agent’s place in the hierarchy. The `executeSubagent` function then manages the child’s lifecycle independently, allowing it to call `spawn_agents` itself and create further descendants while maintaining proper context isolation and cost attribution throughout the chain.

### How are costs calculated when spawning multiple agents?

Cost tracking occurs through the `creditsUsed` field returned by each subagent execution. After `Promise.allSettled` resolves all child promises in `handleSpawnAgents`, the handler aggregates the `creditsUsed` values from every subagent and adds the total to the parent agent’s credit counter. This ensures transparent cost accounting where the parent bears the cumulative expense of all delegated work, regardless of how many levels deep the agent hierarchy extends.