DSH Route
English | 简体中文
Agent-team orchestration for DeepSeek Harness: a Lead assigns tasks to members, members delegate to one level of child agents, and each member reviews its children's output before completing a task.
Quick start · Tools · Configuration · Dashboard · Persistence · Development
Compatibility: @deepseek-ai/dsh@0.2.1-rc.5, Node.js ≥ 22. This package pins its Harness peers and declares an exact engines.dsh version.
Why DSH Route?
- Bounded delegation: one child level per member, at most 3 active children per member.
- Team capacity: normal admission up to 12 active agents; completion wakeups may use reserved capacity up to the hard limit of 15, including the Lead.
- Attempt isolation: every assignment gets a new attempt ID. Late writes are rejected and stale output goes to explicit review.
- Parent-reviewed results: children can report output, but only the parent member or Lead can update tasks.
- Stable routes: provider, model, and reasoning effort are snapshotted at creation and restored on subsequent requests.
- Durable state: atomic disk snapshots, persistent inboxes, and recovery after interrupted execution.
- Read-only dashboard: inspect dependencies, worker routes, active children, and pending reviews.
flowchart TD
L[Lead · root Session] --> A[Member A · researcher]
L --> B[Member B · executor]
A --> C[Child A1]
B --> D[Child B1]
B --> E[Child B2]
C -. report .-> A
D -. report .-> B
E -. report .-> B
Quick start
Install a release
- Download
dsh-route-0.1.0.tgzandroute.patch.ymlfrom the v0.1.0 release. - Place both files in one directory. Edit
workspaceinroute.patch.ymlto your workspace's absolute path, such asC:/projects/my-appon Windows or/home/me/projects/my-appon Linux/macOS. - Run the following commands from that directory:
dsh --profile route-team --from-default-profile web --dump-config
dsh plugin --profile route-team add ./dsh-route-0.1.0.tgz
dsh --profile route-team --dump-config
dsh --profile route-team --patch ./route.patch.yml
The first command initializes a new Web profile. If your target profile already exists, skip it and use the existing profile name in the remaining commands. If dsh is not installed globally, replace the leading dsh with npx @deepseek-ai/dsh@0.2.1-rc.5.
Configure your model providers and credentials in Harness before using the plugin. DSH Route does not create or modify credentials.
The example overlay configures the host's subagent service with maxDepth: 2 and maxActiveSubagents: 14. The host counts children, while this plugin's hard limit of 15 includes the Lead. Without the overlay, the host may reject a start before the plugin quota is reached. Preserve any additional host settings you need: a patch replaces the entire config object.
Build from source
git clone https://github.com/mentho7/dsh-route.git
cd dsh-route
npm ci
npm run check
npm pack
This produces dsh-route-0.1.0.tgz. Follow the installation steps above, using ./examples/route.patch.yml for --patch.
For local development, you can pass the checkout's absolute path to dsh plugin ... add, then rebuild and reload after changes. A direct GitHub source install does not automatically provide lib/; use a prebuilt release tarball for installation.
Try a team
Create a team using the researcher and executor presets. Create an API investigation task, then an implementation task depending on it. Assign the work and check the results. Members must review their children's output. Summarize after all required tasks are complete.
Tools
| Identity | Tools |
|---|---|
| Lead | team_create, team_add_member, team_create_task, team_assign_task, team_delete_member, team_review_output |
| Lead / Member | team_status, team_message, team_update_task, team_inbox |
| Member | subagent_create, subagent_followup |
| Child agent | report |
The team ID is the Lead's root Session ID. Authorization checks the persisted worker identity against its Session parent. Member names cannot be reused. Each member owns at most one nonterminal task.
Task lifecycle
pending → claimed → in_progress → completed | failed | cancelled
- A claimed task may fail or be cancelled, but cannot complete before entering
in_progress. - Only completed dependencies unblock downstream tasks. Dependencies must reference existing tasks, preventing cycles.
- Updates require
task_id,attempt_id, andrevision. OnREVISION_CONFLICT, read the latest task before retrying. - Reassignment creates a new attempt.
STALE_ATTEMPTrejects late writes and queues historical output for review. - The Lead can migrate output to an active attempt using
team_review_output, or explicitly discard it. Migration does not complete the task. - Terminal tasks are immutable. Create a new task to retry terminal work.
Child execution and delivery
Reservations count toward capacity before asynchronous startup. Reserved, running, and stopping workers count; idle members do not. Failed startup releases its reservation after cleanup.
report persists output without marking the child settled. Only runtime settlement releases capacity. The parent cannot complete a task until every child belonging to that attempt has settled.
Deleting a member with active children requires force: true. The plugin cancels pending startup and waits for runtime drain before releasing capacity. Reports arriving during or after deletion are redirected to the Lead.
Messages are stored before wakeup is attempted. If a recipient is offline or capacity-constrained, the message remains in its inbox. Read it with team_inbox and acknowledge processed message IDs.
Configuration
See the complete overlay. Key plugin settings:
memberMaxDepth: 1 # 0 disables nesting; 1 allows one child level
maxChildrenPerMember: 3 # May be reduced, not increased
softLimit: 12
hardLimit: 15
memberPresets:
- id: researcher
persona: 'Investigate facts and provide evidence using read-only tools.'
toolPolicy: read-only
# Optional: defaultProvider, defaultModel, defaultEffort
- id: executor
persona: 'Implement, validate, and review your children’s output.'
toolPolicy: standard
team_add_member accepts provider, model, and reasoning_effort overrides. Omitted values fall back to the preset and then the parent route. Children snapshot the parent's complete route at creation; follow-ups do not inherit later parent changes. Reasoning effort must be supported by the selected model adapter.
Models choose declared preset IDs; they cannot submit arbitrary persona text or tool allow/deny lists. The host can configure additional toolPolicies:
| Policy | Allowed global tools |
|---|---|
read-only |
read, read_image, glob, grep, web_search, web_fetch |
standard |
All read-only tools, plus write, edit, apply_patch, str_replace_editor, bash, pwsh |
Only tools actually registered by the host are exposed. Execution guards also cover later registrations and nested PTC calls. These policies constrain model tool calls; filesystem and shell isolation remain the responsibility of Harness sandbox and permission settings.
Dashboard
The dashboard is a separate, local, read-only page. It shows the task DAG, task states, worker routes, active-agent count, and output awaiting review. Tasks with active children show a waiting indicator. State refreshes from disk every 2 seconds.
From a source checkout after npm run build:
npm run dashboard -- --workspace /absolute/path/to/project --port 3081
Open the token-bearing URL printed in the terminal. The server binds to 127.0.0.1 and has no mutation endpoints. Choose another port if needed; stop with Ctrl+C.
Preview synthetic data without calling a model:
node examples/dashboard-demo.mjs
The demo uses an isolated temporary directory and cleans it up on normal signal-driven exit. Built-in personas, system guidance, and dashboard labels currently use Chinese; persona text is configurable.
Persistence and recovery
<workspace>/.agent-teams/<teamId>/
state.json # Atomic canonical snapshot
members.json # Derived view: members and children
tasks.json # Derived view
attempts.json # Derived view retaining old attempts
mailbox.json # Derived view
.write.lock # Present during a write transaction
Tools and the dashboard read state.json as the source of truth. File locks serialize writes without spanning model startup or network waits. Temporary snapshots are fsynced and atomically renamed, with retries for transient Windows file contention. A failed derived-view refresh does not invalidate a committed operation.
Sessions also receive ignorable plugin:dsh-route/agent-teams/action audit records containing the tool, team ID, revision, and outcome. The disk snapshot retains audit entries, attempts, and mailbox history. Session records correlate calls; they do not replace disk state for recovery.
On restart, workers marked active on disk but absent from the host are marked failed. Their nonterminal member tasks return to pending, and old output remains available for review. Hot reload preserves live reservations and reinstalls tools and route policy. One Harness runtime should own each team; file locking does not provide distributed execution management.
A crash can leave .write.lock behind. On ABANDONED_LOCK, stop all Harness processes using that workspace, remove the exact lock file named in the error, and restart. The plugin never automatically steals locks or deletes history.
Development
| Location | Responsibility |
|---|---|
| src/index.ts | Cordis entry point, scoped tools, lifecycle events, routing |
| src/team.ts | Task state machine, quotas, attempts, messages, reviews |
| src/store.ts | File locking, atomic snapshots, derived views |
| src/config.ts | Settings, member presets, tool policies |
| src/dashboard.ts | Read-only dashboard server |
| test/ | Domain, Harness integration, and HTTP tests |
npm run check runs strict TypeScript checking, 16 tests, and compilation. Tests cover concurrent reservation, rollback, forced deletion, route snapshots, settlement gates, stale-attempt migration, revision races, authorization, dependencies, quotas, delivery failures, and dashboard access controls.
Integration tests use the published DSH AgentLoop, tool service, Session persistence, and spawn provider with a local mock LLM. They verify loading, scoped tool visibility, actual provider/model/effort routing, and child cold resume. Browser rendering has also been checked. No paid model calls were made.
Compatibility and known limitations
The implementation uses rc.5's startActivation() and AgentOptions.reasoningEffort, with a request waterfall restoring disk-backed routes on every turn. Online DSH documentation follows the main branch; this package is tested against its pinned rc.5 types and runtime.
The dependency audit currently reports GHSA-mrhx-c7xc-m3w5 in Zod 4.4.3, pinned by DSH rc.5. This plugin does not replace shared host dependencies. A host upgrade requires another compatibility pass.
Report problems in Issues with DSH/Node.js versions, reproduction steps, and errors with credentials removed.
No comments yet. Be the first to write one.