# Agent Note: 模型选择的 subagent 路由

Status: implemented

[English](2026-08-18-model-selected-subagent-routes.md) | 中文

## 问题

`dsh-tool-subagent` 可以配置子级 `AgentOptions`，两个进程内提供方也已把这些值合并到父 Agent 的 LLM 选择之上。但面向模型的工具不能为某个适合的子任务请求不同的提供方、模型或推理强度。为每条 LLM 路由加载一个名称不同的委派工具会重复 schema，并把每次调用的调度选择变成部署配置。

模型还需要一种有界方式来发现实时提供方和模型自有的推理强度 ID。把 adapter 目录渲染到每一份委派描述中，会让仅供参考且会变化的目录进入 prompt 前缀。

## 决策

只有 Agent 作用域的 `modelSelectionSettings` 实例解析出 Session 策略，且绑定的 subagent 提供方声明 `SubagentCapabilities.agentOptions` 时，`dsh-tool-subagent` 才公开可选的 `provider`、`model` 与 `reasoning_effort` 字段。该策略使用[用户授权的 subagent 模型路由](2026-08-24-user-authorized-subagent-model-routes.zh.md)所拥有的精确用户授权；不存在无限制静态模式。禁用的实例会省略并拒绝面向模型的选择，而配置的 `Config.agentOptions` 仍是部署方所有的默认值。如果 settings 已启用的实例缺少该提供方能力，插件挂载会失败。

提供方与模型共同组成一条路由，必须一起提供。如果配置值、父级值或提供方持有的路由默认值能够提供生效路由，则可以只提供推理强度。静态的 `provider.agentRouteDefaults` 在存在时构成 provider／model 基线；`Config.agentOptions` 与模型参数会在路由相关强度清除之前覆盖它。没有静态默认值的提供方会使用父 Agent 最新记录请求中的兼容字段，首个请求之前由创建选项提供回退，并保留其中配置的输出 token 上限。推理强度 ID 仍由 adapter 所有。只有所选基线的路由不变时才会继承省略的强度；更换提供方或模型但没有指定强度时，会清除下层路由自有的值，使所选模型解析自己的默认值。`AgentOptions` 把结果强度传入子级循环，其请求 header 会记录生效值。可继续描述符会把它与解析后的提供方和模型一同记录，使尚未写入首个请求的子级能以相同选择冷恢复。

显式或配置的提供方、模型或强度会在提供方基线与请求优先级完成后，通过 `ctx.llm.resolveCallConfig()` 解析。具有静态路由默认值的提供方会在请求省略强度时禁止继承父级强度，从而保留所选模型的默认值。LLM 查询负责提供方注册、精确模型元数据、推理强度校验和 adapter 默认值。异步查询完成后、创建子级或后台 job 之前，工具会再次检查取消状态，并确认同一个提供方实例仍处于注册状态，因此 HMR 不会把一个提供方的默认值与另一个提供方的进程组合。既没有面向模型的选择、也没有配置路由字段的调用会保留原有提供方路径，不要求可选 LLM 服务存在。

启用的定义会注册 `list_subagent_models`。无参数调用列出已授权且已注册的提供方；提供 `provider` 时先授权，再调用该适配器的建议性模型目录；同时提供 `provider` 与 `model` 时会先授权精确路由，再解析其推理强度和默认值。因为发现工具使用全局名称，一个工具作用域最多由一个实例启用选择。随附产品组合在 Agent 作用域的主 `subagent` 实例上设置 `modelSelectionSettings: true`，并注册 Host 自有的 `subagent-model-selection` 设置，其中包含默认关闭的显式 `enabled` 开关与 `allowedModels` 列表。Plugins 设置页会原子保存两个字段。设置启用时，新的顶层 Session 会在任何模型请求之前，把路由策略快照记录为 `subagent/model-selection-policy`。子 Session 继承在线父级的策略；恢复的 Session 使用已记录事件，而不是当前设置。因此，设置修改只影响之后组合的顶层 Session。即使缺少可选 LLM 服务，固定发现定义仍保持可用；发现调用和所选路由调用会在该服务出现前失败。发现会列出实时目录与已记录策略的交集，执行器会拒绝策略之外的显式路由。

随附的 `subagent_fork` 实例不会读取模型选择设置，即使进程内 fork 提供方支持 `agentOptions` 也是如此。fork 会继承父级生效的提供方与模型，使复制的对话前缀仍可供提供方侧 KV Cache 复用。更改任一路由组件都会要求新路由重新预填充继承的历史，而这项重算成本可能超过委派任务本身。该限制与发现工具的全局名称无关：分离发现工具的持有权可以让配置生效，却无法保留复用。只有在路由变化仍能保留前缀复用，或调用方可以显式限制并接受重算成本时，才重新考虑 fork 路由选择。

