# 模型路由

Fallback 優先序、tier 與 dispatcher 模型如何決定由哪個模型回應。

## 模型優先序與 tier

已註冊模型以有序清單存於 `config.json` 的 `models`。此順序即 fallback 優先序：被選中的模型失敗後，其餘項目由上而下依序嘗試——排除 `pass` 模型——最後一筆非 `pass` 項目是最後防線。Fallback 會略過與失敗模型同一供應商的模型、以及 context window 容納不下輸入的模型，整份清單最多重試三輪；session 綁定特定模型時不做 fallback。v1.0.20 之前 `pass` 模型一律被移到最後；v1.0.20 至 v1.0.27 間 fallback 仍會依它在清單中的位置嘗試。`POST /v1/model/priority` 會把列出的名稱依序移到最前面，其餘保持在後。

每個模型可在 `model_tag`（`{"<provider>@<model>": "<tier>"}`）帶一個 tier：

| Tier | 意義 |
|---|---|
| `S` | 最強——需要深度或精確度的程式與工作 |
| `A` | 多數工作的預設，比旗艦低一級 |
| `B` | 主流中階 |
| `C` | 快速便宜；能依指示穩定呼叫工具 |
| `pass` | 自動路由、subagent 與 fallback 永不挑選，即使請求指名也一樣（v1.1.0 起）；僅在 session 指定時使用 |

未設定 tier 的模型依內建命名規則判斷：S = `claude-fable`、`claude-opus`、`gpt-*-astra`；A = `gpt-*-sol`、`grok-4.5+`、`claude-sonnet`、`gpt-*-terra`、`gemini-*-pro`、`deepseek-pro`、`glm`、`kimi`；B = `claude-haiku`、`gpt-*-luna`、`gemini-*-flash`、4.5 以下的 `grok`、`deepseek`；C = `*-mini`、`*-nano`、`gemini-*-flash-lite` 與 open-weight 模型（`gemma*`、`gpt-oss`、`qwen*`、`llama*`）。v1.0.19 將 `gpt-*-sol` 與 `grok-4.5+` 由 S 調降為 A。Tier 每次請求即時讀取，變更不需重啟。

## Dispatcher 模型

Dispatcher LLM 決定由哪個 worker 模型處理任務。它在 `exec.Start` 中經 `ResolveAgent` → `SelectAgentNames` 執行，早於 `Execute()` 進入迭代迴圈，輸入為已註冊模型清單、依解析後 tier 分組的所有模型（先看使用者設定，再套命名規則）、下方的工作類別表、使用者訊息，以及命中 skill 的提示。其路由呼叫以 `ReasoningNone` 發出，timeout 為 30 秒。

無意義時會略過路由：呼叫端明確指定的模型直接使用（未註冊則失敗）；session 綁定 `auto` 以外的模型時使用該模型；registry 只有一個模型時直接回傳。

Dispatcher 第一行回傳工作類別、第二行回傳以逗號分隔的模型名稱（v1.1.0 起），因此 reasoning 為 `auto` 的 session 也能由工作類別決定等級，不需 TypeSafe。第一個已註冊、非 `pass` 且未在冷卻中的名稱成為主要模型。自 v1.0.20 起，清單其餘部分不再決定 fallback——fallback 依上述優先序進行。它把請求歸入下方 TypeSafe 一節表格中的五種工作類別之一，再依該類別的 tier 順序挑選。自 v1.0.21 起，LLM dispatcher、TypeSafe 分類器與 subagent planner 讀取同一張工作類別表（`internal/session/config/tier.go`）與同一套命名規則，排序結果一致；在此之前 LLM dispatcher 不區分 `research` / `work`，code、chat、fetch 以外的請求一律走 S > A > B > C。Dispatcher 被告知永不回傳 `pass` 模型，仍回傳的 `pass` 名稱會被丟棄（v1.1.0 之前請求仍可指名）。同 tier 內，訂閱制供應商 `claude-code`、其次 `codex` 的模型排在所有其他供應商之前。同一基礎模型註冊於多個供應商時，優先 `claude-code`，其次 `codex` / `grok-oauth`，再來 `copilot`、直接 API，最後 `openrouter`。Subagent planner 讀同一張表但降一級（S→A、A→B、B→C），因此 `code` 工作的 leg 依 A > B > C > S 嘗試。Dispatcher 呼叫失敗時，下一個 dispatcher 候選依固定的供應商排名挑選；全部無回應時僅依優先序決定。

在 TUI 以 `/model` → `dispatch`，或以帶 `dispatcher` 欄位的 `POST /v1/model` 設定。
