windwhiterain/dsh-subagent-templates ↗★ 1

dsh-subagent-templates

Named subagent templates: each template fixes a starting route — one provider/model pair, or a route pool a route is resolved from per child — an agent preset, and an optional persona, so a delegating agent picks a template by name instead of configuring provider, model, and reasoning effort per call, and a background template child's output is delivered to its parent without a collection call. 适合需要频繁分发子任务、希望通过预设模板简化模型和角色配置的智能体。

Package
dsh-subagent-templates
Compatibility
Unverified
Version
0.1.0
License
MIT
Last updated
Sep 30, 2026

Install

$npx -p @deepseek-ai/dsh dsh plugin --profile web add github:windwhiterain/dsh-subagent-templates

Configuration

- id: subagent-templates
  name: 'dsh-subagent-templates'
  config:
    toolName: subagent        # optional; the model-facing tool name
    maxDepth: 1               # optional; how deep delegation may nest (default 1)
    maxActiveSubagents: 4     # optional; how many children may work at once (default 4)
    templates:                # required; at least one
      - id: medium            # required; lowercase letters, digits, hyphens; the `template` argument
        name: Medium          # required; display name
        description: >-       # required; when to pick this template, in the model's vocabulary
          Executes and explores: reads code, runs commands, and reports what it found.
        provider: command-code-goat   # one route: a registered LLM provider id …
        model: deepseek/deepseek-v4.1-flash  # … and a model that provider serves
        # pool: medium        # … OR the name of a route pool owned by dsh-llm-quota-retry
        preset: personal      # optional; agent preset the child joins (default: the deployment default)
        reasoningEffort: high # optional; the child's starting thinking effort
        maxTokens: 64000      # optional
        persona: You are…     # optional; the child's own persona
        toolFilter:           # optional; the child's narrowed tool set
          deny: [write]

A template fixes only what a child is. It does not say whether a delegation waits; run_in_background on the call does.

One route, or a pool to resolve one from

A template fixes exactly one of:

  • provider + model — one fixed route. Both are required, and neither may be empty.
  • pool — the name of a route pool owned by dsh-llm-quota-retry. The route is resolved per child, right before that child exists, from the pool's ordered routes, skipping the ones whose provider is out of allowance. So two subagents of one template can start on different providers, and a template is how a session says "any of these will do, pick one that works".

Declaring both, or neither, fails the row at activation. A pool template whose service is not mounted, or whose pool that service does not define, fails the delegation with a message naming the template and the pool — a child on the deployment's default model would be a delegation nobody chose.

reasoningEffort on the template is the fallback: a resolved route may bring its own effort, and that one wins for the child. maxTokens, preset, persona, and toolFilter are untouched by the pool.

list_subagent_templates reports which form each template uses, so the model can tell a fixed route from a pool without a second delegation.

The effective template list comes from the profile patch

This package's own cordis.patch.yml is a bundle layer: the host re-reads it on every profile recomposition but never watches it, so an edit there applies at the next recomposition rather than when it is saved. A profile override replaces the whole config object, so the effective list is the last layer that declares one.

The only layers the host watches are the profile's own cordis.patch.yml and $DSH_HOME/cordis.patch.yml. Put your templates in the profile's:

- id: subagent-templates
  name: 'dsh-subagent-templates'
  disabled: false
  config:
    toolName: subagent
    templates:
      - id: medium
        name: Medium
        description: >-
          coding, implement, explore, investigate.
        provider: opencode-go
        model: deepseek-v4.1-flash
        preset: personal
        reasoningEffort: high

An id-targeted override must restate every key the row needs — toolName and templates here, with maxDepth and maxActiveSubagents falling back to their defaults. Saving that file applies the new list without restarting the host, by restarting this row: apply() re-runs and the tools re-register, while live children are untouched (they are root Sessions created through the application root), and a settlement watch or a waiting foreground call keeps working across the restart — both read the Agent registry through that same root context.

A template's provider, model, and reasoningEffort are the child's starting route: they seed its first request, and the child's own model picker can change them afterwards. A pool template's route is chosen the same way, from the pool, and the child's picker can change that too — and once the route it moved to falls outside the pool, dsh-llm-quota-retry stops managing it.

persona gives the child a persona of its own. It is registered as a deployment:persona-prefix section on the child's scope, so it shadows the deployment persona for that one child and is invisible to the parent and to its siblings. A template without one leaves the deployment persona alone.

toolFilter narrows what the child may call, as allow, deny, or both. It is applied as a restrict() on the child's scope, so it intersects with whatever the child's preset already admits and never widens it.

maxDepth

maxDepth bounds how deep delegation may nest, and defaults to 1: a session may delegate, and a child of that delegation may not delegate again. A delegation is refused when it would create a child deeper than the cap, counting a session that has delegated nothing as depth 0, so its child is depth 1. Set it higher, or to provider-managed to state that the bound belongs to the delegation provider — this plugin delegates to ordinary root Sessions and mounts no provider, so it enforces nothing for that value.

A template child carries no parentSession header — that omission is what keeps its model picker — so the Harness cannot answer its depth. The plugin counts it by walking its own mapping store instead. With no storage domain form mounted there is no recorded chain to walk, so the cap cannot be enforced and delegations proceed.

maxActiveSubagents

maxActiveSubagents bounds how many of one session's children may be working at once, and defaults to 4. A child that has finished stops counting, so it frees its slot immediately — the same rule the Harness's own subagent activation pool follows. A child that finished but was never deleted therefore does not block new work; only children still running do.

The cap is per delegating session, not per host: each session gets its own, exactly as each session has its own child names. It reads the same mapping store as maxDepth, so with no storage domain form mounted the count is unanswerable and delegations proceed.

Configuration is validated at activation: an unknown field, a malformed id, a duplicate id, an unusable toolFilter, a maxDepth that is neither a non-negative integer nor provider-managed, or a maxActiveSubagents that is not a positive integer fails the row instead of the first delegation. A background field from an older patch is an unknown field, so it fails the row rather than being ignored.