委派定义不会随 adapter 注册和目录变化而改变，因此实时拓扑既不会扩大每个父级请求，也不会使缓存前缀失效。只有调用发现工具时，目录结果才进入 transcript。自定义的上下文继承实例如果启用选择，其描述会警告，更改提供方或模型可能阻止提供方复用继承的对话前缀。

`SubagentCapabilities.agentOptions` 仍是传输事实。如果请求携带这些选项，而提供方声明为 `false`，服务会在调用提供方前拒绝。两个进程内提供方与 DSH SDK 传输声明为 `true`；DSH SDK 会把 provider／model 默认值作为分离且不可变的数据公开给 Consumer 预检，而 `start()` 会为直接调用方与子运行时初始化独立应用同一份 Config 默认值及 maxTokens。ACP、Codex 与 Claude Code 声明为 `false`。工具配置提供 `agentOptions`、静态启用模型选择或让它受 settings 控制时，如果绑定的提供方缺少该能力，也会失败。

## 考虑过的替代方案

**要求静态启用配置部署路由允许列表。** 不采用，因为它会重复实时 LLM 注册表，并要求自定义组合先配置才能使用已经注册的路由。随附的用户自有偏好属于另一项授权决定，由[用户授权的 subagent 模型路由](2026-08-24-user-authorized-subagent-model-routes.zh.md)记录。

**在每一份委派描述中渲染实时 adapter 目录。** 不采用，因为一个提供方可能公布数百个模型，从而扩大每次请求，而且目录变化会改写缓存前缀中的早期定义。按需目录让可变数据留在固定 schema 之外。

**把公布的目录当作允许列表。** 不采用，因为 adapter 目录只提供建议，有些提供方接受任意精确模型 ID。精确解析仍是权威。

**在 subagent 服务中增加发现方法。** 不采用，因为提供方／模型／强度元数据已经属于 `ctx.llm`；新工具只是该现有能力面向模型的 Consumer。

**把发现工具作为独立加载的插件入口导出。** 不采用，因为随附组合总是把发现工具与主委派工具配套加载。在该实例上显式指定持有权，可以避免重复的全局工具名，无需增加 Cordis 配置项或独立生命周期。

**分别配置发现与面向模型的选择。** 不采用，因为发现功能用于向能够选择这些值的同一个模型提供有效的路由与强度 ID。一个开关可以避免工具 schema 公开选择却没有对应发现路径，或公开发现却没有适用的委派路由。

**在随附 fork 工具上启用面向模型的路由选择。** 不随产品提供，因为更改提供方或模型会失去继承前缀的 KV Cache 复用，重新预填充前缀的成本可能高于委派工作本身。只有在路由变化仍能保留复用，或接口能把这项成本显式化并限制住时，才重新考虑该选项。

**使用全局推理强度枚举。** 不采用，因为推理强度 ID 和默认值属于精确的提供方／模型路由。LLM adapter 会直接校验，无需中心化翻译或截断。

**允许远程提供方忽略这些字段。** 不采用，因为请求会声称发生了实际上没有发生的路由选择。能力标记会让不支持的路径在创建子级前失败。

## 结果

- settings 已启用的 Session 只能选择其记录的精确子级 LLM 路由；禁用的 Session 会省略并拒绝面向模型的路由字段。
- 主委派工具实例默认关闭选择，为新 Session 提供 Plugins 页面精确路由 opt-in，并且只在持久策略存在的 Session 中注册 `list_subagent_models`；发现与显式选择都受该策略限制。
- 随附 fork 工具会继承父级的提供方与模型，并省略面向模型的路由字段，使继承的对话前缀仍可供 KV Cache 复用。
- 省略选择时保留配置默认值，并使用静态提供方路由默认值或来自父级最新记录请求的兼容继承；改变路由但不显式指定强度时，使用所选模型的默认值。
- adapter 目录和拓扑变化不会改变委派定义及其 prompt 缓存前缀。
- DSH SDK 子级接受配置和模型选择的 Agent 路由；ACP、Codex 与 Claude Code 在实现并声明该能力前仍会拒绝。
- 单元测试覆盖默认关闭的 Host 偏好、新 Session 读取、子级继承、恢复决定、选择启用时的 schema 与执行强制、合并优先级、路由相关强度继承、预检取消、实时发现、诊断、定义稳定性、能力拒绝与可选服务行为。随附的 headless 快照固定从父级已记录选择继承的行为；随附示例覆盖组装后无密钥、模型可见的 schema，SDK Loader 与快照证据固定完整路由经过独立子运行时的链路。

## 相关决策

本 Note 仅细化子级 LLM 路由。固定的 subagent 传输仍由 [subagent 能力 seam](2026-06-21-subagent-capability-seam.zh.md)负责，而子级作用域提示词与工具增量对 fork 前缀复用产生的独立影响仍由[保留缓存的 fork child 保持 one-shot](../architecture/2026-08-10-fork-children-stay-one-shot.zh.md)负责。
