高级Provider阅读约 15 分钟最后核对 2026-09-30

自动路由

Spark Work 自动路由(AutoRouter)完整指南:一个 router = 1 个分流器模型 + N 个按强度(high / balanced / low)配置的执行模型,宿主在轮次级把 provider 与 model 换成选中档位的执行模型。覆盖真实落库形态(provider_profiles 的 provider_type = auto-router)、AutoRouterConfig 全字段与默认值、分流决策的强制 JSON schema、强度粘性与最近两轮消息摘要、五类降级阶段(timeout / http / schema / rule / no_executor)、规则兜底分类器的判定顺序、确定性 4xx 不重试与 429 保留一次重试、引擎不匹配回退,以及界面上的路由决策展示与排查表。

自动路由(AutoRouter)解决的是一个很具体的问题:你不该为了「翻译一句话」去启动最强的模型,也不该为了「重构整个模块」省那点 token。 它的做法是给会话配一个分流器模型,让它每一轮先看一眼这轮任务有多难,然后把这轮直接交给对应强度档位的执行模型去跑——不是让执行模型自己去调用工具,而是宿主在轮次开始前就把 provider 和 model 换掉了。

这一页讲清楚四件事:AutoRouter 在数据里是什么、一个 router 由哪些配置组成、一轮任务是怎么被分流的、分流失败时会怎么降级。字段名、默认值、错误后缀都来自应用仓库的真实代码。

先记住这四句话

  • 一个 router = 1 个分流器 + N 个执行模型,执行模型按 high / balanced / low 三档配置。
  • 分流是轮次级替换:宿主在跑这一轮之前把 provider/model 换成选中的执行模型,执行模型本身不需要知道 AutoRouter 的存在。
  • 分流失败从不抛错中断,一律降级(超时 → 规则兜底 → 兜底强度),本轮照常执行。
  • 确定性错误(鉴权、权限、模型不存在、请求非法)不重试,避免白付一次调用。

自动路由:一个 router 由 1 个分流器与 N 个按强度分档的执行模型组成

1. 它在数据里是什么

AutoRouter 不是一个虚拟的伪 Provider。每个 router 就是 provider_profiles 表里一行真实记录,provider_type = 'auto-router',config_json 存的就是下面的 AutoRouterConfig。

早期实现用过 claude-auto-router / codex-auto-router 两个魔法 provider id,已于 2026-09 重构下线。代码里保留这两个常量只为识别存量会话引用并回退默认渠道,不会再用于新建任何行。

项值
落库位置provider_profiles,provider_type = 'auto-router'
配置字段config_json = AutoRouterConfig(kind: 'auto-router',version: 1)
绑定引擎adapter: 'claude' | 'codex'——claude 走 anthropic 系渠道,codex 走 openai 系渠道
强度枚举high / balanced / low(ROUTER_INTENSITIES)
界面入口渠道管理 → 工具栏「自动路由」(创建与管理:分流器 + 强度分级执行模型)

2. 一个 router 由什么组成

interface AutoRouterConfig {
  kind: 'auto-router'
  version: 1
  adapter: 'claude' | 'codex'
  dispatcher: { providerProfileId: string; modelId: string; timeoutMs: number }
  executors: Array<{
    id: string
    providerProfileId: string
    modelId: string
    intensity: 'high' | 'balanced' | 'low'
    enabled: boolean
    reasoningEffort?: 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max' | null
  }>
  fallbackIntensity: 'high' | 'balanced' | 'low'
  allowDecomposition: boolean
  maxConcurrentSubtasks: number
  subagentIntensityMapping: boolean
}
字段默认值说明
dispatcher.timeoutMs30000分流决策超时上限,最大 120000。它是故障兜底而非正常耗时:分流器快返回时不会产生等待,只有真超时才等满然后走规则降级
executors[]每条含渠道 + 模型 + 强度档位;同一强度可以配多条,取第一个有效条目。条目的 enabled 关掉即不参与候选
executors[].reasoningEffortnull(跟随会话)这是模型的思考深度,与条目的任务强度档位是两件不同的事。显式配置后,经该执行器执行的轮次以它为准,覆盖会话与 Agent 级配置
fallbackIntensity'balanced'分流失败时的兜底强度
allowDecompositiontrue是否允许分流器把这轮拆成子任务
maxConcurrentSubtasks3(范围 1–10)子任务并发上限,仍受会话每轮派发预算约束
subagentIntensityMappingtrue把强度档位映射注入引擎子代理环境变量,仅 claude 引擎生效,让 SDK 原生 Task 子代理也按强度分级

分流器怎么选:它只做轻量分类,所以优先选快且便宜的非思考模型。如果选了带思考时间的模型,请按实际思考耗时放宽 timeoutMs(例如 60s),否则会频繁走到规则兜底。

执行模型怎么选:三档各自独立选渠道与模型,例如 high 给最强模型、balanced 给主力模型、low 给最快最便宜的模型。每条还能单独指定推理强度,让「档位」和「思考深度」正交组合。

