Skip to content

CH 13 · Subagents and Multi-Agent Orchestration

Word count~3,800 wordsTime~22 minPrereqCH 08, CH 11LevelReproducible

Chapter Goal

When a task is too big or too tangled, instead of letting one Agent grind to the end, let it split it into a few pieces, send several subagents to work in parallel, and gather the results when done. This chapter makes clear: why multi-Agent, what dsh subagents look like, then hands-on run "split task → parallel delegation → merge results", and finally put the full tool family in the inventory.

Why Multi-Agent: Three Hard Spots of Single-Threaded

An Agent going from start to end will hit three problems:

Hard spotSymptom
Context pollutionHalfway through the task, the early steps, intermediate results, and errors all pile up in the same session, and the model increasingly can't tell which info is most important right now
Cannot parallelizeLook up info, write a draft, review code — three things can only queue, the next one waits when the previous isn't done
Drifts further off trackOn long tasks the model easily gets stuck going down a wrong path, retrying the same failed route, burning tokens

Multi-Agent thinking is exactly the remedy: context isolation. Each subagent only holds the context relevant to its task; the main agent splits, dispatches, and collects. Token consumption is controllable, and every step can be reviewed in the Trajectory.

A Key Fact: Subagents Are Also Plugins

First, reassurance: subagents are not a separate thing dsh has hidden away; they are plugins — another confirmation of CH 08's "everything is a plugin". And subagents are already standard in current Agent tools — Claude Code, Codex both have this capability; the only difference is that dsh still exists as a plugin: take it if you want, or you can swap the whole thing out if you don't.

In the config tree, you can see a delegation contract ctx.subagents whose only job is to register "who can be a subagent". Then different provider plugins mount specific backends onto it:

PluginWhat it runs
subagent-spawn-in-processA brand-new in-process subagent (independent context)
subagent-fork-in-process"Derive" a subagent from the parent session's completed history
subagent-acpUses the Agent Client Protocol, accepts out-of-process ACP-compatible Agents
subagent-codexRuns a real Codex (official app-server protocol)
subagent-claude-codeRuns a real Claude Code (official Agent SDK)
subagent-dsh-sdkStarts another full Harness via the TypeScript SDK

What can the main agent see? They are some "model-visible tools". Open the web config tree, the default is:

ToolWhat it doesDefault
subagentDispatch a subagent, continuable modeon
subagent_forkDispatch a subagent with the parent session's memory, one-shoton
ralphEach round swaps in a new subagent to advance the same goalon
workflowWrite scripts to parallel-orchestrate multiple sub-tasksoff (not enabled by default)
send_messageSend follow-up instructions to a specified subagentoff (not enabled by default)
interrupt_agentInterrupt a subagent's current roundoff (not enabled by default)
list_agentsList the current subagents and their statesoff (not enabled by default)

So out of the box, you can call subagent, subagent_fork, and ralph directly. The other tools are either off by default and need to be turned on manually, or are only useful in "continuable mode" — the next section will cover where each of them appears.

spawn vs fork: Two "Openings"

The two most commonly used subagents, the difference is just one: whether to bring the parent session's history along.

  • subagent (spawn): brand-new context. The subagent doesn't know what the main agent has been chatting about, it just follows the instructions you give it this time. Saves tokens, suited for independent tasks.
  • subagent_fork (fork): inherits the parent session's completed portion. The subagent knows "what we were analyzing up to now" and can continue from there. Costs a bit more for the repeated context, suited for tasks that need to build on previous conclusions.

A detail worth noting: dsh puts "whether to inherit" directly in the tool description — spawn-style tool descriptions say "it can't see this conversation", fork-style ones say "it can't see the in-progress turn". That is, the model itself knows whether to repeat the context in the instructions.

Parallel subagents: main Agent splits tasks, dispatches, collects results

One-liner to remember

subagent is like parachuting in a new colleague, who only has your verbal task brief; subagent_fork is like slapping the meeting minutes on him, "continue from where we just left off".

Hands-on: First Parallel Subagents

In parallel, start three subagents, each doing:

  1. Sort out the packages/ directory structure of the deepseek-harness repo, and explain what each capability family does;
  2. Summarize the core concepts the root README covers;
  3. Find subagent-related documentation under docs/, and list them. After all three are done, merge the results into one summary.

