🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

子代理调度 vitas/dsh-jev-subagent-dispatch

DeepSeek Harness
vitas29 天前有提交已提供中文文档扫描:含敏感能力

降低 LLM 成本:常规任务交给便宜的子代理模型,主模型专注难啃的部分。

29.7/100
综合分
1
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/10/13 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add vitas/dsh-jev-subagent-dispatch
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:待复验
是什么
dsh 原生插件 · model
装得上吗
曾在 dsh 0.2.0-rc.2 下真实安装成功,但当前 dsh 已更新至 0.2.1-rc.5,本站尚未在新版下复验
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 29 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

读写/删除本地文件发起外部网络请求
查看扫描证据(共 5 处,展示前 5 条)
  • 写入本地文件
    index.mjs:173
    await mkdir(logDir, { recursive: true });
  • 写入本地文件
    index.mjs:174
    await appendFile(join(logDir, "verdicts.ndjson"), `${JSON.stringify(record)}\n`, "utf8");
  • 读取本地文件
    bin/jev-replay.mjs:28
    const records = (await readFile(logPath, "utf8"))
  • 读取本地文件
    bin/jev-replay.mjs:32
    const candidateInput = overridesPath === undefined ? {} : JSON.parse(await readFile(overridesPath, "utf8"));
  • 发起网络请求
    jev.mjs:116
    const response = await fetch(buildRequestUrl(config), {
扫描于 2026/11/1(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

依赖的 DSH / Cordis 模块
@deepseek-ai/schemastery@deepseek-ai/dsh-llm
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 任务路由至子代理
  • 降低主模型开销

省 LLM 成本:把日常任务路由给便宜的子代理模型(DeepSeek Harness 插件)

README

由 DeepSeek 最新模型翻译生成
dsh-jev-subagent-dispatch 降低 LLM 成本:常规任务交给便宜的子代理模型,主模型专注难啃的部分。 这是给 DeepSeek Harness 用的 Jev 引导式子代理调度插件:插件向 Jev(TypeSafe 的类型化决策模型)问几个关于任务的原子问题,套用你的路由策略,然后追加一条调度建议:该由哪条子代理模型路由接手这一轮。分工是刻意安排的——Jev 负责引导,主智能体通过 harness 原生的子代理工具完成交接;插件本身不拥有任何委派机制。 Jev 不写代码,也不是聊天 LLM。它回答类型化问题(choice / score / noul),给出概率和置信度,一次并行完成,耗时几十毫秒。所以它是理想的引导者:昂贵的主智能体不用再花 token 去判断该由谁来做这件事。 [jev-subagent-dispatch] 之于你的智能体,就像团队 leader 之于开发者:它花 200 ms 读一遍工单,决定要不要交给初级工程师——而且绝不让初级工程师碰生产环境。 注入的是建议,不是强制:主智能体自行权衡,也可以忽略。在日常工作中信任它之前,先衡量建议的质量(见衡量影响)。 一览 Subagent 插件必须处于启用状态。
展开完整文档(README 剩余 1 节)
dsh-jev-subagent-dispatch

降低 LLM 成本:常规任务交给便宜的子代理模型,主模型专注难啃的部分。

这是给 DeepSeek Harness 用的 Jev 引导式子代理调度插件:插件向 Jev(TypeSafe 的类型化决策模型)问几个关于任务的原子问题,套用你的路由策略,然后追加一条调度建议:该由哪条子代理模型路由接手这一轮。分工是刻意安排的——Jev 负责引导,主智能体通过 harness 原生的子代理工具完成交接;插件本身不拥有任何委派机制。

Jev 不写代码,也不是聊天 LLM。它回答类型化问题(choice / score / noul),给出概率和置信度,一次并行完成,耗时几十毫秒。所以它是理想的引导者:昂贵的主智能体不用再花 token 去判断该由谁来做这件事。

[jev-subagent-dispatch] 之于你的智能体,就像团队 leader 之于开发者:它花 200 ms 读一遍工单,决定要不要交给初级工程师——而且绝不让初级工程师碰生产环境。

注入的是建议,不是强制:主智能体自行权衡,也可以忽略。在日常工作中信任它之前,先衡量建议的质量(见衡量影响)。

一览

Subagent 插件必须处于启用状态。 委派不是这个插件能提供的东西:DSH 分别组合子代理服务、它背后的子服务商,以及 subagent 工具,而这个包刻意不依赖其中任何一个——它在请求时重新检查,当插件缺失能从设置里看出来时,卡片会提醒你。插件关掉后,判定照样产生,只是没有地方可送。

它的路由必须指向你的会话允许列表放行的模型。 允许列表禁止的路由照样参与分类,于是判定看起来一切正常,调度却根本不可能。卡片消除了这个陷阱:每个角色一个下拉选择,只列出允许列表里的模型。

| Jev 的任务类别 | 接手的角色 | 出厂路由 | 是否委派 |
| mechanical —— 重命名、重新格式化、注释、样板代码 | junior | openrouter/qwen3.8-flash | 是 |
| bugfix | implementer | openrouter/deepseek-v4-flash | 是 |
| research | researcher | openrouter/qwen3.8-flash | 是 |
| review —— 对已有工作给出第二意见 | reviewer | openrouter/qwen3.8-flash | 是 |
| refactor、feature_work、meta_chat | — | — | 否 —— 不在 profiles..delegate.taskClass 里,所以永远到不了路由 |

是否委派一列是出厂的 auto 配置档。更严格的 careful 配置档只委派 mechanical,而谓词的上限(工作量、影响范围、每个问题的概率)可以拦下任何类别,不管它对应哪个角色。
每个角色只能选一个模型,可选范围由你的子代理允许列表决定

角色给执行者命名,类别给工作命名。routeFor 把类别映射到角色,routes 把角色映射到模型,所以你可以新增角色,或者把已有角色指向别的模型,而不用动评分规则。junior 之所以存在,是因为 mechanical 和 bugfix 虽然一起被委派出去,却不是同一类活——重命名有明确的规格,修 bug 得先找到原因——这个角色适合指向你最便宜的模型。reviewer 和其他角色一样,默认走同一个示例网关,因为有哪些模型可用是你自己的组合该管的事,不是这个插件该管的:这个角色对配置者的唯一要求,就是它必须指向和你的实现者不同的模型——让写下改动的模型自己给意见,或者让它的孪生兄弟给意见,价值都不大。所有内置路由都是占位符,你在卡片里选一次就能替换掉;没有配置的路由会大声报错,并指出是哪个角色。

下面全是这些事实背后的细节;失败模式见派发能力是前提。

派发能力是前提

对派发插件来说,在还不知道智能体能不能委派之前就调用 Jev,只会浪费这次调用。DSH 需要三样东西才能委派——子代理服务、它背后的子服务商、以及智能体可见的委派工具——并且深度上限为 0 会彻底禁用委派。安装这个插件并不代表这些条件已经满足,所以每次路由请求都会在请求时对着运行中的宿主服务重新核验能力(绝不依赖包依赖,也绝不用启动时的快照):

- 委派工具(subagent / subagent_fork)对当前智能体可见;
- 子代理服务存在,且可见工具背后的服务商已注册;
- 智能体还有剩余委派深度(用 session.header.delegationDepth 对比生效的深度上限——服务商管理的上限在本地总会留有余量);
- 会话的模型选择策略(subagentModelSelectionPolicy 投影):模型选择关闭时,子代理工具不接受模型参数,建议里也不提任何模型——此时套用会话配置的子默认值;开启时,只有会话允许列表包含某个已配置路由,才会点名它,否则消息会引导智能体去看 list_subagent_models;
- 是哪个工具,以及它的服务商:fork 是固定路由,不管工具叫什么名字都一样——对 subagent_fork 和带 provider: fork 的自定义命名工具,建议都渲染成「fork 会继承你的模型和上下文」。模型名永远只是建议,前提是可见工具能照做。

| 情况 | 显式 /route 请求 | 普通回合(auto) |
| 能力检查通过 | classify → inject recommendation | classify → inject recommendation |
| 能力检查失败 | 注入一条诊断信息,说明缺了什么;不调用 Jev | 完全静默 —— 不注入、不调用、不写日志 |
| Jev 调用本身失败(超时、密钥被拒、HTTP 错误) | 注入一行诊断信息,说明失败原因;本轮继续,不做路由 | 完全静默 —— 本轮继续,不做路由 |

对会话或插件设置的改动,在下一个请求生效 —— 启动时不会缓存任何东西。

设置卡片带的是同一套检查的更轻量、更早的版本:它读取 Subagent 插件自己的设置命名空间,加载器只在这一行被组装并启用时才提供该命名空间,一旦消失就显示警告。这样能抓住一个否则你只能拿到结论却无处可去的场景 —— 配置档里插件从未启用。它只是探针,不是权威:只有上面那个请求时的检查才能看到会话的工具可见性,所以命名空间缺失会警告,而深度受限或工具被禁用的会话仍会通过诊断信息自我报告。

模式:Jev 在你要求时运行,而不是每轮都跑

默认是 off —— 不注册任何东西,不共享任何东西。三种激活模型,从最省开始:

| 模式 | 工作方式 | 取舍 |
| off(默认) | 完全没有前置步骤监听器。 | 零成本、零数据共享;想获得价值就得配置更多。 |
| once | 只有明确要求的轮次才分类:/route fix the failing tests 调用 Jev 一次;其他每一轮都原样通过。 | 成本和数据共享可预测,但你得记得开口。 |
| auto | 每个普通用户轮次都会被考虑(原始行为)。 | 无需用户费力,但只有在结论日志显示这些建议确实值回票价时才启用。 |

触发语法(可通过 triggers 配置):

/route fix the failing tests → one Jev call, a routing recommendation
/jev should I delegate this? → free-form decision request to the rubric
/route preview rename everything → evaluation-only verdict (see below)

请求可以点名要做的决策:触发词之后的文本会作为状态发给 Jev(/jev which specialist? 变成一条决策请求,由带类型的评分标准通过自己的词汇表来回答)。这让 Jev 成为智能体可以复用的小型决策服务,而路由策略只是它的一个具体用法。
预览 — /route preview <task> 会分类并注入一条仅供评估的判定:完整答案,包括分数分布(blast_radius distribution: trivial 0.20, …),这样风险策略就能对照真实数据来调;还会明确写上「不要据此委派」,并在判定日志里打上 trigger: preview 标记。漏判也会渲染出来:策略拒绝的判定会注入 verdict: skip — <reason> 及其答案,因为被跳过的那些案例,恰恰是你用别的方式看不到的。用这种方式收集真实样本,对照实际结果读一遍,再允许自动委派。

路线图,按证据能支撑的顺序排列:一个由智能体调用的 route_task 工具(主智能体不确定时就问——对话里很自然,但它仍要花一步来决定调用),以及选择性自动(先跑便宜的本地规则,只对路线仍不明确的轮次用 Jev——需要收集数据来调触发条件)。

一轮对话如何流转

user message ──▶ agent/pre-step waterfall
│
├─ downstream listeners (memory plugins, …) run first │ └─ jev-subagent-dispatch (prepended, sees the final batch) ├─ mode gate: off → never; once → only /route, /jev turns ├─ capability gate: delegation tool + provider + depth ├─ build state: redacted turn + explicit request, capped ├─ POST {provider endpoint}{apiPath} (6 atomic questions, one call) ├─ apply profile policy (predicate + confidence gates) ├─ log verdict to NDJSON (opt-in) └─ "delegate" verdict? append a routing recommendation ▼ main agent spawns the recommended subagent (harness-native tool)

处处 fail-open:缺 key、超时、429,或配置损坏,都会记下原因,这一轮照常继续,不做路由。插件只在有把握时才注入;否则保持沉默。

隐私

发给 TypeSafe 的状态刻意做到最小,而且离开本机之前就已脱敏:

- 用户的轮次文本,加一行 workspace: —— 不含 diff、不含工具输出、不含文件内容;
- 任务文本排在状态最前面,工作区路径作为有界上下文跟在后面(≤ 120 字符)—— 整个拼装好的载荷都会脱敏(路径要过与任务文本相同的凭据过滤器),并整体截断到 stateChars(默认 1200),所以任何路径长度都无法泄露、无法超限,也无法把任务挤出去;
- 形似凭据的子串(sk-…、ghp_…、github_pat_…、AKIA…、Bearer …、api_key=…、长 base64 token)由内置模式替换为 [redacted];redactPatterns 可添加你自己的正则源;
- 日志是可选开启的(logDir),只有 logTurnText 为 true 时,用户这一轮的文字才会写进日志——你要校准的是判定结果本身(分类、分数、概率、路由、用量)。

把任务文本发给 TypeSafe 正是这个插件的意义所在;如果某个仓库不能接受这一点,就给它设 enabled: false。

评分标准(判定什么)

questions 配置与 TypeSafe 文档里的请求结构完全一致——以 question id 为键的 map,每一项带 type、instructions 和 criteria——所以配置里写什么,发出去的就是什么。一次请求里放六个原子问题;增加问题不会增加延迟:

| 问题 | 类型 | 判定标准 |
| task_class | choice(option → description 的 map) | mechanical · bugfix · feature_work · refactor · research · meta_chat |
| effort | score(有序 level 数组) | S (0) · M (1) · L (2) · XL (3) |
| blast_radius | score(有序 level 数组) | trivial (0) · module (1) · cross_module (2) · public_api (3) · infra (4) |
| needs_repo_context | noul | 任务跨多个仓库模块的概率 |
| user_explicit | noul | 用户要求主智能体亲自处理的概率 |
| risky | noul | 任务涉及密钥、迁移、基础设施、破坏性操作的 概率 |

Choice 答案给出选中的选项名(choice),以及每个选项的概率。Score 答案是在 levels 谱上的数值位置(0..n-1),可以落在两个 level 之间——1.4 表示「介于 M 和 L 之间」——并给出每个 level 的概率。Noul 答案是单个 0..1 的概率。

策略(怎么决策)

activeProfile: auto
profiles:
auto:
confidenceMin: 0.7
delegate:
taskClass: [mechanical, bugfix, research]
effortMax: 1.5 # up to "between M and L"
blastRadiusMax: 1.5 # up to "between module and cross_module"
maxNoul:
needs_repo_context: 0.5
user_explicit: 0.3
risky: 0.2
cap the probability of a severe level, not only the average score;
levels are rubric names (structured criteria entries are addressed
by index), "name+" sums that level and everything worse; an
incomplete score distribution fails the gate closed
probabilityMax:
blast_radius: { "public_api+": 0.15, infra: 0.05 }
routeFor: # task class → role that takes it
mechanical: junior # roles name the worker; the class keeps its own name
bugfix: implementer
research: researcher
review: reviewer
routes: # role → the model that role runs on
junior: { provider: openrouter, model: qwen3.8-flash }
implementer: { provider: openrouter, model: deepseek-v4-flash }
researcher: { provider: openrouter, model: qwen3.8-flash }
reviewer: { provider: openrouter, model: qwen3.8-flash }
只有当以下条件全部成立时,才建议委派:对答案的声明式谓词(score ≤ ceiling,因此边界值通过;缺失答案按失败处理),以及主置信度高于配置档下限。内置两个配置档:auto 乐于委派;careful(置信度 0.85,effort ≤ 0.5,blast radius ≤ 0.5)适用于错误委派代价高昂的仓库。系数在配置里调,不要写进提示词。如果你更想按超出*某档位的概率来把关,而不是按数值分数,那就从 score 答案里读 probabilities —— 日志会逐轮记录它们。

routes 与 Settings → Subagent → "Models agents may choose" 里的允许列表保持一致 —— 插件本身不掌管任何委派机制;由 harness 原生的 subagent 工具按推荐的 provider/model 启动。

服务商:你的 Jev 访问权限在哪里

密钥的签发方决定端点、API 路径、凭据变量和固定模型 id。上层共用同一套问题格式和路由策略;provider 预设只替换通信地址和模型:

| 密钥来自 | provider | Jev 端点 | 固定模型 | 密钥环境变量 |
| B.AI | bai | https://api.b.ai/v1/decisions | jev-1.13.0 | OPENROUTER_API_KEY |
| OpenRouter | openrouter | https://openrouter.ai/api/v1/systemone | jev-1.13 | OPENROUTER_API_KEY |
| TypeSafe | typesafe(默认) | https://api.typesafe.ai/v1/systemone | jev-1.13.0 | TYPESAFE_API_KEY |

B.AI 的 Decisions API 和 OpenRouter 的 System One API 都返回同一形状的类型化 Jev 答案;无论用哪个服务商,插件发送的评分标准相同,应用的策略也相同。行配置里显式写出的 endpoint、apiPath、apiKeyEnv 或 model 会覆盖预设 —— 所以自建或走代理的 Jev 端点只需要这四个字符串。如果你的密钥来自 B.AI,设置 provider: bai 就完事了。继承来的值在卡片里留空,卡片会把预设值显示为该字段的占位符 —— 留空意味着「从预设取值」,而不是「未设置」。

安装

dsh plugin --profile web add /path/to/dsh-jev-subagent-dispatch # local checkout
or, once published:
dsh plugin --profile web add dsh-jev-subagent-dispatch

宿主侧用 harness 自带的 @deepseek-ai/dsh-llm 构建注入消息。它声明为可选 peer,并通过运行中宿主的入口点解析,所以 link: 的开发检出 —— 自身没有 node_modules —— 行为与安装副本完全一致。
然后让签发者的密钥以预设期望的名字可用(B.AI 用 OPENROUTER_API_KEY,TypeSafe 直连用 TYPESAFE_API_KEY)。插件在每次调用之前解析这个名字,先查凭据存储,再查进程环境——所以常见情况下什么都不用做,因为 Models 页面已经把密钥存在这个名字下了。环境变量也行,但只有为运行 dsh web 的那个进程设置才有效。配置档。在 once 模式下,你不发送触发之前,不会发送或分类任何东西。

无密钥的接线测试

在插件行配置里设置 mock: true。mock 分类器根据关键词作答,按文档中的答案结构给出固定的 0.9 置信度,这样你就能端到端看到注入、日志和阈值。它不分类任何东西——真正路由时把它关掉。

设置

插件自己的配置页面:每个字段都实时编辑配置

两个界面,一个事实来源。插件在 Plugins 下的自己的页面(DSH 0.1.7+,表单内联渲染在包页面上;该行的 Configure 控件打开同一个表单)——或者 0.1.5 上的 Plugins 设置标签页——实时编辑顶层字段:模式、服务商预设、决策配置档、触发器、路由、日志目录与轮次文本开关、状态上限,以及分类器端点组——改动无需重启宿主即可在下一轮生效,被拒绝的值会保留上一个可用配置。路由放在这里,因为它是唯一会悄悄失败的嵌套字段:路由指定的模型若被你的 Subagent 允许列表禁止,仍然会分类,于是判定看起来健康,却无处可派发。卡片从 subagent-model-selection-settings 命名空间读取那个允许列表——那是另一个插件的命名空间,通过 configForms.get 绑定,框架正是为此提供了文档——并把它的模型按角色各提供一个下拉选择,这样就不会犯这个错。该命名空间未提供服务的地方,原始的 role=provider/model 字段照旧返回。配置档补丁仍是基础层,承载卡片刻意不伪造的一切:配置档阈值(effortMax、noulMax、probabilityMax)、routeFor、自定义 questions、delegationTools。

卡片在右下角打印它构建时所用的版本。浏览器标签页会保留它加载的 bundle,重启宿主不会重新加载它——所以如果你刚安装的控件不见了,先看那一行:完全没有版本行,说明标签页运行的是它存在之前的构建,重新加载即可修复。
所有设置都放在插件行的 config 里。bundle 补丁自带文档中写明的默认值;在你的配置档 cordis.patch.yml 里按 id 覆盖同一行即可(那里的改动是卡片所依托的基础层)。合并规则:questions 和 routes 按 key 合并(覆盖其中一项,其余保留);profiles 深度合并(改一个阈值,保留判定条件);其余项遵循普通深度合并规则。

| Key | Default | Meaning |
| mode | off | 激活方式:off(不生效)、once(仅显式触发)、auto(每轮都触发) |
| triggers | ["/route", "/jev"] | 前导命令,在 once 模式下标记该轮需要分类 |
| provider | typesafe | 适用哪套 Jev 签发方预设:typesafe、bai、openrouter |
| endpoint | per preset | TypeSafe API 基址——代理端点时覆盖此项 |
| apiPath | per preset | 追加到 endpoint 的路径(/v1/systemone、/v1/decisions 等) |
| apiKeyEnv | per preset | 每次调用解析 Bearer key 所用的名称:优先取 Models 页面写入的凭据存储中的凭据,否则取环境变量 |
| model | per preset | 固定的 System One 模型——阈值按版本校准;不要用 jev-latest |
| timeoutMs | 4000 | 分类预算;超时则该轮不路由直接继续(实测一次实时决策耗时 1517 ms) |
| stateChars | 1200 | 由用户轮次构建的脱敏状态的开头长度上限 |
| redactPatterns | [] | 除内置凭据模式外,额外从状态和日志文本中脱敏的正则源 |
| mock | false | 仅用于接线测试的关键词分类器 |
| questions | see bundle patch | TypeSafe 请求格式中的原子评分表 |
| activeProfile | auto | 适用哪个配置档的策略 |
| profiles | auto, careful | { confidenceMin, delegate } 判定条件 |
| routeFor | class → role | 任务类别映射到哪个具名路由 |
| defaultRoute | implementer | 类别没有映射时的回退角色 |
| routes | junior, implementer, researcher | role → { provider, model };与你的 Subagent 允许列表保持一致。卡片为每个角色显示一个下拉选择,选项限于该允许列表许可的模型;没有该命名空间时回退为逗号分隔的 role=provider/model,清空输入框则恢复随包提供的三项 |
| skipSubagentSessions | true | 只路由主智能体的轮次 |
| logDir | null | NDJSON 判定结果输出目录;null 或 "" 关闭日志;设置目录路径即启用 |
| logTurnText | false | 日志开启时,在日志中包含(脱敏后的)轮次文本 |
| includeFallbackLine | true | 添加「子代理不可用时自行继续」这一行 |
| delegationTools | subagent, subagent_fork | 能力门探测的 { toolName, provider } 对;配置了自定义 toolName 的预设必须在此列出,否则派发会报告自身不可用 |

可观测性与重新校准

设置 logDir 后,每条判定——delegate、skip 或 error——都会追加一行 NDJSON:

{"at":"2026-09-27T20:41:03.114Z","action":"delegate","reason":"predicate holds",
"confidence":0.94,"role":"implementer","route":{"provider":"openrouter","model":"deepseek-v4-flash"},
"model":"jev-1.13.0","usage":{"input_tokens":360,"output_tokens":39},"latencyMs":180,"answers":{…}}

重新校准的循环:委派之后测试失败,或者工作需要返工,那就是一次路由失误——调高 confidenceMin,或者对出问题的类别收紧判定条件;日志显示机械性回合被路由到主模型,那就放宽。

衡量效果

每条推荐都要花一次分类调用;它得靠证据挣来自己的位置,而不是靠信念。判定日志加上 usage,就给了你所需的输入:

- 判定率——以 delegate 判定收尾的回合占比。每条记录都带 id 和 delivered 标记(推荐是否真的注入——缺少消息工厂会让判定无法投递);
- 延迟与成本——每条判定的 latencyMs 和 usage.input_tokens,对比机械性回合省下的主模型 token;
- 返工——统计路由过的回合与未路由的回合之后,测试失败和重新委派的次数(把 enabled 关掉,取一段可对比的基线期)。

如果这些差值撑不起多出来的那次调用,就收紧策略,让它触发得更少——安静的路由器才是好路由器。

对差距要诚实:今天的日志衡量的是策略判定与投递,不是采纳——它看不到主智能体是否真的派生了子代理、跑的是哪个模型、工作有没有重做。下一步是闭环的路由账本:把每条判定的 id 与实际子代理调用、耗时、返工关联起来,再按任务类别报告跟进率和节省的时间。先观察;依据这些证据重新调整阈值,而不是凭直觉。

离线重放策略变更

评估候选策略不需要更多 Jev 调用——判定日志已经存下了每一组答案。重放会在本地对记录的答案重新判定,展示哪些会翻转,并按任务类别和原因分组:

npx jev-replay ~/.dsh/verdicts/verdicts.ndjson candidate.json
candidate.json — plugin-input overrides, e.g. { "profiles": { "auto": { "delegate": { "effortMax": 1, "probabilityMax": { "blast_radius": { "public_api+": 0.1 } } } } } }

[jev-subagent-dispatch] replay: 42 judged, 35 unchanged, 7 would flip
flips by task class:
5 research
2 mechanical
flips by reason:
7 effort 1.4 > effortMax
仅路由变更单独计数:把某个任务类别映射到另一个角色的候选,会报告 N route-only 次翻转,并按每条路由给出 from → to 明细,与 delegate↔skip 翻转分开统计。旧日志里没有路由字段的记录,一律不计为路由变更。加上 --json 可输出机器可读结果。回放让决策始终可复核:提交阈值改动之前,你能清楚看到它会让哪些历史轮次发生翻转。规划中的路由账本(把判定 id 与实际子调用、返工关联起来)还会让回放把策略改动与观测到的结果做对比。

测试

npm run check # lint (node --check over every .mjs) + unit tests

测试套件覆盖 TypeSafe 线上契约(questions 是以 id 为键的映射,含 type/instructions/criteria;有文档记录的答案归一化,包括小数分数)、分数边界情况(正好等于上限通过,超过则失败)、声明式谓词、脱敏、配置合并,以及带假上下文的宿主集成路径(注册、注入、fail-open、跳过规则、可选日志)。测试不会发出真实 TypeSafe 请求;用真实密钥发出的第一个真实请求,是剩下的集成检查。

注意事项

- 输入英文,输出置信度。 Jev 主要用英文训练;请对简短的英文意图陈述做分类,不要直接喂非英文原文,并依赖置信度门控。
- 固定模型。 jev-latest 会变,阈值不会。响应里的 model 字段会随每条判定一起记录,漂移一目了然。
- 状态卫生。 状态就是脱敏后的用户轮次加上工作区路径——见隐私。risky 门控之所以存在,是因为路由器很容易被骗。
- 价格。 只计输入 token($42/Btok,输出免费):状态 1.2k、六个问题的轮次,在每月数千万轮次的量级下只花不到一美分。

兼容性

纯 ESM,无运行时 npm 依赖;@deepseek-ai/dsh-llm peer 从宿主解析。如果 peer 不可达(裸检出),插件会跳过注入,而不是在 DSH 的消息契约之外伪造一条消息。可选的 @deepseek-ai/schemastery peer(≥3.18.1)支撑设置 schema;没有它时,配置档补丁仍是唯一配置来源。Node ≥ 22。针对 DSH 0.1.5、0.1.7 和 0.2.0(web 配置档)开发并测试——设置界面由服务注入决定,绝不靠版本检查。

许可证

MIT
预览分享卡片长什么样 ↓vitas/dsh-jev-subagent-dispatch
分享 · DeepSeek Harness Hub
vitas/dsh-jev-subagent-dispatch

降低 LLM 成本:常规任务交给便宜的子代理模型,主模型专注难啃的部分。

回到顶部