dsh-plugin-subagent-roster
Manifest validConstrained subagent roster for DeepSeek Harness: one tool per role, each pinning a child system prompt, a capability allow-list, and a model tier. Bulk work vs team work by tool shape. 子代理名册:按角色约束系统提
dsh-plugin-subagent-roster
A constrained subagent roster for DeepSeek Harness. Every role has a pinned system prompt, a pinned capability range, and a pinned model tier — and bulk work and team work are reached through tools of different shapes.
The problem
DSH's built-in subagent tool gives a child the parent's identity and the parent's whole toolset.
Real delegation therefore fails in three predictable ways:
- Identity leaks — the child carries the parent's persona into a narrow job, and its output shape is whatever the model felt like.
- Capability leaks — you wanted a file read; the child has a shell. You asked for a review; it edited the code.
- Model does not match the job — a 200-item extraction and a load-bearing design decision run on the same (usually most expensive) model.
This plugin turns all three from prompt requests into structural constraints:
| Constraint | Mechanism | Effect |
|---|---|---|
| System prompt | each delegation puts the role persona on the request; it becomes the child's persona-prefix section | identity is decided by the role, never by the parent |
| Capability | the request's toolFilter.allow | a reviewer has no write tool at all — it cannot edit even if asked |
| Model | the request's agentOptions | bulk runs cheap, review runs adequate, team runs strongest |
| Depth | maxDepth: 1 and a filter that never grants subagent* | a role child is a leaf; no recursive fan-out |
Two lines
- Bulk line — one item per call, launched in parallel, children have no tools at all. Field extraction over 20 records, per-item validation, per-item rewriting.
- Team line — planning, building, reviewing, retrieving, assembling. Each role has a different capability range, and no role can stand in for another.
All 20 roles: role reference (中文).
Install
# from GitHub (source is the artifact; no build authorization needed)
dsh plugin --profile <your-profile> add github:<owner>/dsh-plugin-subagent-roster
# or from a local checkout
dsh plugin --profile <your-profile> add /path/to/dsh-plugin-subagent-roster
The bundle applies one plugin row. The parent agent gains one delegate tool whose role enum
is the whole roster, so it pays for one schema instead of twenty. dsh --profile <name> --dump-config should show the subagent-roster row.
Operations page (define your own roles)
While a profile runs, the plugin serves a loopback page:
http://127.0.0.1:4317/
Add or delete roles, change a role's position, temperament, tier or capability range, and edit the persona — the child's system prompt — directly. Saving applies immediately, no restart: the page replaces the delegation tool registration and the routing section, and rolls back to the previous roster if the new one fails to mount.
Roles live in $DSH_HOME/subagent-roster/roles.json, seeded from the shipped twenty on first start.
The file is a normal document: editing it by hand is supported.
- Port is the plugin's
pagePortsetting;0disables the page. - No authentication, bound to
127.0.0.1: it grants the same file authority a local shell already has. Do not expose it on another interface. - Every save is validated as a whole: kebab-case ids, known tier/capability/line values, and role invariants (a reviewer that can write is rejected). A rejected document never overwrites the file.
Deterministic entry point (no "should I delegate?" decision)
Measured: letting the parent model decide whether to delegate is unreliable on free models (see test report §3). So the decision moves to the entry point — drive it by item count:
node bin/roster-fanout.mjs \
--profile <your-profile> \
--role batch-exact \
--items-file items.json \
--contract 'one JSON object {"text": <the item>}' \
--expect-json \
--concurrency 3 \
--out results.jsonl
- N items in, N role-children out — the shape is a property of the invocation, not the model
- Each answer is read from the child's
tool_resultevent, never from the parent's paraphrase --expect-jsonvalidates the contract; a child that errors, returns nothing, or returns invalid JSON fails the item- Non-zero exit when any item failed, so a script or CI job can gate on it
The contract is enforced by
--expect-json, and the contract text is delivered inside the child's task (outside it, the child never sees it). Measured 8/8 compliant on the cheapest bulk-tier model. A failed check is a failed item, never prose passed off as success.
Configure model tiers
Every model id in the composition resolves from the environment, so one package serves several deployments:
| Variable | Purpose |
|---|---|
ROSTER_PROVIDER | provider route shared by all four tiers |
ROSTER_BATCH_MODEL / ROSTER_BUILD_MODEL / ROSTER_REVIEW_MODEL / ROSTER_TEAM_MODEL | model id per tier |
ROSTER_BATCH_MAX_TOKENS and friends | output ceiling per tier |
Any single row can also be overridden by id in a profile's cordis.patch.yml.
Plugin settings
| Field | Default | Meaning |
|---|---|---|
mode | advisory | advisory warns; strict refuses to load a self-contradicting roster |
provider | deepseek-official | provider the tiers resolve against |
allowedModels | [] | when non-empty, any tier resolving outside this list is a violation |
routingGuidance | true | register the bulk-vs-team routing section into the parent prompt |
Verify
npm test # 18 unit tests, zero model calls
node bench/run.mjs --repeat 1 # real runs against a local OpenAI-compatible gateway
Bench verdicts come from the gateway's request log, not from answer text: which persona the child actually ran with, whether its model equals the tier model, whether its tool count equals the role's grant, and whether negative cases really left the workspace untouched.
- Design notes: docs/design.md
- Test report: docs/test-report.md
- Review: docs/review.md
Compatibility
- DSH
>=0.2.0-rc.2 <0.3.0 - Node
>=22.18 - Plain ESM JavaScript artifact, no build step
License
MIT
Comments
Loading…
Similar plugins
File-defined subagent roles for DeepSeek Harness: roles live in project and global .dsh/roles files, a delegating agent sees one catalog line per role, and each role's tool policy decides which tools
★ 1
↓ 828/wk
MIT
JavaScript
dsh plugin --profile web add dsh-plugin-subagent-rolesDeepSeek Harness plugin: on task send, pick a different model for subagents and an independent reviewer that validates each subagent's work before it reaches the main agent
★ 0
MIT
TypeScript
dsh plugin --profile web add dsh-orquestratorby MaRi23333
DeepSeek Harness 具名子代理库插件:settings 驱动的角色名册,list_subagents / delegate 工具与设置页。Named subagent roster plugin for DeepSeek Harness.
★ 6
↓ 614/wk
MIT
JavaScript
Oct 17, 2026
dsh plugin --profile web add dsh-subagent-libraryby bpc-oss
DeepSeek Harness plugin: subagent_routed — run a one-shot subagent fully mounted on ANY agent preset from ANY session, with per-call model/provider override and a model-availability pre-check.
★ 3
MIT
JavaScript
Sep 12, 2026
dsh plugin --profile web add dsh-routed-subagentby xiagaogaozi
Maintains reusable named subagent profiles for DeepSeek Harness and runs them with per-profile model, reasoning effort, and agent-preset settings.
★ 0
TypeScript
Sep 2, 2026
dsh plugin --profile web add dsh-subagent-poolby KouzakiUmi
DeepSeek Harness 插件:按 Agent preset 限制每个 Agent 可见的工具,保留全局 provider 挂载;基于 agent/created 与 ctx.tools.restrict()。
★ 0
MIT
JavaScript
Oct 5, 2026
dsh plugin --profile web add dsh-preset-tool-guard