Models and presets
How the harness picks a model for each role from its runtimes and tag registry, the default tags per role, model pins, the six shipped presets and the conductor's model and effort
This page says how a run's roles get their models and what the shipped presets change. File:line citations are in parentheses; "not checked" means the code read for this page does not settle it. The key tables are on harness.json, not repeated here.
01runtimes#
The work runtimes are claude, codex and grok (RuntimeNames; RegistryRuntimes). A registry entry on any other runtime is refused. DetectRuntimes asks each one's probe whether it can start, and a runtime with no probe is reported "no readiness probe". What each probe checks: not checked.
internal/runtime/ollama.go and internal/runtime/anthropic.go are provider adapters (OllamaProvider at, AnthropicProvider at). They are not in RuntimeNames, so a run's roles cannot use them. Where they are used instead: not checked.
02the registry#
Every model the instance can run is a registry entry: a runtime, a model id, tags and a rank (ModelEntry). The tags are a fixed list: reasoning, code, review, creative, fast, cheap and long-context. Any other tag is refused. A higher rank wins, and the order of the entries breaks a tie.
The shipped pool is six entries (DefaultRegistry). An instance changes it with the model_registry key, see model_registry (RegistryConfig):
runtimeskeeps only the shipped entries on those runtimes. Empty keeps all.addappends extra entries.overridere-tags or re-ranks one entry named by runtime and model. An override naming no entry, or one entry twice, is refused.
The result is validated, and a bad registry fails closed.
03role tags#
Each role asks the registry for the models carrying all of its tags. The defaults are DefaultRoleTags. The role_tags key changes them, see role_tags.
| role | default tags |
|---|---|
| intake | code,fast |
| plan | reasoning |
| work | code |
| review | review |
| close | fast,cheap |
Roles are picked in the order intake, plan, work, review, close, so review is picked after work (roleOrder).
- A
*_modelpin wins over tags: a role with a pin skips tag matching (Select). A pin on a registry model that runs on another runtime than the role's is skipped, with the reason "pin ... skipped". - Every role can change runtime: each has its own
*_runtimekey, see harness.json. - The reviewer must differ from the worker. The review request carries
DifferentFrom: workwhenever work is picked too. That keeps a second pair of eyes without a second vendor (DefaultRoles).
04presets#
A preset is a named set of quality knobs a ticket run launches with. It turns quality dials only: nothing in a preset removes the human gate, the checks, the completion proof or the land. A preset names no model unless a role is pinned; each role is matched by its tags inside the preset's level.
A level is a rank band in the registry plus an effort. floor is the lowest rank a match may have, prefer says whether the strongest (highest, the default) or the cheapest (lowest) entry in the band wins, and effort is one of low, medium, high, max. Effort is passed only to claude and codex. An effort asked of any other runtime is recorded as not applied.
DefaultPresets ships six:
| preset | level | role_tags | routes (challenge, review, second_review) | max_revise_loops | budgets | limits |
|---|---|---|---|---|---|---|
| quick | floor 0, lowest, effort low | plan asks code |
off, off, off | 1 | 200000 output tokens, 10 searches; max_asks 1 | every role: 4 MiB output, 30m deadline |
| balanced | floor 0, highest | none | off, off, off | 2 | none | none |
| thorough | floor 70, highest, effort high | none | auto, auto, auto | 2 | 1000000 output tokens, 40 searches | every role: 16 MiB output, 60m deadline |
| max | floor 70, highest, effort max | none | auto, auto, auto | 3 | 4000000 output tokens, 100 searches | every role: 32 MiB output, 90m deadline |
| lean | floor 0, lowest | none | off, off, off | 2 | none | none |
| heavy | floor 0, lowest | work asks code,reasoning |
off, off, off | 2 | none | none |
- Balanced is today's launch: every role at its strongest match, no optional steps, two revise loops.
- Lean is the cheapest tagged match per role. Heavy is lean with work on a model that is both code and reasoning.
offskips a step.onrequires the pool to meet the step's tags and the differ-from rule.autotakes the step when the pool can and records why it was off when it cannot.- A shipped preset is replaced by an operator preset of the same name, and an operator's new ones are added after (
Presets). Thepresetskey is described at presets. - Tweaks made at launch are frozen into the launch digest, which is why a tweaked run is called
custom. See launch for what go freezes. - The revise-loop numbers are explained on feedback-loops.
05the conductor's model and effort#
The conductor's chats are moved with two desk tools:
conversation_modelmoves a chat to another claude model. Its session resumes on the new model at the next turn. A chat whose conductor is replying is refused, and an unknown model is refused with the list of conductor models.conversation_effortsets a chat's effort. See chats for how the chat controls read.
The conductor's default effort is the conductor_effort key in desk.json, see desk.json.