Foreword¶
In agent development, you often encounter batches of heterogeneous tasks: one is mental arithmetic of 17×23, another requires writing code and verifying primes, and a third is long-form translation. Sending all of them to the same model results in simple tasks queuing up on flagship models, wasting time and tokens; handing difficult tasks to cheap models often leads to errors. Manually selecting models for each task is unmanageable as the number of tasks grows.
dsh-swarm-router solves this problem: it organizes a batch of heterogeneous tasks into a “sub-agent matrix swarm” — tasks are rows, candidate models are columns, the router selects a cell for each row, and then uses DSH’s ctx.subagents to turn each cell into an in-process sub-agent bound to the selected model for parallel distribution.
What is it¶
dsh-swarm-router is a DSH plugin maintained by GitHub user r600a-code, version 0.2.0, under the MIT license. A one-sentence positioning: route every task to the most suitable model (OpenRouter-like gateway + cfgpu.com/llm/square directory) and parallelly distribute them via in-process sub-agents (or direct ctx.llm calls) bound to the selected model.
Within DSH’s “everything is a plugin” system, it is packaged as a dsh.bundle manifest: dsh.bundle.patch in package.json points to ./cordis.patch.yml. The patch adds two independent LLM routes, cfgpu-swarm and openrouter, rather than modifying the original cfgpu configuration of the machine, so the swarm’s model directory does not interfere with the orchestrator’s own models.
How the Router Selects Models¶
The task structure is { id, kind, prompt, maxTokens? }, where kind ∈ {reasoning, coding, longcontext, fast, general}. The routing is a pure function, O(1) per task — it spends no model time to decide “which model to use,” and the saved overhead is fully invested in parallel distribution. Model selection consists of five steps:
-
Infer
kind: Explicitly providedkindtakes priority; otherwise, take the first non-empty prompt in the order{reasoning, coding, longContext, fast}; if none exist, classify asgeneral. -
Capability hard filtering (capability gate): Models lacking capability tags are directly marked as -∞ and eliminated.
reasoningrequires areasoningtag,codingrequirescoding,longcontextrequireslongContext;fastandgeneralhave no thresholds. -
Weighted scoring by task type: For surviving models, calculate a linear score using the 1-10 rating (strength, speed, cost) and capacity (contextWindow, maxTokens) from the directory:
| kind | Scoring Formula |
|---|---|
reasoning |
reasoning×3 + strength×2 + coding×0.3 + contextWindow×0.000004 |
coding |
coding×3 + strength×2.5 + longContext×0.3 |
longcontext |
contextWindow×0.00002 + strength×0.5 + coding×0.3 |
fast |
speed×3 + cost×1.5 + strength×0.3 |
general |
strength×2 + speed×0.6 + cost×0.3 + coding×0.3 |
-
Asymmetric penalties: If
kindis notfastbut the model belongs to the fast tier, -2.0; if ageneraltask hits a reasoning flagship, -2.0 (overkill, slower and more expensive); if acodingtask hits a reasoning model, -0.5; models with unstable routing during directory collection (unstable), -4; unavailable models (e.g., OpenRouter without a configured key), -1000. WhenuseRankings: trueis enabled, rank feedback is added: success rate ≥ 0.9 and trial count ≥ 3 adds +1.5, success rate ≤ 0.4 subtracts -3.0. -
Select the best and explain: The highest scorer wins; if tied, compare
strengthfirst, then lexicographically byid. The tool returns the winner, as well as the scores of the top 5 candidates and readable reasons for the choice.
These numbers are asymmetric and intentional: rewarding cheap models on quality-oriented tasks is exactly the failure mode this design aims to avoid. The fast penalty and reasoning overkill penalty (each -2.0) are large enough to flip ties but small enough to allow truly strong cheap models to still win on general based on merit; the magnitude of rank bonuses (+1.5 / -3.0) is smaller than static penalties, meaning a model must first achieve real good performance before feedback becomes eligible to override directory ratings.
Core Capabilities¶
-
Model aggregation registry + PR process:
models/registry.jsonis the canonical directory;scripts/validate-registry.mjsvalidates the structure and can be directly integrated into CI;CONTRIBUTING.mdrecords the PR process for adding new models. -
Plugin extension points: Plugins expose the API via
ctx.provide('swarmRouter', api). Other plugins declareinject: ['swarmRouter']to register runtime models, custom task types, subscribe to feedback events, and read rankings and usage. -
Real task feedback and ranking:
swarm_feedbackrecords{correct, quality 1-5}and persists torankings.json;swarm_rankingshows success rates and quality scores by model and task type. Models with good empirical performance are weighted in routing, while those with poor performance are down-weighted — static directory ratings are just the author’s estimates; real task results will override them. -
Token consumption statistics: In
directmode, it precisely captures the prompt/completion/total of each call from theusageblock ofctx.llm.stream(includingreasoning_tokensfromcfgpuif the adapter outputs it); insubagentmode, it captures via a globalllm/streamlistener and attributes the data to specific sub-agents based onsessionId == sub-run id. Data is persisted tousage.json, andswarm_statsdisplays summaries, details by provider, by model, and by task type, accompanied bycfgpuHighlighthighlighting.
Tool Overview¶
| Tool | Mode | Calls Model |
|---|---|---|
swarm_route_preview |
— | No, pure routing preview |
swarm_dispatch |
subagent (default) | direct |
Yes, parallel calls |
swarm_models |
— | No, list registry |
swarm_feedback |
— | No, record one result |
swarm_ranking |
— | No, read cumulative feedback |
swarm_stats |
— | No, read cumulative usage |
“Decision” and “Execution” are separated: first use swarm_route_preview to see the complete routing plan without spending a token, then confirm and use swarm_dispatch for actual distribution. The subagent mode follows the full agent loop; the direct mode is a one-time ctx.llm.stream call, suitable for scenarios requiring precise token accounting.
Installation and Activation¶
By default, it installs to DSH_HOME (default ~/.dsh, which must already contain cfgpu credentials):
dsh plugin --profile headless add github:r600a-code/dsh-swarm-router
To verify installation, check if cfgpu-swarm and swarm-router appear in the configuration:
dsh --profile headless --dump-config | grep -E 'cfgpu-swarm|swarm-router'
If you want isolation from ~/.dsh, you can first prepare a workspace-level DSH_HOME, containing .credentials.yaml and settings.yaml with CFGPU_API_KEY, and install from the local path:
export DSH_HOME=/path/to/.dsh-home
dsh plugin --profile headless add /path/to/dsh-swarm-router
Credential requirements: The cfgpu route requires CFGPU_API_KEY in $DSH_HOME/.credentials.yaml (or environment variable); the OpenRouter route requires OPENROUTER_API_KEY. If missing, the router will report it as unavailable and will never distribute to it, though the profile can still start normally. Additionally, package.json’s peerDependencies declares five @deepseek-ai/* packages (cordis, dsh-tools, dsh-agent, dsh-llm, dsh-subagent), all of which are required.
Typical Usage: Running the Built-in Benchmark¶
benchmark/benchmark.json is the minimal benchmark set: 5 cheap, heterogeneous tasks covering fast/reasoning/coding/general. Success is determined by content (expected answer substring / CJK), not just completion.
subagent mode, 5 tasks:
dsh --profile headless "$(cat benchmark/benchmark_prompt.txt)"
node benchmark/verify_benchmark.mjs # 27/27 green
direct mode, 3 tasks:
dsh --profile headless "$(cat benchmark/benchmark_direct_prompt.txt)"
node benchmark/verify_benchmark.mjs benchmark_direct_RESULT.json # 31/31 green
Results recorded in the README: in subagent mode, 5 tasks are routed to 4 different real cfgpu models and all are correct (17×23=391, bat-ball=0.05, real is_prime, CJK translation, widgets=5); in direct mode, 3 tasks precisely capture token consumption per task. When a batch of tasks is spread across multiple models, distinctModels aggregation is the signal that “routing is working” rather than converging to a single model.
Applicable Scenarios and Notes¶
Suitable for three types of people: DSH users who frequently have batches of tasks with large difficulty differences and want to match models by difficulty; teams wanting to accumulate real task feedback and make the routing more accurate with use; and other plugin developers wanting to reuse the registry and rankings. For design details, there is a formal design document docs/PAPER.zh.md in the repository.
Notes before use:
-
The plugin runs with the permissions of the current dsh process; please check the source code and license (MIT) yourself before installing.
-
The
cfgpuroute cannot work withoutCFGPU_API_KEY; put credentials in$DSH_HOMEbefore installing. TheOpenRouterroute missing a key will only make that route unavailable, not affecting startup. -
Benchmark numbers are based on the repository README: subagent validates 27/27, direct validates 31/31.
Conclusion¶
The philosophy of dsh-swarm-router can be summarized in three steps: make “selecting a model” a zero-cost pure function, hand “execution” to parallelly distributed sub-agents, and then use real task feedback to correct static directory ratings into your own rankings. For DSH users who frequently run heterogeneous task batches, this is a ready-to-use routing solution.
- GitHub repository: https://github.com/r600a-code/dsh-swarm-router
- Community directory page: https://www.skillhub.cn/plugins/r600a-code/dsh-swarm-router