Fix Claude Code smart routing: opus-4-8 pin, model name mapping, subagent prompt - #284
Open
masonc08 wants to merge 5 commits into
Open
Fix Claude Code smart routing: opus-4-8 pin, model name mapping, subagent prompt#284masonc08 wants to merge 5 commits into
masonc08 wants to merge 5 commits into
Conversation
Discovery's newest-wins family bucketing picks claude-opus-5 over claude-opus-4-8, but CLAUDE_ROUTE_ARMS hardcodes claude-opus-4-8 — so the routing availability check fails with 'required Claude routing models are unavailable: claude-opus-4-8' on workspaces that have both. Pin the opus slot to 4-8 when both exist so routing works with the currently-deployed task_v1 router. Revert once the router accepts opus-5 (PR databricks-eng/universe#2365446).
Claude Code's Agent tool model field only accepts short family names (sonnet, opus, haiku, fable), not full workspace ids. The PreToolUse hook was injecting the full id (e.g. system.ai.claude-sonnet-5) into updatedInput.model, which Claude Code rejected with a schema validation error. Map the router's pick back to its family name before injecting.
Claude Code's SubagentStart event does not include the subagent's model field, so the reconciliation audit recorded model=null and reported a false mismatch. When the actual model is unknown, record matches_router_decision as None (unknown) rather than False (mismatch), and emit no SubagentStart message to the user — the PreToolUse hook already injected the routed model.
route_spawn_tool looked for message/task_name/agent_name to derive the routing task, but Claude Code's Agent tool puts the subagent task in prompt/description — so Claude always fell through to the generic "Claude Code subagent task" label, and the router made decisions on a constant string. Add prompt and description to the front of the field fallback chain. Safe for Codex: its spawn_agent tool uses message, which is absent from Claude payloads, and vice versa.
masonc08
marked this pull request as ready for review
August 6, 2026 23:49
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Four fixes for Claude Code smart routing, all tested end-to-end against a live workspace.
1. Pin opus-4-8 in discovery (
databricks.py)Discovery's newest-wins family bucketing picks
claude-opus-5overclaude-opus-4-8, but the deployedtask_v1router'sccscenario requiresclaude-opus-4-8as a route arm. Pin opus-4-8 when both exist so the routing availability check passes. Revert once the router accepts opus-5 (databricks-eng/universe#2365446).2. Map subagent model to short family name (
claude_routing.py)Claude Code's
Agenttoolmodelfield only accepts short family names (sonnet,opus,haiku,fable), not full workspace ids. The PreToolUse hook was injecting the full id (e.g.system.ai.claude-sonnet-5), which Claude Code rejected with a schema validation error. Map the router's pick back to its family name before injecting.3. Don't report mismatch when harness omits subagent model (
routing.py,cli.py)Claude Code's
SubagentStartevent does not include the subagent's model field, so the reconciliation audit recordedmodel: nulland reported a false mismatch ("router requested sonnet, but Claude Code started None"). When the actual model is unknown, recordmatches_router_decision: None(unknown) rather thanFalse(mismatch), and emit no SubagentStart message — the PreToolUse hook already injected the routed model.4. Send Claude subagent prompt to router (
routing.py)route_spawn_toollooked formessage/task_name/agent_nameto derive the routing task, but Claude Code'sAgenttool puts the subagent task inprompt/description. So Claude always fell through to the generic "Claude Code subagent task" label, and the router made decisions on a constant string. Addpromptanddescriptionto the front of the field fallback chain. Safe for Codex: itsspawn_agenttool usesmessage, which is absent from Claude payloads, and vice versa.This pull request and its description were written by Isaac.