dsh-subagent-router
已验证dsh-subagent-router · v0.2.0 · MIT · Web 界面
Model-routed subagent delegation for DeepSeek Harness: a `subagent_model` tool with per-call provider/model/max_tokens overrides and a built-in `model: "auto"` routing policy (anchored to the parent's own model by default; task-tier upgrades, failure esca
安装
dsh plugin add dsh-subagent-router 用 dsh --profile default --dump-config 确认 layer 已生效 —— 参见安装指南。
源码
发布到 npm 但没有公开仓库。安装前请检查包内容。
标签
说明文档
dsh-subagent-router
English | 简体中文
为 subagent 委派做模型路由的 DeepSeek Harness 插件。自带的 subagent 工具只会继承父级模型路由;本插件新增一个姊妹工具,让委派模型在每次调用时自行挑选子代理的 LLM provider、model 与 输出上限(或把选择交给内置的 model: "auto" 路由策略)—— 而委派的其他一切(深度核算、委派策略、continuable 后台子代理、结果收集)仍然完全走标准的 ctx.subagents 通道。
工具
| 工具 | 用途 |
|---|---|
subagent_model |
委派任务给子代理,并在本次调用中指定 provider / model / max_tokens。省略的字段继承调用方代理的路由。传 model: "auto" 可把模型选择交给内置自动策略。 |
subagent_models |
只读目录:列出当前 ctx.llm 上注册的 provider 路由(listProviders())及每个 provider 广告的模型列表,并标注每个路由的 health 状态。 |
模型选择如何工作
provider会与ctx.llm上注册的路由(如deepseek-official,或你在 settings 里声明的任意 pi-ai 路由)做硬校验;未知路由立即报错并列出已注册路由。model原样透传。Harness 把模型目录视为「参考性」信息:DeepSeek 适配器接受任意模型 id,而 pi-ai 路由会拒绝未配置的模型 —— 所以模型有效性由 provider 自己裁决,与你自己会话的行为完全一致。subagent_models的存在就是为了让模型能做出有依据的选择。max_tokens限制子代理输出(正整数),透传为agentOptions.maxTokens。- 子代理通过
ctx.subagents.start()/startContinuable()创建,携带agentOptions = { provider, model, maxTokens };harness 的resolveChildAgentOptions会把本次覆盖与父级路由合并,因此省略的字段自动继承。
自动选择(model: "auto")
把模型选择交给一个确定性、可审计的策略 —— 不引入额外 LLM 调用:
- 确定 provider:显式
provider参数优先,否则取调用方代理自己的路由(parent.options.provider)。需要llm服务。 - 任务分档:
trivial(短任务,≤160 字符且无重标记)、complex(≥1200 字符,或含代码块 / 结构化输出诉求 / 推理动词如 analyze、design、debug、refactor、evaluate),其余为standard。 - 默认锚定父模型:调用方代理的 options 在解析出的 provider 上命名了模型时,就用它 ——
trivial/standard任务无条件使用,complex任务在父模型已算强模型(pro/max/reason/think/ultra/code/turbo/large/deep)时也保留。只有两种情况回退到目录打分选型(强信号 +1、廉价信号flash/mini/lite/fast/small/quick/nano/light−1;trivial取最低分、complex取最高分、standard取第一个 0 分):父没有命名模型,或任务是complex且父模型不够强(此时取目录最强模型)。显式provider与父路由不同时同样丢弃锚点(父模型不再属于该分组)。 - 可审计:每次 auto 调用都会在工具结果里记录
auto: { provider, model, tier, reason, anchored?, escalatedFrom?, reroutedFrom?, rerouteReason? },渲染文本带[auto]行(保留父模型时带anchored标记)与理由 —— 随时可以问「为什么选它」。 - 失败恢复(仅前台调用):
- 瞬态失败升级(
autoEscalate+autoEscalationTiers):rate-limit/server/timeout/transport/ 未分类失败时,用下一档重试(trivial → standard → complex,默认最多 1 次),但仅当该选择严格更强于当前模型时才升级 —— 锚定的强父模型永远不会被降级。重试结果记录escalatedFrom。 - 终态失败换路(
autoReroute):quota/auth(配额耗尽 / 凭据失效)重试同一 provider 无意义 —— 直接换到目录里第一个健康的 provider 路由重启(reroutedFrom+rerouteReason)。升级中若撞上终态失败也会停止继续升级该 provider。
- 瞬态失败升级(
- 健康感知(死锚检测):插件在会话内记录每个 provider 路由的失败分类。一旦父模型所在路由被判定不健康(
quota/auth为终态、瞬时类 60 秒 TTL),后续model: "auto"调用不再锚定该父路由,而是直接改挑健康 provider —— 避免把子代理一直钉在坏路由上。subagent_models目录工具也会为每个 provider 标注health: healthy/unhealthy+failingClass+retryAfterSec。 - 失败详情透传:子代理失败不再只是「subagent run failed」——能观测到的失败(
start拒绝、基础设施故障)会被分类(quota / rate-limit / auth / context / server / timeout / transport)并脱敏后拼进工具结果(含 HTTP 状态码与 retry-after),调用方直接看到「provider rate-limited (http 429)」而不是误判成执行失败。
策略刻意保守:默认沿用调用方自己的模型,只有任务明显超出弱父模型能力时才升级,从不隐藏自己的决策理由,并且一旦路由被证实不健康就果断换路而不是盲目重试。
安装
dsh plugin add dsh-subagent-router
bundle 只插入一行组合(subagent-router)。它消费 host 的 tools / subagents / llm 注册表且不发布任何服务,所以属于 host 平面(或 preset 的自由行),不需要 isolate realm。
配置
设置页 UI:插件提供 client half,配置可在 设置 → 插件配置 里直接编辑(subagent-router 卡片)。编辑即时写入用户设置层(~/.dsh/settings.yaml 的 subagent-router 段),无需重启即对下一次 subagent_model 调用生效;清除字段回退到下方组合行配置。
也可以写在组合行的 config 里(作为 base 层,被设置页 user 层覆盖):
| 字段 | 默认 | 含义 |
|---|---|---|
subagentProvider |
spawn |
启动子代理的 ctx.subagents provider。 |
toolName |
subagent_model |
面向模型的委派工具名。 |
modelsToolName |
subagent_models |
面向模型的目录工具名。 |
enableRunInBackground |
true |
是否暴露 run_in_background 参数。 |
backgroundMode |
one-shot |
one-shot 默认前台等待;continuable 默认后台执行、返回持久子代理 id,并要求 provider 具备 prepareContinuable 能力。 |
enableModelList |
true |
是否注册 subagent_models 目录工具。 |
enableAuto |
true |
是否接受委派工具上的 model: "auto"。 |
autoEscalate |
true |
前台运行失败后是否用高一档自动重试一次。 |
autoReroute |
true |
终态失败(quota/auth)时是否换到健康 provider 路由重试。 |
autoEscalationTiers |
1 |
同一 provider 上瞬态失败的最大升级次数(0 表示不升级)。 |
autoProviderOrder |
— | provider 优先级:model: "auto" 按此顺序解析 provider(未列出的排在之后);父路由不健康或缺失时用它兜底。不配则用注册表顺序。 |
autoTierPolicy |
— | 每档选型模式:`{ trivial |
autoTierPicks |
— | 每档显式候选序:`{ trivial |
autoCeiling |
— | 预算封顶:model: "auto" 永不超过该模型强度(命名分更高时截断到它)。不在目录时忽略。 |
maxDepth |
3 |
子代理深度上限;'provider-managed' 表示不设上限(数值上限要求 provider 具备 depthLimit 能力)。 |
示例行:
- id: subagent-router
name: 'dsh-subagent-router'
config:
subagentProvider: spawn
toolName: subagent_model
backgroundMode: one-shot
带模型路由优先级的示例(按你自己的供应商偏好配置):
- id: subagent-router
name: 'dsh-subagent-router'
config:
autoProviderOrder: [deepseek-official, pi-ai-cn] # 供应商优先级
autoTierPolicy:
trivial: cheapest # 琐碎任务永远用最便宜的
standard: anchor # 普通任务跟随父模型
complex: strongest # 重任务用最强模型
autoTierPicks:
complex: [deepseek-v4-pro, pi-3-maxi] # 可选:重任务显式候选序
autoCeiling: deepseek-v4-pro # 可选:预算封顶
典型模型流程
subagent_models→ 列出deepseek-official(含其目录)与所有 pi-ai 路由。subagent_model传{ description: "对比定价", prompt: "...", provider: "deepseek-official", model: "deepseek-r1", max_tokens: 4000 }→ 子代理在该路由上运行并返回结果。subagent_model传{ description: "say hi", prompt: "hi", provider: "deepseek-official", model: "auto" }→ 若调用方自己的模型属于该 provider,则沿用父模型([auto]行带anchored标记);否则回退到目录选型并记录[auto] ...及其理由。- 省略
provider/model即让子代理沿用你自己的路由。
开发
pnpm install
pnpm test # vitest:schema 形态、路由校验、agentOptions 透传、目录工具、auto 策略与升级、健康换路
pnpm run build # tsc -> lib/
测试套件在真实的 ToolRuntime + SubagentRuntime 上驱动真实插件体,使用脚本化子代理 provider 与伪造的 llm 路由注册表;不触网、不用凭据。
路线图
自动路由策略的后续计划(目录元数据、推荐工具、反馈闭环、预算上限):见 docs/ROADMAP.md。交接见 HANDOFF.md,发布记录见 PUBLISHING.md。
License
MIT