跳到主要内容

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 | 简体中文

npm version GitHub stars

为 subagent 委派做模型路由的 DeepSeek Harness 插件。自带的 subagent 工具只会继承父级模型路由;本插件新增一个姊妹工具,让委派模型在每次调用时自行挑选子代理的 LLM providermodel输出上限(或把选择交给内置的 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 调用:

  1. 确定 provider:显式 provider 参数优先,否则取调用方代理自己的路由(parent.options.provider)。需要 llm 服务。
  2. 任务分档trivial(短任务,≤160 字符且无重标记)、complex(≥1200 字符,或含代码块 / 结构化输出诉求 / 推理动词如 analyze、design、debug、refactor、evaluate),其余为 standard
  3. 默认锚定父模型:调用方代理的 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 与父路由不同时同样丢弃锚点(父模型不再属于该分组)。
  4. 可审计:每次 auto 调用都会在工具结果里记录 auto: { provider, model, tier, reason, anchored?, escalatedFrom?, reroutedFrom?, rerouteReason? },渲染文本带 [auto] 行(保留父模型时带 anchored 标记)与理由 —— 随时可以问「为什么选它」。
  5. 失败恢复(仅前台调用):
    • 瞬态失败升级autoEscalate + autoEscalationTiers):rate-limit / server / timeout / transport / 未分类失败时,用下一档重试(trivial → standard → complex,默认最多 1 次),但仅当该选择严格更强于当前模型时才升级 —— 锚定的强父模型永远不会被降级。重试结果记录 escalatedFrom
    • 终态失败换路autoReroute):quota / auth(配额耗尽 / 凭据失效)重试同一 provider 无意义 —— 直接换到目录里第一个健康的 provider 路由重启(reroutedFrom + rerouteReason)。升级中若撞上终态失败也会停止继续升级该 provider。
  6. 健康感知(死锚检测):插件在会话内记录每个 provider 路由的失败分类。一旦父模型所在路由被判定不健康(quota / auth 为终态、瞬时类 60 秒 TTL),后续 model: "auto" 调用不再锚定该父路由,而是直接改挑健康 provider —— 避免把子代理一直钉在坏路由上。subagent_models 目录工具也会为每个 provider 标注 health: healthy/unhealthy + failingClass + retryAfterSec
  7. 失败详情透传:子代理失败不再只是「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.yamlsubagent-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  # 可选:预算封顶

典型模型流程

  1. subagent_models → 列出 deepseek-official(含其目录)与所有 pi-ai 路由。
  2. subagent_model{ description: "对比定价", prompt: "...", provider: "deepseek-official", model: "deepseek-r1", max_tokens: 4000 } → 子代理在该路由上运行并返回结果。
  3. subagent_model{ description: "say hi", prompt: "hi", provider: "deepseek-official", model: "auto" } → 若调用方自己的模型属于该 provider,则沿用父模型([auto] 行带 anchored 标记);否则回退到目录选型并记录 [auto] ... 及其理由。
  4. 省略 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