description: "Role presets and a model pool for dsh: the model delegates to a role, the operator's rules pick the model, and a failure walks the role's chain."
dsh-role-config
English | 中文
A dsh bundle that gives delegation two ways in and one decision layer:
- Role presets. The model delegates to a role (
role: "premium") and never learns which model serves it. Each role carries a description the model reads, a priority chain, and the operator's own routing rules. - Model pool. Models the model may name directly, each with the description the operator wrote for it. A direct route is used as given and never fails over.
- Routing rules. Before a role's chain head serves, its conditions run in order: prompt substrings, a regular expression, required input modalities, a minimum context window, or the operator's own capability tags. Nothing matched and AI routing is on, one bounded router call decides; if it fails, the chain head serves.
- Priority failover. A delegated child whose request fails terminally retries the same request on the next member of its role's chain, and the original failure stands once the chain is exhausted.
- Function bindings. Context compaction and session titles can follow a role instead of the session's route, or keep the harness default.
Install
dsh plugin --profile <profile> add github:snnh/dsh-role-config
The built halves (lib/index.js, lib/client.js, and their declarations) are
committed, so a git install needs no build script and no allowBuilds
permission; install it and enable the bundle. Rebuild them with
npm run build after changing src/.
The one prerequisite
This plugin registers its delegation tool under the official subagent name.
While the plugin is enabled that routed tool is what the agent sees; disable
the plugin and the official tool serves again. Shadowing needs the official
tool one scope further out than the agent, so the official tool-subagent row
must carry modelSelectionSettings: false:
- id: tool-subagent
config:
provider: spawn
toolName: subagent
modelSelectionSettings: false
A profile patch reaches the rows the profile declares. The shipped presets
declare their own, nested inside a cordis:group, and a patch replaces a
row's whole config — so restate the preset row with that one field flipped,
the way the harness's own overlays do. packages/bundle/web-app/presets/standard.patch.yml
lists the shipped plugins; refresh your copy when it changes:
- id: preset-standard
config:
id: standard
order: 1
plugins:
# …the shipped plugin list, unchanged…
- id: delegation
name: cordis:group
group: true
isolate: { workflowEngine: true }
config:
- id: tool-subagent
name: '@deepseek-ai/dsh-tool-subagent'
config:
provider: spawn
toolName: subagent
modelSelectionSettings: false
With model selection on, the official tool registers inside every agent's own
scope, where a same-named tool cannot exist. The plugin then names the row to
fix and leaves the official tool in place, so the session still opens;
delegate.toolName renames this plugin's tool instead, if you would rather
keep the official configuration.
Configuring over a LAN address
Settings documents are confined to a loopback page by default, so a deployment reached at http://<lan-ip>:<port> shows the model pages and every plugin page as unavailable. To configure this plugin from the address you actually use, restate the client-connection row with its operator surface opened:
- id: connection
config:
trustedHosts: !!js ctx.webRuntime.trustedHosts
operatorSurface: trusted
A patch replaces a row's whole config, so keep trustedHosts in the row. The page is served only after the access token is validated and every request it makes still passes the Host/Origin fence and the session check; what changes is that the settings and plugin pages render at all.
Configure
Open Plugins in the Web sidebar and select Role Config. The page edits
one role-config settings section: the pool with its descriptions, the role
presets with their chains and rules, the switches (which surfaces exist,
failover, AI routing), the function bindings, and the delegation wiring.
What the model sees
| Surface | Content | When |
|---|---|---|
list_model_roles |
Role ids with descriptions, and pool routes with descriptions | Only when the model calls it |
| System prompt | The same catalog, compact | Only with exposure.sessionStart |
subagent (role) |
Nothing about the chosen model | Always |
A role's members, rules, and the router's answer never reach the model.
Limits
- A role never fails over for a directly named route, and the main agent's own requests never fail over.
- Agent-team members inherit the lead's route; this plugin can only fail them over, not choose their model.
- Function bindings write the target row's configuration and have no failover of their own.
No comments yet. Be the first to write one.