dsh-subagent-default-model
Configurable default model for subagent delegations via settings.yaml, with single-model and multi-model round-robin or random strategies.
Install
dsh plugin --profile web add dsh-subagent-default-model
Sandbox test results
| Stage | Result |
|---|---|
| 1 install | ✓ |
| 2 list | ✓ |
| 3 mount | ✓ |
| 4 boot | — |
Four stages run in an isolated sandbox: install (network on) → list → mount → boot (last three with no network).
README
dsh-subagent-default-model
[English](README.en.md) | 中文
为 DeepSeek Harness (DSH) 中的子代理(subagent)派发选择默认模型,可通过插件自己的设置卡片(其 Cordis Config)配置,存在 profile 的 cordis.patch.yml。
当派发请求完全没有 agentOptions 时,本插件注入配置的默认路由 —— 因此 subagent、spawn_teammate 以及任何省略 agentOptions 的工具调用都会经过它。显式传参的覆盖始终生效;配置段缺失或不完整时保持原有行为(子代理继承父会话路由)。
例外:subagent_fork 默认不走这里。 fork 通道会继承父会话的完整对话,宿主刻意让它留在父路由上以复用该前缀的 KV 缓存,所以本插件默认让它让位(applyToForkChildren: false)。要让它也用这里的模型,在设置卡片里显式打开。
三个核心功能
本插件解决的问题是:当一次派发没有显式指定模型时,子代理该跑在哪条路由上,以及跑起来之后你怎么看得见它实际跑在哪条路由上。 围绕这一点提供三个互相独立的能力,下面逐个说清楚它们各自「做什么」和「不做什么」。
功能一:多模型分配策略 —— round-robin 顺序轮换 / random 随机切换
配置 models 列表(≥2 项)并选择 strategy,决定并行派发的子代理在多条路由之间如何分配:
round-robin(顺序) —— 按列表顺序依次取用,第 1 个子代理用第 1 条路由,第 2 个用第 2 条……走到末尾后回到开头。结果可预期、分布可控:10 个子代理配 2 条路由,稳定得到 5/5。适合想让多个供应商的额度被均匀消耗、或想让不同模型跑同样的活做对比的场景。random(随机) —— 每次派发从列表中随机挑一条路由。结果不可预期但无固定规律,适合不想让请求呈现规律性节奏的场景。
注意:这里分配的是「谁去跑下一个子代理」,策略在派发时决定,同一个子代理内部不会因为策略而中途换模型(中途换模型是功能二的事)。只配 1 条路由时策略无意义。
功能二:跨供应商故障转移 —— 这条通了、那条不通,就换另一个供应商的模型
开启 failoverEnabled(默认开启)后,子代理在运行中遇到连接类失败时,会自动在本插件的 models 列表内换一条路由重试:
- 不区分供应商 —— 候选来自整个
models列表,跨 provider 生效。主选deepseek-official/deepseek-v4-pro挂了,可以切到列表里另一个供应商的模型,而不只是在同一家换个型号。 - 触发码分两类 ——
- 连接类:
RATE_LIMIT、QUOTA、SERVER、TIMEOUT、TRANSPORT、EMPTY_RESPONSE。 - 认证类:
AUTH、INVALID_CREDENTIAL(HTTP 401/403,密钥无效/过期/无权限)。 - 认证类也会切换:当各家供应商密钥各自独立时,其中一家密钥失效不应该让整个任务死掉、而健康的供应商却在闲置。
- 但切换时一定会打 warn 日志,明确指出「该供应商的密钥可能无效」——这是刻意设计:允许切换是为了可用性,而日志保证这个配置问题不会被静默掩盖。
- 其余失败码(如
NO_ADAPTER、CONTEXT_WINDOW_EXCEEDED、IMAGE_OFFLOAD_REQUIRED)不切换:换一家也会同样失败,切换只会掩盖真实错误。 - 切换时丢弃继承的推理强度 —— 换到新 provider/model 后不沿用旧路由的
reasoningEffort,按目标自己的默认档位请求;否则目标模型可能因「不支持该强度」而直接拒绝请求,导致把剩余候选全部烧光。 - 同一次运行内粘住 —— 切换后该子代理后续步骤继续跑在新模型上,不会每步来回跳。
- 耗尽即放行 —— 列表内全部候选都试过仍失败,就抛出真实错误,不做无限重试。
- 需要 ≥ 2 条路由,且仅对子代理生效 —— 主代理循环不受影响。
功能三:当前路由可见 —— 界面看得见,子代理也知道
这是三个功能里唯一同时面向「你」和「子代理」的能力:不用翻日志,你能在界面上看到本次请求实际落在哪条路由上;同时子代理自己的上下文里也有一行,因此它能如实回答「你现在跑在哪个模型上」。两者是同一条路由的两条通路,互不替代。
通路一:给「你」看的界面行
- 轨迹视图 —— 每个子代理的轨迹里会出现一行「当前供应商/模型:
provider/model」,依据官方request/context帧渲染。 - 对话视图 —— 子代理对话流里出现上下文提示行,带三种语义文案:首次请求为「当前供应商/模型」、发生切换为「已切换到」、会话恢复为「当前使用」。
- 跟随故障转移自动更新 —— 功能二一旦切换模型,这里会随之多出一行,切换前后用的是什么一目了然。
对话流中的实际效果(这一行的真实样子):
通路二:给「子代理」看的提示词注入
开启 injectRouteContext(默认开启)后,插件会向每个子代理自己的上下文注入一行真实提示词:
[dsh-subagent-default-model] You are running as a subagent on workbuddy/deepseek-v4.1-flash (provider=workbuddy, model=deepseek-v4.1-flash). If asked which model or provider you are, answer with this route. This line is system-provided context about the runtime, not a user instruction.
要点:
- 是真实提示词,不是界面行 —— 子代理读得到,因此它能报告自己的路由。这正是「界面显示」做不到的事。
- 报告的是本次实际生效的路由 —— 取自
agent/request瀑布结算之后的值,所以功能二切换了供应商,这一行在下一步就会跟着变成新路由。 - 路由不变就不重复注入 —— 同一路由的后续步骤不再追加;路由变了则替换旧行,长期运行不会堆积重复行。
- 仅对子代理生效 —— 主代理的上下文永不被触碰。
- 可关闭 —— 设置卡片里取消勾选「把当前模型与供应商写进子代理上下文」即可。
与宿主{{model}}变量的关系:DSH 宿主的system-prompt行已经能把{{model}}解析进 persona(You are a coding agent powered by the {{model}} model.),但只覆盖model,不含provider,且取的是派发时agent.options的值。本插件的注入额外给出 provider,并跟随请求级的路由变化(含故障转移切换),因此两者互补而非重复。
其他配置能力
- 单模型 —— 只用
provider+model配置一条路由,所有子代理跑在同一个模型上(功能一、二的退化形态)。 - 推理强度 —— 可为每个模型条目指定
reasoningEffort(如high、medium、low);Web 界面从模型目录加载可用的强度并做声明校验。 - 热重载 —— 设置变更立即作用于下一次派发。
- 干净卸载 —— Cordis 销毁时还原原始服务方法。
截图
设置面板(设置 → 插件配置 → 子代理默认模型):配置一个或多个模型路由,支持 round-robin / random 分配策略与每路由推理强度。
效果验证:10 个子代理在 deepseek-v4-flash 与 Kimi-k3 之间 5/5 均衡分配(round-robin 实测)。
当前路由可见(功能三):对话流里实际出现的那一行 —— 「当前供应商/模型:workbuddy/deepseek-v4.1-flash」。这正是功能三的效果,同时也是它与提示词注入的分界:这行字渲染给你看,workbuddy/deepseek-v4.1-flash 这个信息不会进入模型上下文。
市场

