Skip to content
Back to skills

Batuta Routing

ASecurity

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.

  • 2,785 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 3, 2026
ai-agentsrust

Works with

  • cli

Security analysis

A100/100

Scanned September 3, 2026

npx -y skills add compozy/compozy --skill batuta-routing --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Batuta Routing?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Batuta Routing
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/compozy-batuta-routing/badge)](https://www.skillsdirectory.com/skills/compozy-batuta-routing)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
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.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.