3. 一轮任务是怎么被分流的

自动路由一轮分流时序,以及分流失败时的降级阶梯

用户发消息
  → 加载 router 配置,筛出 enabled 的执行模型
  → 调用分流器 LLM(带上当轮消息 + 会话事件数 + 估算 token + 最近两轮用户消息摘要)
  → zod 严格解析决策 JSON
  → 强度粘性判定(上轮同强度且执行器未变 → 沿用,避免来回横跳)
  → 选中该强度的执行器,宿主替换本轮 provider / model
  → 落一条 auto_router_decision 事件,轮次开始执行

分流器的输出有强制 schema,不是自由文本:

{
  intensity: 'high' | 'balanced' | 'low',
  decompose: boolean,            // 默认 false
  subtasks: Array<{ summary: string; intensity: ...; parallelizable: boolean }>,  // 最多 10 条
  reason: string,                // 最多 300 字符
}

三个值得注意的实现细节:

  • 最近两轮用户消息摘要会被一并送进分流器,专门用来解决「继续」这类消息的误判——单看「继续」两个字只能判成低强度。
  • 强度粘性:如果这轮的决策强度与上轮相同且执行器没换,会命中 keptPrevIntensity,避免相邻轮次在档位间反复横跳、导致模型频繁切换。
  • 轮次取消可中断分流:分流期间如果这一轮被取消,会中止分流的 HTTP 请求并标记 cancelled,不会留下挂着的请求。

你在界面上能看到什么

分流结果会落成 auto_router_decision 事件并持久化,所以重进会话或换设备都还在,展示有两种形态:

形态出现条件内容
轮次边界提示条仅当本轮实际模型与上一轮不同时渲染⚙ 已路由 → ●高强度 <模型名> · <分流理由>;降级或引擎回退时图标换成 ⚠,文案变成「分流降级」/「引擎不匹配回退」
轮次 meta 行小标识每轮常驻强度色点 + 模型名
悬浮提示悬停提示条路由器名、本轮强度、上轮强度、是否兜底、兜底落在哪个阶段

输入框上方的模型悬浮卡也会把 router 展开成「分流器 + 各档执行模型」的行列表,并显示引擎标签与错误信息——不用打开设置页就能确认这个 router 现在派给谁。

4. 分流失败时发生什么

核心约定:分流环节的任何失败都不抛异常、不中断本轮。 所有异常路径都收敛成 fallbackStage 五个值之一,再由兜底强度选执行器把这一轮跑完。

fallbackStage触发原因行为
timeout分流调用超时或请求被 abort走规则兜底分类器
http分流调用返回错误走规则兜底分类器
schema返回内容不是合法 JSON / 不满足 schema走规则兜底分类器
rule规则兜底路径本身(含引擎不匹配回退)用规则或 fallbackIntensity 选执行器
no_executor筛选后一个可用执行器都没有ok: false,本轮无法执行

规则兜底是怎么判的

规则分类器只在分流 LLM 失败时使用,逻辑是「token 阈值 + 收敛正则」:

  1. 估算 token > 30_000 → 直接 high;
  2. 命中低强度正则(好的 / ok / 可以 / 继续 / go on / continue 这类整句、翻译、错别字、改个名、格式化、总结一句)→ low;
  3. 命中高强度正则(重构、架构、设计…方案/系统/实现、多文件/多模块/多步、全链路、排查…问题/故障/根因、性能优化/调优、implement / refactor / architect / redesign)→ high;
  4. 都不命中 → balanced。

顺序很重要:token 阈值在正则之前判定,所以一条很长的「总结一句」消息仍然会被判成 high。规则兜底只是降级路径,不是主逻辑。

重试策略

分流调用失败后最多重试一次,且区分错误类型:

  • 确定性 4xx(鉴权失败、权限不足、模型不存在、请求非法)→ 立即收口,不再重试。重试必然同样失败,只会白付一次调用。
  • 429 → 保留那次重试。代码注释说明了取舍:套餐权限类 429 重试确实是白费,但通用上无法与瞬时限流区分,所以按「可能瞬时限流」处理。

引擎不匹配(adapterMismatch)

如果 router.adapter 与会话当前引擎不一致(例如 router 声明 claude,会话在 codex 引擎跑),不会报错:宿主按兜底强度找一个匹配会话引擎的渠道,找不到就回退默认渠道,并把 adapterMismatch: true 标记出来,界面上显示为「引擎不匹配回退」而不是「已路由」。这样存量会话换引擎后不会突然跑不动。

一个执行器都没有

如果筛完可用执行器为空,本轮会直接报错并给出可操作文案:

自动路由「<router 名>」没有可用执行模型:<原因>。请在渠道管理 → 自动路由中检查配置

