YixiangTang/dsh-tool-subagent-batch ↗★ 0

dsh-tool-subagent-batch

Rolling-window batch orchestration for DeepSeek Harness subagents with synchronous and asynchronous modes, user-owned concurrency, and per-task acceptance reports.

Package
dsh-tool-subagent-batch
Compatibility
Unverified
Version
0.3.0
License
MIT
Last updated
Oct 30, 2026

Install

$npx -p @deepseek-ai/dsh dsh plugin --profile web add github:YixiangTang/dsh-tool-subagent-batch

Configuration

FieldDefaultMeaning
providerspawnSubagent provider name on ctx.subagents.
toolNamesubagent_batchModel-facing batch tool name.
statusToolNamesubagent_batch_statusModel-facing status tool for async batches.
modesyncDefault mode: sync or async.
concurrencyautoUser-owned window: an integer 1..maxConcurrency, or auto.
maxConcurrency8Ceiling for auto, the environment, and (when enabled) the model.
allowModelConcurrencyfalsefalse hides the model parameter; "lower" lets the model only shrink the window; true lets it choose up to maxConcurrency.
maxTasks32Largest queue one call may carry.
outputCharsPerTask12000Characters of each child answer retained in the report.
maxAsyncBatches8Concurrent async batches allowed per parent session.
retainedBatches16Finished batches kept for later status reads.
maxDepthHost settingAbsolute delegation-depth cap; omit to use subagent.maxDepth (default 1).

Unknown fields are rejected at mount, so a typo fails loudly instead of being silently ignored.

Usage

Sync mode

Ask the main agent for a batch, for example:

I have six independent modules to review. Use subagent_batch in sync mode, at most three at a time, and report each result.

{
  "tasks": [
    { "description": "Review auth module", "prompt": "Review src/auth for ... Report findings only." },
    { "description": "Review billing module", "prompt": "Review src/billing for ..." },
    { "description": "Review search module", "prompt": "Review src/search for ..." }
  ],
  "mode": "sync",
  "fail_fast": false
}

With concurrency: 3 the three children start immediately. With concurrency: 2, the third starts as soon as either of the first two settles. The call returns the complete report.

Async mode

Start the same six reviews in async mode, then let me know when they are done.

The model starts the batch:

{
  "tasks": [
    { "description": "Review auth module", "prompt": "Review src/auth for ..." },
    { "description": "Review billing module", "prompt": "Review src/billing for ..." }
  ],
  "mode": "async"
}

The immediate result is a running snapshot:

{
  "batchId": "batch-1f0c...",
  "mode": "async",
  "status": "running",
  "total": 2,
  "completed": 0,
  "failed": 0,
  "cancelled": 0,
  "skipped": 0,
  "pending": 1,
  "running": 1,
  "concurrency": 3,
  "concurrencySource": "config",
  "startedAt": "2026-10-30T09:41:00.000Z",
  "durationMs": 12,
  "results": [
    { "index": 1, "description": "Review auth module", "status": "running", "childId": "session-...", "output": "", "outputTruncated": false, "durationMs": 12 },
    { "index": 2, "description": "Review billing module", "status": "pending", "output": "", "outputTruncated": false, "durationMs": 0 }
  ]
}

Later, collect it:

{
  "batchId": "batch-1f0c...",
  "wait": true,
  "timeout_ms": 120000
}

subagent_batch_status accepts:

FieldMeaning
batchIdRequired. The id returned by the async start.
waitWait until the batch settles or the timeout expires.
timeout_msWait bound, 1000..600000, default 60000.
cancelCancel the batch and wait for its children to stop.

Only the session that started the batch can read or cancel it. Without wait, the call returns a snapshot immediately; poll it to show progress.

Result

{
  "batchId": "batch-1f0c...",
  "mode": "sync",
  "status": "completed",
  "total": 3,
  "completed": 2,
  "failed": 1,
  "cancelled": 0,
  "skipped": 0,
  "pending": 0,
  "running": 0,
  "concurrency": 3,
  "concurrencySource": "config",
  "startedAt": "2026-10-30T09:41:00.000Z",
  "finishedAt": "2026-10-30T09:41:48.000Z",
  "durationMs": 48210,
  "results": [
    {
      "index": 1,
      "description": "Review auth module",
      "status": "completed",
      "childId": "session-...",
      "stopReason": "completed",
      "output": "Found two issues: ...",
      "outputTruncated": false,
      "durationMs": 22100
    },
    {
      "index": 2,
      "description": "Review billing module",
      "status": "failed",
      "childId": "session-...",
      "stopReason": "error",
      "output": "",
      "outputTruncated": false,
      "durationMs": 900,
      "error": "child stopped with reason \"error\"",
      "diagnostic": "..."
    }
  ]
}

childId is a durable session id. In deployments that mount @deepseek-ai/dsh-tool-subagent-control, the main agent can use send_message to continue a child, for example to ask for a corrected answer, without rerunning the whole batch.

Statuses

Batch status:

StatusMeaning
runningThe pool has not settled; some tasks may be pending or running.
completedEvery task settled (individually completed, failed, or skipped).
cancelledThe batch was cancelled before every task settled.

Task status:

StatusMeaning
pendingQueued, not admitted yet.
runningA child is executing this task.
completedChild stopped with stopReason: "completed".
failedStart rejection, child error, or non-completed stop reason.
cancelledChild stopped because the batch was cancelled.
skippedNever started, because fail_fast fired or the batch was cancelled.