Note the three elements in this sentence, missing any one will cause chaos:

ElementWhy it's required
Task split rulesTell the model "split into which pieces", otherwise it just guesses on its own
Wait mechanism (wait until all done)Without this, the main agent may start organizing incomplete results before one subagent is even done
Output requirement (merge into a summary)Without this, the three subagents each throw back a pile of raw text, and you have to piece it together yourself

After sending, you can see in the conversation that the model makes several subagent calls in a row — that's it dispatching. In the default continuable mode, the model "first sends out the parallelizable ones together, then continues with its own work", rather than waiting for the first subagent to return.

Three subagents started in parallel, main agent waiting for their returns

If some subagents finish earlier, that's fine — the main agent will keep waiting for the remaining ones, and only start merging when all are in:

Main agent waits for all subagents to finish before merging

Subagent tool rows in the Trajectory: three subagent calls and the detail panel

Foreground / Background / Continuable: Three Run Modes

Subagents aren't just "dispatch and wait for the result". By "whether to wait, whether to keep talking" they split into three modes:

ModeWhen to useWhat you see
Foreground one-shotThe next step must immediately depend on this resultWait for the subagent to return the final text
Background job (one-shot background)Don't need to wait, collect laterstarted background subagent job <id>, use job_output to collect, job_kill to stop
Continuable subagentMay need to send follow-up instructions, go back and forthstarted subagent <childId>, can send messages later

The default subagent is continuable mode: dispatched to run in the background by default, and the main agent does its own thing; when the subagent is done, a callback notification delivers "it's done, here's the result". The model only switches to foreground waiting when the next step really needs the result.

When you want more control over a continuable subagent, you need to turn on send_message (follow-up instructions), interrupt_agent (interrupt the current round, don't destroy, can resume), list_agents (list subagents and states). They're off by default because most scenarios don't need them — it's an "advanced capability, turn it on when you need it".

workflow and ralph: Two "Orchestration" Tools

Besides "split into pieces and run in parallel", dsh also has two more structured orchestration types, both plugins:

ToolWhat it doesSuited for
workflowLet the model write a small orchestration script, fan out sub-tasks with agent() / parallel() / pipeline(), and finally return a resultLarge number of tasks, fixed structure, need precise control over execution order (e.g. analyze 10 documents at once)
ralphEach round swaps in a new subagent to advance the same goal, with a handoff report written at the end of each round for the next roundMulti-round refinement, easy to get stuck in a rut, creative or debugging tasks

ralph is on by default (subagent uses spawn, max 64 rounds). workflow is off by default — its script runs in a separate thread, it's an "orchestration constraint" not a security sandbox, only worth turning on for clear batch scenarios.

::: tl;dr Daily parallel → subagent; To continue with previous conclusions → subagent_fork; Structured bulk → workflow (off by default); Anti-rut iterative refinement → ralph. :::

Common Pitfalls

PitHow to avoid
Multiple subagents writing to the same file at the same timeParallel tasks should prioritize reads (search, analyze, review); for writes, let the main agent collect all results and write in one go
Forgot to say "wait until all done" in the instructionsInclude the wait mechanism when dispatching, otherwise the main agent may start working with half the results
Tasks split too finelyEach subagent has startup overhead; splitting a 5-minute task into 10 subagents is actually slower; split down to "independently complete one meaningful thing"
Subagents nest infinitelyDelegation depth has a cap (default 3, 0 means forbidden); keeping a "main agent → subagent" star topology is the most stable

What you learned in this chapter

You pass if you can complete the items below:

  • [ ] State the three hard spots of single-Agent long tasks, and the core value of multi-Agent (context isolation)
  • [ ] Know that subagents are also plugins: ctx.subagents is the delegation contract, spawn / fork are the two most commonly used backends
  • [ ] Distinguish subagent (brand-new context) from subagent_fork (with the parent session's completed history)
  • [ ] Have run a "split tasks + wait for all done + merge results" parallel subagent at least once, and seen the subagent call in the Trajectory
  • [ ] State the differences between foreground, background job, and continuable subagent modes
  • [ ] Know what workflow, ralph, send_message, interrupt_agent, list_agents each do

Open Source · MIT · Community Driven