Files
deepseek-harness/packages/subagent/subagent-fork

@deepseek-ai/dsh-subagent-fork

The in-process fork subagent backend: a SubagentProvider that runs each child as a child Agent seeded with a prefix of the parent's session log — so the child inherits the parent's conversation context instead of starting fresh. Shares the run driver (startInProcessRun) with dsh-subagent-spawn; the only difference is the seed. The shared run.started boundary resolves only after the seeded child is published, so subagent/start observers see a live registry entry.

The seed boundary (the crux)

At the moment a subagent tool's execute runs, the parent's CURRENT turn is open and unbalanced: the log holds the assistant/message carrying this spawn's tool-call and the dangling tool/call with no tool/result yet. Seeding that raw prefix would give the child an open turn that the session constructor and the dev-mode invariants replay reject.

So the fork seeds only the balanced completed-turn prefix — the parent's log up to and including its last turn/end, excluding the in-flight turn entirely (completedTurnPrefix). Because the live log keeps seq === index, the slice is contiguous-from-0 and a valid seed. A parent on its very first (not-yet-complete) turn forks an empty seed — i.e. effectively a fresh child.

The seam this rides on: CreateAgentOptions.seed (added on dsh-agent, threaded through AgentLoop.createAgentctx.sessions.prepare({ seed })), the same primitive resume uses.

Capabilities

{ outputSchema: true, depthLimit: true, toolFilter: true, persona: true } — identical to spawn because the shared driver owns depth, model, persona, tool-filter, and structured-output behavior.

Config

Key Meaning
providerName Registry name on ctx.subagents (default fork).

See dsh-subagent-spawn for the run lifecycle, model inheritance, and depth tracking — all shared.

Model Experience

Context surface What the model sees Token effect
Child-agent history The child receives the parent's balanced completed-turn surface prefix, then the new task, along with its own scoped persona, tool filter, and optional structured-output contract. The parent's current in-flight turn is excluded. Forking duplicates the retained completed history into a separate child's requests; the child then accumulates its own tokens independently. A first-turn fork has no inherited history.
Parent tool result, indirectly The parent receives only the child's own final output through dsh-tool-subagent, not the inherited prefix or intermediate work. Parent input grows by one data-dependent final result retained until compaction.

Known Limitations and Deferred Work

  • Runs expose no sendMessage/resume — the optional runtime capabilities are absent on in-process runs; the consumer collects synchronously.
  • The seed is a one-time snapshot — the child sees the parent's completed turns as of the fork and nothing the parent logs afterwards; there is no live context sharing.