# How the spawn-agents Tool Coordinates Parallel Agent Execution in Freebuff

> Discover how Freebuff's spawn-agents tool orchestrates parallel agent execution using Promise.allSettled, ensuring efficient coordination and consolidated results for your AI workflows.

- Repository: [Codebuff/freebuff](https://github.com/CodebuffAI/freebuff)
- Tags: internals
- Published: 2026-08-20

---

**The `spawn_agents` tool launches multiple child agents concurrently using `Promise.allSettled`, shares the parent's execution context, validates each child specification, creates isolated `AgentState` instances, aggregates results after all agents complete, and combines billing costs back into the parent agent.**

The `spawn_agents` tool is a core orchestration primitive in the [CodebuffAI/freebuff](https://github.com/CodebuffAI/freebuff) agent runtime that enables a parent agent to delegate work to multiple specialized sub-agents in parallel. Understanding how parallel agent execution is coordinated reveals the architectural decisions behind safe, deterministic multi-agent workflows.

## Preparing the Shared Execution Context

Before any child agents launch, the tool extracts the parent's runtime dependencies once through `extractSubagentContextParams`. This function, defined in [[`spawn-agent-utils.ts`](https://github.com/CodebuffAI/freebuff/blob/main/spawn-agent-utils.ts)](https://github.com/CodebuffAI/freebuff/blob/main/packages/agent-runtime/src/tools/handlers/tool/spawn-agent-utils.ts#L60-L68), captures:

- Environment configuration
- Billing/credit tracking state
- LLM client instances
- Other shared infrastructure

This single extraction ensures all children inherit consistent context without redundant setup overhead.

## Validating Child Agent Specifications

Each child agent specification undergoes two-phase validation in `validateAndGetAgentTemplate` and `validateAgentInput` (same file, lines 71-98):

1. **Template validation** — confirms the requested `agent_type` is allowed in the current runtime and loads its configuration template
2. **Input validation** — checks the supplied `prompt` and `params` for type correctness and required fields

Failed validations reject that specific child without aborting the entire batch.

## Creating Isolated Agent States

For every validated child, `createAgentState` (lines 51-63) constructs an independent `AgentState` instance. This isolation prevents cross-contamination: each sub-agent maintains its own message history, tool access, and execution lifecycle while still sharing the parent's underlying infrastructure.

## Launching Agents Concurrently with Promise.allSettled

The core parallel coordination happens in [[`spawn-agents.ts`](https://github.com/CodebuffAI/freebuff/blob/main/spawn-agents.ts)](https://github.com/CodebuffAI/freebuff/blob/main/packages/agent-runtime/src/tools/handlers/tool/spawn-agents.ts#L89-L96):

```typescript
const results = await Promise.allSettled(
  agents.map(async ({ agent_type, prompt, params }) => { … })
);

```

**Why `Promise.allSettled` instead of `Promise.all`?** The settled variant guarantees the parent receives results from every child even when individual agents fail. This design choice supports partial success patterns common in multi-agent workflows—some children may hit LLM rate limits or encounter tool errors while others complete successfully.

Each mapped promise executes this sequence:

- Create sub-agent state
- Validate configuration
- Call `executeSubagent` to run the core agent loop

## Executing Individual Sub-agents

The `executeSubagent` function ([[`spawn-agent-utils.ts`](https://github.com/CodebuffAI/freebuff/blob/main/spawn-agent-utils.ts)](https://github.com/CodebuffAI/freebuff/blob/main/packages/agent-runtime/src/tools/handlers/tool/spawn-agent-utils.ts#L66-L80)) invokes `loopAgentSteps`, the runtime's standard LLM-backed agent driver. During execution, it emits lifecycle events:

- `subagent_start` — sent when a child begins
- `subagent_finish` — sent on completion or failure

These events enable real-time monitoring of parallel agent execution from the parent or external observer.

## Collecting and Aggregating Results

After all promises settle, the handler builds a structured report (lines 98-115 in [[`spawn-agents.ts`](https://github.com/CodebuffAI/freebuff/blob/main/spawn-agents.ts)](https://github.com/CodebuffAI/freebuff/blob/main/packages/agent-runtime/src/tools/handlers/tool/spawn-agents.ts#L98-L115)):

```typescript
// Results array contains status, value/error, and metadata for each child
const report = results.map((result, index) => ({
  agentName: agents[index].agent_type,
  agentType: agents[index].agent_type,
  value: result.status === 'fulfilled' ? result.value : result.reason,
}));

```

The tool then aggregates billing costs (lines 18-60), adding any credits consumed by successful or partially-failed sub-agents to the parent's `creditsUsed` field. This ensures accurate cost attribution across the entire parallel batch.

## Practical Usage Examples

### Spawning Multiple Agents Simultaneously

```typescript
await runTool({
  name: 'spawn_agents',
  input: {
    agents: [
      { agent_type: 'code-reviewer', prompt: 'Review this PR', params: {} },
      { agent_type: 'test-runner',   prompt: 'Run tests',    params: {} },
    ],
  },
});

```

This call launches both agents in parallel. The code reviewer and test runner execute simultaneously, subject only to underlying LLM provider rate limits.

### Processing the Returned Report

```typescript
const { output } = await runTool(...);
const reports = output[0].value; // array of { agentName, agentType, value }

reports.forEach(r => {
  if (r.value instanceof Error) {
    console.error(`${r.agentName} failed:`, r.value.message);
  } else {
    console.log(`${r.agentName} (${r.agentType}):`, r.value);
  }
});

```

The settled results preserve individual success/failure states while presenting them in a unified structure.

## Comparison: spawn_agents vs spawn_agent_inline

| Tool | Use Case | Concurrency | Message History |
|------|----------|-------------|---------------|
| `spawn_agents` | Multiple independent children | Parallel | Isolated per child |
| `spawn_agent_inline` | Single child sharing parent context | Sequential | Shared with parent |

The `spawn_agent_inline` tool ([[`spawn-agent-inline.ts`](https://github.com/CodebuffAI/freebuff/blob/main/spawn-agent-inline.ts)](https://github.com/CodebuffAI/freebuff/blob/main/packages/agent-runtime/src/tools/handlers/tool/spawn-agent-inline.ts#L25-L34)) creates state with `includeMessageHistory: true` and runs synchronously—appropriate when the parent needs to continue a coherent conversation through a single delegate.

```typescript
await runTool({
  name: 'spawn_agent_inline',
  input: {
    agent_type: 'doc-generator',
    prompt: 'Create API docs',
    params: {},
  },
});

```

## Key Implementation Files

- **[[`spawn-agents.ts`](https://github.com/CodebuffAI/freebuff/blob/main/spawn-agents.ts)](https://github.com/CodebuffAI/freebuff/blob/main/packages/agent-runtime/src/tools/handlers/tool/spawn-agents.ts)** — Core handler with `Promise.allSettled` coordination, result aggregation, and cost accounting
- **[[`spawn-agent-utils.ts`](https://github.com/CodebuffAI/freebuff/blob/main/spawn-agent-utils.ts)](https://github.com/CodebuffAI/freebuff/blob/main/packages/agent-runtime/src/tools/handlers/tool/spawn-agent-utils.ts)** — Context extraction, validation utilities, state creation, and `executeSubagent` implementation
- **[[`spawn-agent-inline.ts`](https://github.com/CodebuffAI/freebuff/blob/main/spawn-agent-inline.ts)](https://github.com/CodebuffAI/freebuff/blob/main/packages/agent-runtime/src/tools/handlers/tool/spawn-agent-inline.ts)** — Sequential single-child variant with shared history

## Summary

- **Parallel execution** uses `Promise.allSettled` to run all child agents concurrently while capturing individual success and failure states
- **Shared context** is extracted once via `extractSubagentContextParams` and inherited by all children
- **Validation** occurs per-child through `validateAndGetAgentTemplate` and `validateAgentInput`, with failures isolated to that agent
- **State isolation** via `createAgentState` ensures independent execution lifecycles
- **Result aggregation** combines outputs and costs only after every child settles, producing a deterministic final report
- **Billing transparency** adds sub-agent costs to the parent's `creditsUsed` for accurate accounting

The design prioritizes **observability** (lifecycle events), **fault tolerance** (allSettled semantics), and **cost accountability**—essential properties for production multi-agent systems.

## Frequently Asked Questions

### What happens if one spawned agent fails?

The failure is captured in the results array with status `'rejected'` and the error reason. Other agents continue and complete normally. The parent receives a complete report showing which children succeeded and which failed, enabling targeted retry logic or graceful degradation.

### How does parallel agent execution handle rate limits?

Actual concurrency is constrained by the underlying LLM provider's rate limits and the runtime's HTTP client configuration. The `Promise.allSettled` structure launches all promises simultaneously, but network-level queuing or provider throttling may serialize requests. The runtime does not implement additional concurrency limiting—this is left to infrastructure configuration.

### Can spawned agents spawn their own children?

Yes. Since each child receives a full `AgentState` with tool access including `spawn_agents`, nested parallel execution is technically possible. However, the current implementation in CodebuffAI/freebuff does not include explicit depth limits, so application-level guardrails should prevent unbounded recursion.

### What's the difference between shared and isolated message history?

Shared history (via `spawn_agent_inline`) preserves the entire conversation thread between parent and child, making it suitable for delegated single tasks that must return to the parent's context. Isolated history (default in `spawn_agents`) gives each child a clean slate, appropriate for independent work that should not pollute or leak into other agents' contexts.