# Multi-source routing strategy Quota Router deliberately separates two questions that should not be conflated. ## 1. Which resource should be tried first? This is the global **source priority** question: ```text priority 1 opencode-go subscription priority 2 token-share free priority 3 starchasing paid (protected by default) priority 4 deepseek paid/manual policy ``` The answer belongs in `sources[].priority`. Lower number wins. A tier is a user policy label for cost/risk communication; it is not a price lookup, a balance check, or a hidden ordering rule. ## 2. Which model should this task use once a source is reached? This is the **task model decomposition** question. It belongs in `profiles[].modelBySource`. ```text opencode-go token-share coding mimo-v2.5 gpt-5.6-luna hard-coding mimo-v2.5 gpt-5.6-terra planning deepseek-v4-flash/high gpt-5.6-luna writing deepseek-v4-flash gpt-5.6-luna deep-thinking — gpt-5.6-terra ``` These dimensions are orthogonal: ```text user message ↓ first matching profile profile identity + global source order ↓ expand each source's model mapping candidate chain ↓ native validation / cooldown filtering current request route ``` ## Why not one global fallback? `coding` and `hard-coding` can deliberately share the same cheap primary: ```text coding: opencode-go/mimo-v2.5 → token-share/gpt-5.6-luna hard-coding: opencode-go/mimo-v2.5 → token-share/gpt-5.6-terra ``` If a router only remembers the current provider/model, these two cases are indistinguishable after they both select `opencode-go/mimo-v2.5`. Quota Router stores the profile identity and candidate position per DSH turn, so a quota failure advances each task to its own intended fallback. ## Recommended policies ### Save existing quota first Use automatic sources in a conservative order: ```text free → subscription → unlimited/quota → protected paid ``` Keep `allowPaidFallback: false` until you consciously want automatic spend. You can still keep paid source mappings in profiles for visibility and later opt-in. ### Give difficult tasks a stronger second hop Do not make every task use the same fallback. For example: ```text simple → gpt-5.4-mini coding → gpt-5.6-luna hard-coding → gpt-5.6-terra ``` The source remains shared; task quality is chosen per source. ### Put specific profiles before broad profiles Profile matching is first-match. Example: ```text hard-coding keywords: deadlock, concurrency, performance coding keywords: bug, fix, code ``` Keep `hard-coding` above `coding`, otherwise a broad `bug` profile may shadow a more specific one. ### Tune transient tolerance to the source The default threshold of `2` permits one normal DSH retry before a route is cooled. Increase it when a source has short harmless blips; decrease it when repeated errors usually indicate a real provider outage. Cooldown prevents every new turn from retrying the same failing route. ### Keep manual and emergency routes out of automatic chains Use `tier: manual` or `tier: emergency` for a route that should remain configured/visible but must not be chosen automatically. This plugin does not manage credentials or manually apply a provider; use DSH's model selection controls for that operation. ## Example task family The following source/profile family is a safe starting point to adapt. It intentionally contains no credentials and protects paid sources by default: ```yaml allowPaidFallback: false sources: - { id: opencode-go, provider: opencode-go, tier: subscription, priority: 1, autoEligible: true } - { id: token-share, provider: token-share, tier: free, priority: 2, autoEligible: true } - { id: starchasing, provider: starchasing, tier: paid, priority: 3, autoEligible: true } - { id: deepseek, provider: deepseek, tier: paid, priority: 4, autoEligible: false } profiles: - id: simple keywords: ["翻译", "摘要", "simple"] modelBySource: { token-share: gpt-5.4-mini } - id: coding keywords: ["写代码", "修复", "bug", "fix"] modelBySource: { opencode-go: mimo-v2.5, token-share: gpt-5.6-luna } - id: hard-coding keywords: ["死锁", "并发", "deadlock", "concurrency"] modelBySource: { opencode-go: mimo-v2.5, token-share: gpt-5.6-terra } - id: planning keywords: ["规划", "架构", "plan", "architecture"] modelBySource: opencode-go: { model: deepseek-v4-flash, reasoningEffort: high } token-share: gpt-5.6-luna - id: writing keywords: ["文档", "教程", "document", "tutorial"] modelBySource: { opencode-go: deepseek-v4-flash, token-share: gpt-5.6-luna } - id: deep-thinking keywords: ["深度思考", "复杂推理", "hard reasoning"] modelBySource: { token-share: gpt-5.6-terra } ``` DSH must already have the provider and model IDs registered. Quota Router validates those native IDs before it writes a request header.