dshkit

Sub-agents, workflows and the Ralph loop in DeepSeek Harness

How dsh delegates work: the subagent and subagent_fork tools, background agent control, the workflow tool's agent/pipeline/parallel primitives, job management, and what a Ralph loop actually is.

Updated 2026-08-134 min
Short answer

Delegation in dsh is four separate tool families: subagent and subagent_fork spawn agents, subagent-control sends messages to and interrupts them, jobs manages background work of every kind, and workflow orchestrates with agent(), pipeline() and parallel(). The ralph tool is a distinct shape — a foreground loop of fresh child sessions driving at one immutable objective.

Most coding agents delegate by prompting themselves harder. DeepSeek Harness ships four genuinely distinct delegation mechanisms, and using the wrong one is the difference between an orchestration that converges and one that burns tokens in a circle.

Spawning: subagent and subagent_fork

@deepseek-ai/dsh-tool-subagent provides subagent, and where the fork backend is mounted, also subagent_fork.

The distinction is what the child starts from. A plain sub-agent begins with the task you hand it. A fork begins from the current session's state — useful when the child needs the context you have already built, wasteful when it does not.

The general rule: fork when the context is the task ("keep going down this path, but try the other fix"), spawn fresh when the task is separable ("go read these thirty files and report what you find").

Controlling what is running

@deepseek-ai/dsh-tool-subagent-control gives the parent three verbs:

  • send_message — a follow-up to a running background sub-agent
  • interrupt_agent — stop its current turn
  • list_agents — see what is actually alive

And @deepseek-ai/dsh-tool-subagent-report gives the child one: report, which passes findings back to the parent. It is visible only inside continuable in-process child sessions — a child that cannot be continued has nothing to report into.

This is a real message-passing surface rather than fire-and-forget delegation. A parent can start five sub-agents, watch them with list_agents, redirect one with send_message, and kill another that has gone off the rails — without waiting for all five to finish.

Jobs

@deepseek-ai/dsh-tool-jobsjob_list, job_output, job_kill — manages background work across every job type: bash commands started with run_in_background, persistent terminals, and sub-agents alike.

That unification matters. Without it you would need a different mental model for "the build I backgrounded" and "the agent I spawned". Here they are both jobs.

Workflows

@deepseek-ai/dsh-tool-workflow orchestrates multi-agent work with three primitives:

  • agent() — run one agent
  • pipeline() — run items through stages
  • parallel() — run tasks concurrently

The important structural choice is between pipeline() and parallel(). A pipeline moves each item through every stage independently — item A can be in stage three while item B is still in stage one. parallel() is a barrier: everything must finish before anything proceeds.

Reach for the barrier only when a later stage genuinely needs all of the earlier stage's results at once — deduplicating across a full result set, or deciding whether to proceed at all. Otherwise the pipeline finishes in the time of the slowest single chain rather than the sum of the slowest stages.

The Ralph loop

@deepseek-ai/dsh-tool-ralph is not a workflow variant. It is a different shape, and the harness's own glossary defines it precisely:

  • A Ralph loop is one foreground fresh-agent workflow run toward an immutable objective.
  • A Ralph round is one fresh child session in that loop, with no parent conversation seed.
  • A Ralph handoff is the normalised, bounded, structured report passed from one continuing round to the next.

Read those three definitions together and the design intent is clear. The objective cannot drift, because it is immutable. Context cannot bloat, because each round starts fresh. And continuity is preserved not by carrying the conversation but by carrying a bounded structured report.

That is a direct answer to the failure mode of long agent sessions: an agent thirty turns deep is reasoning inside a context that is mostly archaeology. Ralph throws the archaeology away every round and keeps only the handoff.

Use it when the objective is genuinely fixed and progress is measurable between rounds — grind a test suite to green, work a list until it is empty.

Do not use it when the objective should be allowed to change as you learn. Immutability is the point, and it is the wrong property for exploration.

Goals, which are not todos

Two more pieces are easy to conflate:

todo_write (@deepseek-ai/dsh-tool-todo) is session scratch state — pending, in_progress, completed, and each call replaces the whole list.

create_goal / get_goal / update_goal (@deepseek-ai/dsh-tool-goal) is durable. The glossary defines a goal as one durable completion objective attached to an existing session, with a phase and a round cap, supporting pause, resume, complete and blocked states. A goal round is one continuation cycle admitted for the current goal, and goal activation is the process-local permission that admits another one.

The round cap is the part worth noticing. A durable objective with no bound is how an agent loop becomes an unbounded bill.

Scoping: why a sub-agent's tools differ

The harness's scope model explains the behaviour people find surprising when a child agent has a different tool set than its parent.

A scope is the unit of per-agent registration for contributions such as tools and prompts — either global or scoped to one agent. Shadowing is most-specific-wins name resolution: a scoped item replaces a same-named global item for that scope alone. A restriction filters the global tool set for one scope by intersection.

So a sub-agent is not handed a copy of your tools. It is composed with its own scope, which may shadow, restrict, or extend what is globally registered. That is the mechanism behind a preset like "a reviewer that can read but never write" — a restriction on one scope, not a different program.

Frequently asked

What is the difference between subagent and subagent_fork?

Both delegate to a separate agent; the fork backend registers additionally as subagent_fork. Forking starts the child from the current session's state rather than from nothing.

What is a Ralph loop?

One foreground fresh-agent workflow run toward an immutable objective. Each Ralph round is a fresh child session with no parent conversation seed, and a normalised bounded structured report — the handoff — carries context from one round to the next.

Why use a fresh session per round instead of continuing one?

A long session accumulates context that is mostly irrelevant to the current step, and irrelevant context degrades attention. Restarting with a bounded structured handoff keeps every round's context proportional to the work in front of it.

Do sub-agents share my tools?

Registrations are scoped. A scope is the unit of per-agent registration for contributions like tools and prompts, and scoped items shadow same-named global items for that scope alone.

Keep reading