Lesson 8 of 19 · 13 min read
Run several agents without losing the thread
Split independent work, choose models deliberately, and bring the results back through one review. A practical orchestration pattern for DeepSeek Harness, with its capability limits made explicit.

Course syllabus · lesson 8 of 19
In this lesson
Parallelism is only useful when the work can be separated without weakening ownership. Two agents can inspect different parts of a bug at once; they can also overwrite the same file twice as fast. The useful unit is a bounded task with an owner, an input, an output contract, and evidence to return.
This lesson extends the search-race exercise for developers who already delegate work to agents. It is a recommended coordination pattern, not a recorded multi-agent run. The diagram shows our proposed ownership model, not a screenshot or a promise that DSH chooses these roles automatically.
First, check what your Harness actually exposes
DSH's subagent contract makes delegation optional and provider-dependent. One-shot runs return a terminal result; continuable children support later messages. Supported one-shot backends can accept model overrides, but not every backend accepts them. A child starting successfully does not prove its task succeeded.
There is also an experimental Agent Teams package. It needs durable session storage and its companion tool package. It adds named teammates, messaging, and a shared task board in one process and one checkout. It does not supply separate worktrees or merges. Treat it as an opt-in deployment feature, not something this tutorial assumes is enabled in every Web session.
Before delegating, ask the current session to identify its available delegation tools and their supported options. Check that answer against the installed composition and the linked reference. If the tools are absent, do the stages sequentially. A prompt cannot install a missing capability. Do not paste internal service method names into a terminal as if they were CLI commands.
Give each role a different responsibility
Use these roles as instructions, not product presets:
- Orchestrator: Holds the task boundary, resolves design choices, assigns non-overlapping work, reconciles evidence, and decides what may proceed.
- Worker: Completes one named assignment within its allowed paths. Reports what changed, what was checked, and what remains unknown.
- Reviewer: Inspects the assembled result against the original requirements. Reports reproducible findings without changing the patch being reviewed.
The orchestrator owns the final decision; it should not edit a worker's files while that worker is active. The reviewer should examine the actual candidate and requirements, not merely endorse a worker's summary. These roles can use the same model. Independence comes from a separate inspection and a clear remit, not a different brand name.
Fan out only after agreeing on the question
Start with the same revision and the search contract from Part 7: only the current request may update the view. A useful first split is read-only:
Coordinate a search-race investigation. Do not edit yet.
If supported, run at most two independent workers concurrently.
Worker A: trace request creation, identity, completion, and clearing.
Return actual paths, the ownership rule, and the nearest state tests.
Worker B: inspect loading, empty, error, retry, and keyboard behavior.
Return actual paths and a deterministic browser reproduction plan.
Both: read-only; no installs, external requests, commits, or deployment.
Do not delegate further. Report missing context instead of guessing.
Wait for both outcomes. Reconcile disagreements before proposing edits.
If parallel delegation is unavailable, perform these stages sequentially.
Two concurrent workers is my starting budget for this exercise, not a DSH platform limit. It leaves room to understand both reports and keeps test processes, context duplication, and provider use manageable. Increase it only when you can name another independent task and explain how you will verify its output. More workers also mean more results to reconcile.
An invalid split would give one worker the request-identity implementation and another the controller integration before either agrees on the interface. The second task depends on the first. Keep that edge serial: decide the contract, implement the state rule, then wire the controller.
Choose models for the assignment, not the diagram
The model configuration guide explains configured providers and the model picker. That picker is not evidence of an automatic per-role router. A provider connection and a delegation backend are different configuration concerns.
For one-shot delegation, the subagent reference documents capability-gated provider, model, effort, and output-token overrides. In-process backends merge supported overrides over parent options; the DSH SDK backend uses its own defaults. ACP, Codex, and Claude Code backends reject that agentOptions field. Do not assume the same route controls work everywhere.
For a deployment that should let the agent choose child models, the delegation-tool reference documents modelSelectionSettings: true and the host's exact-route authorization preference. This requires a compatible backend. The enabled tool exposes list_subagent_models and optional route fields; provider and model are supplied together. Treat these as model-facing tools and deployment settings, not shell commands. Ask the orchestrator to list the authorized routes before assigning a model, and stop if the required route is absent.
My recommendation: use a model you have already checked on a small representative task. Keep ambiguous design and final review on a model that can handle the full relevant context. Try a cheaper or faster route for bounded extraction only after checking its accuracy on that workload. Keep the same acceptance tests across routes; record the model and settings with each report. This is a selection method, not a claim that a particular model is best.
Do not silently switch providers after a quota or transport failure. That can change cost and where repository content is sent. Stop and confirm an authorized route before trying again.
Route a task to a model, then check the choice
Choose the route after defining the assignment. These are the questions I would use; they are selection criteria, not a benchmark ranking:
- Architecture and review: Prefer the strongest reasoning route you have verified on the relevant workload. It must fit the contract, affected code, and evidence in context. A larger model name alone proves none of that.
- Bounded mechanical work: Try a faster or cheaper route for independent extraction, fixture inspection, or a small prescribed transformation. Measure accuracy, elapsed time, and actual provider usage before keeping it in that role.
- Specialist or long-context work: Check that the exact route supports the required input, context size, and tools. A model that can read a screenshot is not automatically compatible with the delegation backend that would call it.
- Failure and fallback: Name an approved alternate in advance, including the provider and data boundary. If it is unavailable or unauthorized, stop. Do not trade away a required capability merely to keep an agent running.
Here is a concrete routing exercise using four labels observed in the local opencode-go picker in Part 2. This is an example allocation, not a claim that these models were tested, rank in this order, or have equal prices. The local picker does not prove they are available to child agents.
Use DeepSeek V4 Pro (New) as the orchestrator candidate. Ask it to hold the search-race contract and resolve architectural questions. Assign Worker A's read-only request trace to MiniMax-M3, and Worker B's independent UI-state inspection to Qwen3.8 Flash. After the reports agree, let one designated writer implement the bounded repair. Give GLM-5.3 a separate, read-only review of the frozen candidate. The review remains independent even though one orchestrator owns the final decision.
Before trying that allocation, use the enabled list_subagent_models tool to resolve each display label to an exact authorized provider/model pair. Do not invent a model id from its spelling. Select the parent route through its configured picker; per-child choices use the documented one-shot route fields only when the compatible backend and host policy expose them. Reconcile conflicting evidence before the writer starts, and run the same integration gates regardless of which model produced the work.
If those child routes are unavailable, the diagram is not executable in that session. Use separate authorized sessions with explicit handoffs, or run the stages serially; neither is automatic per-subagent routing. The OpenCode Go compatibility caveat in Part 2 still applies. A visible provider label is not a successful compatibility check.
Protect the shared checkout
In experimental Teams, file scopes are advisory: the task contract describes overlap warnings, not filesystem locks. A task-board ownership record is not permission enforcement.
After both investigations return, appoint one writer for the search repair. Give it the reconciled contract, actual paths, tests, and a stop rule. If a later task truly has disjoint writes, list each owner's files explicitly. “Frontend” and “tests” are too vague when both workers may touch a shared fixture, exported type, or package manifest.
Serialize changes to shared types, generated outputs, lockfiles, and common configuration. Do not run concurrent formatters over the same directory. Even separate test commands can collide through a common port, database, snapshot folder, or build cache; use isolated resources or run them one at a time.
Separate worktrees can isolate files in a workflow that explicitly supports and sets them up, but they still need integration and conflict checks. They are not an automatic property of starting another agent, and the Team package does not create them for you.
Reconcile evidence before review
Require a compact handoff from each worker:
Assignment and starting revision:
Status: complete / partial / blocked
Actual paths inspected or changed:
Observed behavior and supporting evidence:
Commands run, exit codes, and artifact paths:
Checks not run and why:
Open processes, unresolved risks, and the next safe action:
If A reports that clearing invalidates a request but B sees old results after clearing, neither report wins by confidence. Reproduce the disputed path. Check whether the state rule exists but the view bypasses it. Assign that precise investigation before changing more code.
Freeze the candidate while the reviewer inspects it. Give the reviewer the original contract, final diff, and evidence, including failed or skipped checks. A finding should identify a path, expected behavior, actual behavior, and reproduction. Confirm it, send a bounded repair to the owner, then review that repair. Do not ask the reviewer to quietly rewrite the same candidate it is judging.
Make the join deterministic
Fan-out creates a second design problem: how the host decides that the branches are complete enough to reconcile. Give every child a stable task id, role, input revision, allowed paths, deadline, and result schema. The parent should be able to distinguish completed, failed, cancelled, timed-out, and unknown, even when the child returns a plausible paragraph.
Use an explicit join policy. For two independent read-only reviews, “both complete with a structured result” may be required before a writer can start. If one reviewer fails, the parent can preserve the successful evidence and stop for inspection. It should not silently treat a missing branch as agreement. If a branch times out after a tool may have written, mark its workspace and side effects unknown until inspected.
Model cancellation as a state transition, not a delete operation. A cancelled child may already have emitted a tool call or changed a file. Record the cancellation request, the last observed event, and the cleanup result. If the host cannot prove cleanup, keep the branch quarantined and prevent the writer from using its checkout.
Reconciliation should compare evidence, not prose length. Check whether both branches started from the same revision, whether their findings point to real paths, and whether their proposed actions overlap. When findings disagree, preserve both with the conflict reason and ask for a focused decision. A longer answer is not a tie-breaker.
Stop, inspect, then recover
Interruption needs care. The continuable subagent contract says interruption requests cancellation without waiting for quiescence; queued work and descendants are not automatically removed. The Team package also retains task ownership when a teammate is interrupted.
So do not treat “stop requested” as “all writers stopped.” Check the affected agents and processes before assigning their files again. Inspect partial changes and saved outputs; interruption is not a filesystem rollback. Preserve unrelated edits. Resume from the last verified boundary, not from an optimistic summary.
For a failed worker, keep its result marked partial or blocked until the missing evidence is supplied. A timeout does not establish whether work finished. If the status is unknown, resolve that uncertainty before retrying a write. Keep successful independent evidence, but rerun checks whose inputs changed during recovery.
Integrate once, then verify the result
For the search exercise, the final gate is still the same: state tests, controller ownership, visible browser behavior, recovery paths, and the original API and layout. Run the project's lint, type checks, tests, and build against the assembled candidate, with browser checks for the race and keyboard behavior. Require actual command results and inspect the diff for weakened tests or unrelated changes.
Two green worker reports do not prove their combined patch works. One agent saying “done” does not authorize a commit, push, or deployment. Keep those actions behind the user's explicit release decision.
Do not parallelize a tiny edit, a task whose contract is still disputed, or work that needs the same files and mutable test environment. Use one worker when explaining the split would take longer than doing the work. The aim is a result you can verify, with less waiting where the work really is independent.
Next, build a custom web environment around these capabilities, with explicit boundaries for users, tools, and stored data.
Before you move on
Try it in your workspace
Split one task into independent read-only questions. Assign routes, output contracts, and an accountable reviewer. If the backend cannot route models, document the serial fallback and its tradeoff.
Keep a short note of what you tried, what passed, and what you still need to check.
0 of 3 checked.
Saved in this browser when storage is available. Uncheck any item to revisit it. This is your own record, not an assessment.