Skip to content

Agent lanes and capabilities

config/agents.yaml answers one question per role: which model should do this job? It does not describe endpoints — that is providers.yaml. This page covers the lane map, the capability metadata, and the budget block that is display-only.

The lane map

lanes:
  planner: sonnet
  researcher: sonnet
  implementer: sonnet
  worker: sonnet
  reviewer: opus
  verifier: sonnet
  reflector: sonnet
  publisher: sonnet
  rollback: sonnet

Every value is a provider name from providers.yaml (or an alias defined elsewhere in lanes). Workflow nodes reference the key:

- name: reviewer
  type: reviewer
  model_lane: reviewer

Canonical roles

The canonical loop roles are the ones generic recipes use:

Lane Fills Default in the shipped map
planner Decomposes a kickoff into nodes sonnet
researcher Gathers context before implementation sonnet
implementer Writes the change sonnet
worker Alias for implementer in generic workflows sonnet
reviewer Judges the finished change; final verdict quality opus
verifier Runs or assists deterministic gates sonnet
reflector Extracts lessons after a verdict sonnet
publisher Applies the publish gates sonnet
rollback Restores the tree on escalation sonnet

Multi-stage recipes add stage-specific lanes — decomposer, spec_author, spec_reviewer, bdd_runner, healer, brain. A recipe may use any of them without changing the executor; unknown lane names are resolved against the map at dispatch.

Lens lanes

A review panel is only diverse if its members are not all the same model. The shipped map therefore pins one lane per provider family:

Lane Provider Family
glm_lens glm Zhipu
kimi_lens kimi Moonshot
codex_lens codex OpenAI
opus_lens opus Anthropic
minimax_lens minimax MiniMax

The judge lane is deliberately separate from reviewer. The eval node's resolved lane is published into MO_DISPATCH_CHAIN, which dispatch reads before a per-juror lane argument — sharing reviewer would pin every juror to one model and make a cross-family jury inert.

One lane, one family

If two lens lanes resolve to the same provider, the panel is not heterogeneous. Check with mini-ork providers status after editing the map.

Capabilities

capabilities: declares what each lane can do. It is metadata used by capability-driven dispatch and by the UI:

capabilities:
  opus:
    vision: true
    tools: true
    reasoning: true
    search: true
  sonnet:
    vision: true
    tools: true
    reasoning: false
    search: false
  codex:
    vision: false
    tools: true
    reasoning: true
    search: false

A workflow node may require capabilities:

- name: analyst
  type: researcher
  model_lane: sonnet
  requires_capabilities: [vision]

The capability flags are claims about a lane, not probes. If a gateway silently loses tool support, the flag will not notice — the lane-health gate catches reachability, not behaviour.

Budget block — read this before relying on it

budget:
  per_epic_usd: 5.00
  per_run_usd: 0.50
  daily_cap_usd: 50.00

Display-only

No gate reads this block. It is rendered by the IDE and the SDK. The only enforcing cost knob is MO_DAILY_BUDGET_USD, a rolling 24-hour cap, plus a node's max_cost_usd and a task class's budget_cap_usd.

Per-model descriptors

config/agents/*.yaml carry richer metadata per model — identity, tier, tags, escalation target. A representative shape:

id: glm
display: "GLM 5.1"
model_arg: ""
budget_usd: null            # null = flat-plan / uncapped
role: worker
escalate_only: false
capabilities: [refactor, security, precision]
tier:
  speed: 1                  # 1 = slow, 4 = fast
  precision: 4              # 1 = low, 4 = high
  max_context_tokens: 256000
fallback_above: deepseek    # escalate up on repeated failures
fallback_below: kimi        # documented, not used at runtime
  • capabilities are free-form tags matched against a task's required_capabilities.
  • tier lets a router weigh speed against precision.
  • fallback_above is the escalation target after repeated failed reviews; the chain ends at a lane with fallback_above: null.
  • fallback_below is documentation only — nothing consumes it today.

The native dispatcher reads providers.yaml and agents.yaml; the descriptor files supply routing metadata, not transport.

Scope guards

config/scope-patterns.yaml.example shows how to restrict which files a lane may touch:

lanes:
  frontend:
    allow: ["src/**/*.tsx", "src/**/*.ts", "tests/e2e/**"]
    deny: ["server/**", "db/**"]
  backend:
    allow: ["server/**/*.ts", "server/tests/**"]
    deny: ["src/**", "public/**"]

Copy it to $MINI_ORK_HOME/config/scope-patterns.yaml and adapt. Enforcement happens through tool restrictions and a post-diff validation before merge.

Overriding for one machine

Never edit the committed map to point at a personal model. Use the overlay:

$MINI_ORK_HOME/config/agents.local.yaml

It is merged over agents.yaml and wins on conflict. Point MINI_ORK_AGENTS at a different path to keep several overlays.