feat(routing): complete #3018 — RouterCandidates + provider_router_candidates; candidate-aware heuristics, router prompts and recommendation parsing; skip the network router when no cheap tier exists; validate spawn-time model against the active provider; tests + SUBAGENTS.md per-role models docs

Co-Authored-By: Claude <noreply@anthropic.com>
https://claude.ai/code/session_018zaP8vUfTAsrE38L6h6fw5
This commit is contained in:
Claude
2026-06-11 03:03:08 +00:00
parent a004cfbee6
commit fc10d10189
5 changed files with 513 additions and 55 deletions
+44
View File
@@ -124,6 +124,50 @@ cancelled records persist for inspection but don't occupy a slot.
Agents that lost their `task_handle` (e.g. across a process
restart) also don't count against the cap.
## Per-role models (#3018)
Children can run on a different model than the parent. Two config surfaces
feed the same override map (`[subagents.models]` keys win on conflict, keys
are case-insensitive):
```toml
[subagents]
default_model = "deepseek-v4-flash" # fallback for every role
worker_model = "deepseek-v4-pro" # worker / general
explorer_model = "deepseek-v4-flash" # explorer / explore
awaiter_model = "deepseek-v4-flash" # awaiter / plan
review_model = "deepseek-v4-pro" # review
custom_model = "deepseek-v4-pro" # custom
[subagents.models]
# Free-form role → model map; any role alias accepted by agent_open works.
implementation = "deepseek-v4-pro"
```
Model ids may be **any model the active provider accepts** — validation is
provider-aware and happens at spawn time, not load time. On the official
DeepSeek API only DeepSeek ids are accepted; every other provider passes the
id through to the provider API, which is the authority. A non-DeepSeek
example:
```toml
provider = "moonshot"
model = "kimi-k2.6"
[subagents]
worker_model = "kimi-k2.5"
```
Spawn-time `model` arguments on `agent_open` are validated the same way; an
invalid id on the official DeepSeek API fails the spawn with the accepted-id
list instead of an opaque provider 400.
With `/model auto`, sub-agent routing is provider-aware too: providers with a
known big/cheap pair (DeepSeek, and the hosted DeepSeek routes on NVIDIA NIM,
OpenRouter, Novita, SiliconFlow, SGLang, vLLM) route between that pair;
providers without a known cheap tier (e.g. Ollama, Moonshot) skip the
network router and keep children on the session model.
## Per-step API timeout (#1806, #1808)
Each sub-agent step wraps its DeepSeek `create_message` call in a