Orch uses an LLM-as-classifier to route each task to the best agent. This is a non-agentic call (--print) — fast and cheap, no tool access needed.
How It Works
- The Rust router (
src/engine/router/) sends the task title, body, labels, and the skills catalog to a lightweight LLM (default:claude --model haiku --print). - The router LLM returns JSON:
{ "executor": "claude", "complexity": "medium", "reason": "why this agent/model", "profile": { "role": "DeFi Protocol Engineer", "skills": ["Solana", "Anchor"], "tools": ["Bash", "Edit", "Read"], "constraints": ["audit with sealevel attacks"] }, "selected_skills": ["solana-best-practices"] } - Sanity checks run -- e.g. warns if a backend task gets routed to claude, or a docs task to codex. If the router fails repeatedly (configurable via
max_route_attempts, default 3), it falls back to round-robin. - If the router fails, it falls back to
config.yml'srouter.fallback_executor(default:codex).
Config
router:
mode: "llm" # "llm" | "round_robin" | "local"
agent: "claude" # which LLM does the routing
model: "haiku" # fast/cheap model for classification
timeout_seconds: 60
max_route_attempts: 3 # LLM failures before falling back to round-robin
max_tasks_per_tick: 1 # routing concurrency cap
weighted_round_robin: false
fallback_executor: "codex"
allowed_tools: # default tool allowlist
- yq
- jq
- bash
default_skills: # always included in routing
- gh
- git-worktreeTo exclude an agent from routing entirely, remove it from the agents: discovery list (the router only considers installed, listed agents) — there is no separate disabled_agents knob.
Available Executors
| Executor | Best for |
|---|---|
codex | Coding, repo changes, automation, tooling |
claude | Analysis, synthesis, planning, writing |
opencode | Lightweight coding and quick iterations |
kimi | Alternative coding agent |
minimax | Alternative coding agent |
Agents are auto-discovered from PATH. The router only picks from installed agents.
Complexity-Based Model Selection
The router assigns a complexity level (simple, medium, complex) which maps to agent-specific models:
model_map:
simple:
claude: "haiku"
codex: "gpt-5.1-codex-mini"
medium:
claude: "sonnet"
codex: "gpt-5.2"
complex:
claude: "opus"
codex: "gpt-5.3-codex"
review:
claude: "sonnet"
codex: "gpt-5.2"The routing prompt is in prompts/route.md. The router only classifies — it never touches code or files.
Pre-emptive Routability
The router performs a pre-emptive routability check before attempting to invoke agents or the router LLM. This does two things:
- It excludes agents that are currently in cooldown or have been marked degraded by the health check (rate-limit signals). These checks are authoritative — if an agent is degraded, it will be skipped regardless of weight.
- When
router.weighted_round_robinis enabled, an additional weight-based threshold (router.skip_limited_threshold) is applied after the degraded check. Agents whose routing weight has decayed below this threshold are skipped proactively to avoid sending work to recently rate-limited agents. This weight-based exclusion only layers on top of existing cooldown/degraded logic and does not replace it.
Configure the threshold in your config.yml under router.skip_limited_threshold (default: 0.3).