Preface¶
In DSH, selecting models for sub-agents originally only had three tiers: the static agentOptions of the tool instance, the session-level subagent-model-selection whitelist, and the per-entry configuration of the named subagent library. These three tiers could not express one thing: that you are working in a specific project directory, and the sub-agent should use the model configured for that project. The result is that you have to manually select it every time a task is dispatched, or simply settle for whatever is available.
dsh-subagent-routes is the plugin that fills this gap. It is maintained by zdt3476, with the repository at zdt3476/dsh-subagent-routes, and is categorized under “Model Inference” in the community directory. The plugin performs longest prefix matching based on the workspace directory and injects the matched provider / model / reasoning level into the sub-agent’s agentOptions, providing a visual settings page. Below is an introduction to its capabilities and usage.
What is this¶
One-sentence positioning: A DSH plugin that specifies provider, model, and reasoning level for a sub-agent based on the workspace directory of the parent session when the sub-agent is dispatched.
The pain point it solves is “Project-level routing”. Frontend projects want strong models, long-document research wants to fix the maximum reasoning level, temporary scripts want to use cheap models, and different strategies are needed for different sub-directories within one repository—these cannot be expressed with the existing three-tier configuration. The plugin uses a route table with longest prefix matching to cover these scenarios, while also providing a settings page to avoid manual YAML editing. The category on the community directory page is “Model Inference”, and the repository currently has 1 star, making it a small-scale personal project.
Core Features¶
Routing only applies to newly dispatched sub-agents; it makes no changes to sessions that are already running.
The plugin intervenes at a single point: all entry points for creating sub-agents (subagent, subagent_fork, workflow, agent-team, and delegate from the named subagent library) eventually call ctx.subagents.startActivation, and the plugin only intercepts here. Therefore, it naturally covers all dispatch paths without needing to modify DSH itself.
The processing flow is:
1. Read the current working directory of the parent session (prefer workingDirectory projection, fallback to session header cwd);
2. Perform longest prefix matching in the route table;
3. Merge the matched provider / model / reasoningEffort into request.agentOptions;
4. Call llm.resolveCallConfig() for preflight as needed; fail directly at the dispatch point if the route is invalid.
No session events are written during dispatch, and the profile is not modified; the configuration is only persisted to the current profile via the host configEditor.edit when the user saves the base configuration, followed by validation and plugin reloading.
The settings page provides three-level linkage selection: Provider, Model, and Reasoning Level are all selected from the host’s detected list; there is no need to memorize IDs. Private channels support “manual input”. When no Provider is selected, the Model dropdown lists all models grouped by vendor. The options internally encode provider + model, so models with the same name from different vendors will not overwrite each other. The Reasoning Level follows the actual metadata of the selected model: if the model does not support reasoning, the option is disabled and cleared; if supported, only the specific levels for that model are listed. The reasoning level for manually input unknown model IDs is preserved, and the plugin does not arbitrarily rewrite it.
In project rules, the “Project Root Directory” defaults to picking from the host’s registered workspaces (displayed as “Title — Path”). You can switch to “Manual Input” if ~/... or a finer sub-directory is needed. When editing preferences directly, you can switch to “Raw YAML Mode” in the top right corner. The visual form and YAML sync bidirectionally, and the structure is validated upon saving.
Additionally, there is a status pill (Sub provider / model ▾) in the input area of the session page. Clicking it allows you to temporarily switch the provider / model for the current session locally, used for temporarily boosting or downgrading without changing the rules. The “Sub-agent” tab in the right sidebar retains a form-like appearance closer to the configuration table; both locations share the same priority determination and data layer.
Installation and Enablement¶
The installation command comes from the repository README:
# Install from local directory
dsh plugin --profile desktop add /path/to/dsh-subagent-routes
# Or install from npm (after release)
dsh plugin --profile desktop add @zdt3476/dsh-subagent-routes
Upon first installation or upgrading from an old implementation without a client, you must reload the plugin or restart DSH to ensure the host loads the new client capabilities; simply opening the old settings page will not reload the new entry. If there is still no settings entry after reloading, please restart DSH.
After installation, the settings entry appears at “Plugin Management -> This Plugin -> Settings”. Both the bundle card and the patch plugin row provide an entry. The right sidebar tab and the pill in the input area are registered by the same client artifact; if the “Sub-agent” does not appear in the right sidebar, reload the plugin first, and if it still doesn’t work, restart DSH (Slot registration for client plugins only happens during plugin loading).
Typical Usage¶
It works in three steps, and you don’t need to write YAML manually throughout the process:
1. Open the settings page: Plugin Management -> This Plugin -> Settings.
2. (Optional) Set a global default model: use it as a fallback when no project is matched; leave it empty to inherit the parent session’s model.
3. Add project rules: Click “+ Add Project Rule” -> Select project from the workspace dropdown -> Select model from the model dropdown -> Reasoning level automatically follows the model linkage -> “Confirm Save Rule” -> “Save All Changes” at the bottom.
After saving, it takes effect immediately on the next new dispatch without needing to restart DSH.
You can also write the route table directly. The default location is $DSH_HOME/subagent-routes.yaml (usually ~/.dsh/subagent-routes.yaml), and the visual settings page is its editor:
default:
provider: openai
model: gpt-4.1
reasoningEffort: medium
routes:
- path: ~/Code/frontend-app
provider: anthropic
model: claude-sonnet-4
reasoningEffort: high
- path: ~/Code/frontend-app/legacy # Longer prefix takes priority
provider: deepseek
model: deepseek-chat
- path: ~/Code/research
reasoningEffort: max # Only change level, provider/model inherit from parent session
Field rules: path is required, absolute path or starting with ~, trailing separators will be normalized; provider and model must appear together or be omitted together; reasoningEffort uses the adapter’s own level IDs (low / medium / high / max, etc., depending on the model); at least one of the three must be present.
After changing the route table, it takes effect on the next new dispatch. The file is re-read for every dispatch, so no restart is needed.
Priority Rules¶
From high to low:
Caller Explicitly Specified > Session Choice > Project Rule > Global Fallback > Global Default Policy
Specific behaviors:
- Caller explicitly provided provider + model → The plugin completely defers, not even appending reasoning level (this is the level configured for the workspace model, applying it to another model may not be supported).
- Caller only provided reasoningEffort → The plugin supplements provider / model, preserving its level.
- Session selected “Inherit Main Agent” → Defers directly; project rules and global policies do not intervene.
- Session selected “Specify a Set” → Overrides project rules.
- Session made no selection (interface default state, stored as follow) → Continues to judge according to the above hierarchy.
- Global policy is “Inherit Main Agent” → Defers; does not check the route table.
- Global policy is “Use Route Rules” → Matches project rules by directory; uses global fallback if not hit.
- No content in all layers → The plugin does not inject any fields, and the sub-agent maintains DSH’s native inheritance behavior.
Session-level switching exists in $DSH_HOME/subagent-routes.overrides.json, in the same directory as the route table, written atomically, keeping the last 100 sessions. Note that “Inherit Main Agent” has no provider / model to write to the route table; in this state the “Lock to Project Rule” button will be disabled. When locked to a specific directory, existing entries in that directory will be replaced, not appended as a second one.
Plugin Configuration Items¶
Override by id in the profile’s cordis.patch.yml. Overrides with the same id replace the entire config; three fields must be written out:
- id: subagent-routes
config:
routesFile: ~/.dsh/subagent-routes.yaml
enabled: true
preflight: true
fallbackPolicy: rules
| Field | Default | Description |
|---|---|---|
routesFile |
$DSH_HOME/subagent-routes.yaml |
Route table path; leave empty to use the default location |
enabled |
true |
Route injection switch; when false, injection stops, but the settings entry is still retained |
preflight |
true |
Validate the route using llm.resolveCallConfig before injection; if off, errors are left for the first round of the sub-session |
fallbackPolicy |
rules |
inherit = inherit main agent model when no more specific source; rules = inject according to route table |
These four items correspond respectively to the “Enabled / Paused” switch, the “Global Default Policy” card, and the collapsible “Advanced Options” in the settings page. Click “Save All Changes” at the bottom after making changes; no manual editing of the profile is required. If an unknown value is written for fallbackPolicy, it is processed as rules and kept explainable in the logs.
Suitable Scenarios and Notes¶
Suitable for DSH users who need project-level model routing, especially developers maintaining multiple projects under one profile with differentiated requirements for cost and capability tiers, or scenarios like long-document research that want to fix reasoning levels by directory.
Be clear about a few points when using:
- The plugin only affects newly dispatched tasks; sub-agents currently running will not be re-routed.
- fork also applies, but fork will inherit the parent session’s conversation prefix; changing the model will invalidate the provider-side cache for this prefix, which is an expected cost.
- Prefix matching is purely string-based; it does not do realpath, and symbolic links and .. will not be automatically normalized.
- Workspace and model lists come from the host; if the host does not provide the corresponding service or the profile has not yet registered a workspace, the settings page will automatically fall back to manual input.
- Session specification must provide the model in pairs; specifying only provider or only reasoning level will be rejected.
- When the route table is written incorrectly, the log will provide line-number-level explanations, and this dispatch will continue as “No Route” without blocking work.
It also needs to be noted that the plugin runs with the permissions of the current dsh process; you should check the source code and license before installing. The repository is declared as MIT licensed (see license in package.json), requiring Node ^22.19.0 || >=24.0.0 and DSH >=0.2.1-0.
Conclusion¶
What dsh-subagent-routes does is very narrow: it refines the sub-agent’s model routing from “one global choice” to “one route per workspace directory”. Its value lies in not needing to modify DSH itself, natively covering all dispatch entry points, and providing a visual settings page to reduce maintenance costs. The project currently doesn’t have many stars; the functional boundaries are written in the “Known Boundaries” section; if you have specific behaviors you need, it is recommended to compare before deciding whether to adopt.
Directory page: https://www.skillhub.cn/plugins/zdt3476/dsh-subagent-routes
GitHub: https://github.com/zdt3476/dsh-subagent-routes