<!-- Markdown mirror. Canonical: https://empryo.com/docs/agents/dispatch -->

# Parallel agents

> Forge dispatches Spark and Ember sub-agents in parallel for multi-file work, sharing an I/O cache and findings while a model mix cuts cost.

![Strong models get the short tour, small models get the full manual and a scout, and every tool result gets a budget.](https://empryo.com/media/forge-v2-delivery.svg)

*Strong models get the short tour, small models get the full manual and a scout, and every tool result gets a budget.*

For bigger tasks, Forge (the main agent) dispatches sub-agents in parallel. Each one does a slice of the work, then reports back.

## Two tiers

| Agent | Role | Model (router slot) |
|-------|------|---------------------|
| Spark | Read-only research: navigate, read, analyze | `spark` |
| Ember | File edits, refactors | `ember` |

Plus a WebSearch agent for multi-step web research, and a background lane: `background_dispatch` (or `explore` with `background: true`) detaches a worker as a `bg-N` handle that keeps running while the conversation continues. Its report is delivered back automatically when it finishes.

Assign cheap models to `spark`, strong models to `ember` in the [task router](/docs/recipes/task-router). That is where most of the cost savings come from.

## What they share

- **I/O cache.** When multiple agents run concurrently and one has already fetched a file, the others get the cached bytes instead of touching disk again. This is a speed win, not a token win: every agent still reads the content into its own context window and pays tokens for it.
- **Edit serialization.** Concurrent writes to the same file are queued, not raced.
- **Findings channel.** One agent's discovery reaches the others at their next step.

## How the cost savings actually work

Savings do not come from shared context. They come from:

- **Model mix.** Spark agents run on a cheap model (Haiku, Flash) while Ember runs on a strong one. The [task router](/docs/recipes/task-router) decides per task.
- **Symbol-level access.** Agents use LSP go-to-definition and surgical symbol reads, not `grep + cat` on whole files. See [code intelligence](/docs/concepts/intelligence).
- **Parallelism hides latency.** Three agents finishing in parallel beats one agent doing three things serially.

## When dispatch happens

You do not trigger it. Forge decides when a task benefits from parallelism: multi-file refactors, research questions spanning several modules, or plan-mode execution. For one-shot questions, Forge does the work directly.

## Steering mid-flight

Type while the agents are running. Your message is queued and injected at the next step. See [steering](/docs/agents/steering).

Individual workers can be steered too. Forge uses `agent_send(agentId, message)` to redirect a running dispatch task or background handle. On the desktop, the per-agent activity modal has an instruction box that does the same thing. Deliveries land at the agent's next step boundary and show up as a distinct instruction row in its activity log, with an “instructed” badge on the lane.

## Council: resident agents you talk to

A dispatched agent normally answers once and exits. Spawn one with `resident: true` on `background_dispatch` and it joins the council instead: after each reply it parks as `waiting` with the conversation retained, and Forge continues the exchange with `agent_send(id, message)`, back and forth, like a colleague on a thread. `background_stop(id)` dismisses it.

A resident reads files from the cache the main agent already filled, so a long conversation does not re-pay for the same files. Its transcript has a cap, and the oldest exchanges drop first.

Councils have limits: 4 residents at a time, 12 exchanges each, and an idle member expires after 30 minutes. Ask Forge to "spawn an advisor and discuss" and it runs a council. Residents show as `waiting` in the Subagents panel.

## Dispatching to your own agents

Spark and Ember are the defaults. When you define your own agents as markdown files, Forge sees their descriptions and can hand a task to one instead, running it under that definition's prompt, model, and tool policy, in-turn (`dispatch`) or detached (`background_dispatch`). Lanes running under a definition are badged with its name in the Subagents panel and the TUI dispatch tree. See [agents](/docs/tools/agents).