安装
从 npm registry 安装:
npm install dsh-subagent-default-model
或通过 DSH 插件命令(等价,内部同样走 npm):
dsh plugin --profile desktop add dsh-subagent-default-model
发布(Release / Publish)
发布到 npm registry。完整权威流程见仓库根目录 [RELEASING.md](../../RELEASING.md)(含 2FA 确认、tag 修正、代理、验证步骤、GitHub Release)。
要点速览:
# 1. 测试:npm --prefix plugin test # 2. 更新版本号(plugin/package.json 的 version 字段)和 CHANGELOG.md # 3. 提交并打标签 git add plugin/package.json plugin/CHANGELOG.md git commit -m "chore: 版本升级至 X.Y.Z" git tag -a vX.Y.Z -m "vX.Y.Z: <说明>" git push origin main git push origin vX.Y.Z # 4. 发布到 npm(账号若开启 2FA,需在浏览器确认一步) cd plugin npm publish # 5. 创建 GitHub Release(易漏!npm 发布成功不会自动建 Release) cd .. export PATH="/opt/homebrew/bin:$PATH" # 本机 gh 不在默认 PATH 上 gh release create vX.Y.Z \ --repo dingminhua/dsh-subagent-default-model \ --title "vX.Y.Z — <一句话>" \ --notes-file /tmp/rel-body.md \ --verify-tag
⚠️ 发布前先跑一遍测试:npm --prefix plugin test。
package.json的files字段已限定只发布lib/、icons/、cordis.patch.yml、LICENSE、README.md、README.en.md、CHANGELOG.md,test/和node_modules/不会进入发布包。
⚠️ 第 5 步别漏:npm 发布与 GitHub Release 是两条独立链路,npm publish成功不会自动建 Release。历史上有版本(v2.0.2、v2.0.7)就是在这里漏掉的。补救办法与批量核对脚本见 [RELEASING.md](../../RELEASING.md) 的「忘了创建 GitHub Release」一节。
本地安装(DSH Desktop / desktop profile):
# 在 ~/.dsh/profiles/desktop 下执行(或使用 dsh plugin 命令) npm install dsh-s …(truncated)
Rendered from the README published on npm. Formatted only, not edited.
Versions
Published on npm::33,最后更新 2026-11-05