5. 在界面里怎么配

  1. 打开渠道管理,点工具栏上的「自动路由」入口,打开管理弹窗。
  2. 左侧是 router 列表,右侧是编辑表单。首次进入恢复上次选中的 router。
  3. 配分流器模型:选渠道 + 模型,按需调整「决策超时 (ms)」。旁边有**「测试分流器」按钮,会对当前草稿**(无需先保存)发一个最小请求并显示延迟。
  4. 配执行模型(按强度):每行是一个档位条目,选渠道、模型、推理强度(留空 = 跟随会话),可「添加执行模型」多配几条。
  5. 配兜底强度:分流失败时用哪一档。
  6. 按需打开高级项:子任务拆分与并发上限、子代理档位映射。
  7. 保存后,在会话的模型选择器里选中这个 router 即可生效。

渠道管理页的卡片网格里,AutoRouter 会以独立类别出现。它的编辑入口是自动路由弹层,不是普通渠道编辑面板——后者会把 provider_type 改掉,留下脏数据。

速查表

项目内容
落库provider_profiles(provider_type = 'auto-router')+ config_json
组件构成1 个分流器 + N 个执行模型(按 high/balanced/low)
强度枚举high、balanced、low
分流器超时默认30000 ms(上限 120000)
兜底强度默认balanced
子任务并发默认3(范围 1–10)
决策 schema 强制项intensity;可选 decompose、subtasks(≤10)、reason(≤300 字符)
降级阶段timeout / http / schema / rule / no_executor
重试次数最多一次;确定性 4xx 立即收口,429 保留一次
规则兜底优先级token > 30000 → high;低强度正则 → low;高强度正则 → high;否则 balanced
决策事件auto_router_decision(持久化,重进会话仍可见)
无执行器时的行为抛错并提示到渠道管理 → 自动路由检查配置

排查表

现象原因怎么办
每轮都显示「分流降级」分流器调用超时或返回不合法 JSON放宽 timeoutMs、换更快的分流器模型
提示条显示「引擎不匹配回退」router.adapter 与会话引擎不一致按会话引擎重建 router,或确认这是预期回退
本轮直接报「没有可用执行模型」筛完可用执行器为空补全条目渠道/模型,或启用被关掉的条目
简单任务被判成高强度消息很长(token > 30000)优先于低强度正则拆短消息,或接受这一档
相邻轮次模型来回横跳分流器对同类任务给出不同强度强度粘性只在同强度且执行器未变时生效;可减少档位差异
子代理没按强度分级subagentIntensityMapping 关闭,或引擎不是 claude打开该开关,并确认会话在 claude 引擎上
改了配置但当前轮没变化分流是轮次级替换等下一轮;必要时重发消息
分流器测不通渠道凭据/端点问题在「测试分流器」里看错误原文,先回渠道设置修凭据
重进会话看不到路由记录了该轮不是经 AutoRouter 跑的只有经 router 的轮次才有 auto_router_decision 事件
旧会话切换到新引擎后跑不动存量会话仍引用已下线的魔法 provider id代码会自动回退默认渠道;建议把会话模型改到新建的 router

常见问题

分流器会不会拖慢每一轮?

会有一点点额外延迟,但不占用执行模型的额度。想压缩这点延迟,就把 timeoutMs 收紧、并把分流器换成快模型——注意别换成带思考的模型,否则会频繁超时走规则兜底。

为什么这一轮用的模型和我选的不一样?

因为会话选中的是 router 而不是具体模型,本轮 provider/model 被宿主替换成了分流结果对应的执行模型。轮次边界提示条会写明「已路由 → 具体模型」,悬浮提示里有分流器的判断理由。

为什么界面上写「分流降级」而不是「已路由」?

说明分流环节失败了,本轮走的是规则兜底或兜底强度。悬浮提示会给出具体阶段(timeout / http / schema / rule)。如果这个前缀频繁出现,通常是分流器渠道不稳定或 timeoutMs 太紧。

执行模型的"推理强度"和"任务强度档位"是一回事吗?

不是。档位(intensity)决定派给哪个模型,推理强度(reasoningEffort)决定该模型的思考深度。两者正交:你可以让 low 档的执行模型也开高推理强度。

为什么改了 router 配置,正在跑的会话没变?

分流是轮次级的。已开始的轮次不会被改写,下一轮才会用新配置。

报「没有可用执行模型」怎么办?

检查三件事:执行模型条目是否都补全了渠道与模型、条目的 enabled 是否被关掉、adapter 与会话引擎是否匹配。任意一档都没有可用条目时本轮会直接失败。

分流器和执行模型可以用同一个模型吗?

可以,但基本没有收益。分流的价值在于「用便宜模型做分类、把贵模型留给难任务」;如果分流器和执行模型是同一个,你等于每轮多付一次调用,却没有拿到任何成本优化。

为什么同一档配了多条执行模型,实际只用其中一条?

同一强度允许多条,但取的是第一个有效条目(enabled 为真的第一条)。想让另一条生效,就把排在前面那条关掉,或者调整条目顺序。