Default cost/complexity routing table for the batuta conductor. Read at bootstrap as a starting point, validated against the live provider catalog, then stored as the per-workspace loop configuration; the stored workspace override is authoritative afterwards.
Scanned 9/3/2026
Install to Claude Code
npx -y skills add compozy/compozy --skill batuta-routing --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Batuta Routing?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/compozy-batuta-routing)More formats (shields.io, HTML) on the badges page.
---
name: batuta-routing
description: Default cost/complexity routing table for the batuta conductor. Read at bootstrap as a starting point, validated against the live provider catalog, then stored as the per-workspace loop configuration; the stored workspace override is authoritative afterwards.
---
# Batuta Routing Table
Batuta's core opinion: route every task to the cheapest executor that can
handle it. Lanes use the `complexity` vocabulary that `cy-create-tasks`
writes into task frontmatter (`low`, `medium`, `high`, `critical`) — the
same vocabulary `runtime_rules[].match.complexity` matches on.
## Lane semantics (the durable opinion)
| Lane | Intent | Selection rule |
| ---------- | ------------------------------------- | ---------------------------------------------------------- |
| `low` | Contained change, well-trodden paths | Cheapest coding-capable model in the catalog |
| `medium` | New interfaces, moderate coordination | Mid-tier coding model; raise reasoning before raising cost |
| `high` | New subsystem, heavy reasoning | Strong coding model, premium tier acceptable |
| `critical` | Cross-cutting, high regression risk | The operator's most trusted frontier model |
## How batuta derives the concrete table (never copy an example)
1. `compozy__provider_models_list` (with costs) is the ONLY source of
concrete provider/model IDs — it reflects the CLIs actually installed
and the models actually discovered on this machine. A provider absent
from the catalog is not installed; never route to it.
2. Map each lane's selection rule onto the catalog using the cost fields
(`input_per_million` / `output_per_million`) as evidence.
3. Model enablement is account-side and invisible to the daemon — present
the derived table (with costs) to the operator for confirmation before
storing; ask what their accounts enable when in doubt.
### Example only — derived on one machine on 2026-08-11, DO NOT reuse
On that machine the derivation produced: `low → codex/gpt-5.6-luna`,
`medium → codex/gpt-5.6-terra@high`, `high → codex/gpt-5.6-sol`,
`critical → claude/claude-opus-4-8`. Your catalog will differ; derive, do
not copy.
## Canonical rule shape
This is the exact JSON SHAPE batuta writes with `compozy__loop_configure`
(stored per-workspace override for `implement-tasks`) after deriving the
values from the catalog — the model/provider strings below are the same
dated example as above and MUST be replaced by the derived ones. The stored
override is what `run-loop` children resolve at execution — batuta never
sends per-run rules on dispatch, because per-run rules freeze into the run
and are not inherited by `run-loop` children anyway. Rule matching
precedence inside the stored layer: `id > type > complexity`.
```json runtime_rules
[
{ "match": { "complexity": "low" }, "runtime": { "provider": "codex", "model": "gpt-5.6-luna" } },
{
"match": { "complexity": "medium" },
"runtime": { "provider": "codex", "model": "gpt-5.6-terra", "reasoning": "high" }
},
{ "match": { "complexity": "high" }, "runtime": { "provider": "codex", "model": "gpt-5.6-sol" } },
{
"match": { "complexity": "critical" },
"runtime": { "provider": "claude", "model": "claude-opus-4-8" }
}
]
```
## Provider quirks
- Some providers multiplex upstreams and require the model field to carry a
prefix — e.g. `opencode` only binds `opencode/kimi-k2.5`, never bare
`kimi-k2.5`. The catalog's exact `model_id` is authoritative; copy it
verbatim into the rule.
- A model can exist in the catalog and still be disabled for the operator's
account at the provider (invisible to the daemon). When a lane fails its
bind with zero tokens, ask the operator what their account enables.
## Escalation and reclassification
- Repeated failure in a lane: write a surgical `id` rule one lane up into
the STORED override (`compozy__loop_configure` on `implement-tasks`, e.g.
`{"match":{"id":"task_NN"},"runtime":{...}}` prepended to the rules), then
re-dispatch `batuta-deliver`. `id` beats `complexity`; remove the rule
after the task lands.
- Operator reclassification in conversation ("use luna for this one")
becomes the same stored `id` rule before the next dispatch.
- The daemon persists `resolved_runtime` with per-field provenance on every
generation — routing decisions are auditable via `compozy__loop_status`,
never narrated.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!