Route reviews to a different family than the writer
flowctl config set review.backend codex ✓ The writer never grades its own work; the verdict still lands as a receipt on disk.
Review workflow →flow-next is an orchestration layer, not a single-agent workflow. The host agent conducts: it fans work out to tiered subagents, routes reviews to a different model family than the writer, optionally drives a second CLI agent through a headless bridge, and runs autonomous build/ship loops. Which model does what is a routing decision — and every routing decision in flow-next is either a parameter or a sentence of intent away. The second kind carries judgment.
Routing is one move on a larger menu. The doctrine (skip, reorder, prompt into, chain, parallelize, all under the same contracts) is Menu, Not a Rail; the copy-paste recipes, including a model-routing section, live in the Cookbook. The same doctrine applied to subsystems rather than models — which layers to switch on at all, and what each costs — is Running Lean.
Optional chart discovery respects the same automation boundary as the rest of the menu: unattended drivers may fan out one invocation per open unattended D-ID (research / probe / eval); attended decisions (prototype, interview, attended task) terminate NEEDS_HUMAN and never self-resolve. Chart is not a pilot/build-loop stage - it ends at a briefing for capture.
Two words carry the whole routing story. A tier is what kind of model a job wants. Reach is how the active harness obtains one — the in-session model, an in-host subagent, shelling out to another CLI, or not available.
| Tier | What it means |
|---|---|
| reviewer | Anything grading work someone else produced. The only tier carrying a family rule: a reviewer from the writer’s own family is not an independent verdict. |
| implementer | Work handed to another harness. The load-bearing case — plan on the session model, implement somewhere cheaper or faster. Absent, the session model implements. |
| fast scout | Mechanical inventory scanning, where the cheapest model is the correct one. |
| thinking scout | Analysis that degrades badly on a fast model. |
| unset | The default, and the majority: planning, capture, interviews, requirement analysis, every verdict, and the worker run on the session model. This is the never-delegate-judgment doctrine, stated as the default rather than as a special case. |
Four names, chosen once. An unrecognized tier name is treated as unset, with one advisory line — never an error.
A tier says which model executes a stage, not which stages run. Which stages run is decided by what you invoked; asking for a leaner pipeline is a separate instruction that already works.
The family rule is advice, not enforcement. A model’s family cannot be verified from a name you invented, so the reviewer tier documents the rule, the receipt records what ran, and nothing fails closed on it.
Preferences live in your instruction file (CLAUDE.md / AGENTS.md), in your own words, naming models you can verify against your own account. One line per tier:
reviewer: <model>implementer: <model> at <effort>fast scout: <model>thinking scout: <model>An absent tier means the session model. An unparseable line is ignored with one advisory, never an error. Effort semantics stay the host’s — flow-next passes effort through and never translates between vendors’ scales. /flow-next:setup proposes this block commented out, for you to edit; nothing infers availability into it, and nothing rewrites a block a human has edited.
The block is the durable form of an ad-hoc instruction. Written once, it is read every turn — and an explicit instruction in the moment still wins over it.
Worked example, in a consumer’s own words:
you conduct + review (frontier, medium effort); implementation goes to<another model> via <its CLI>, one task per dispatchHighest first: an explicit argument in the invocation, then the project routing block in your instruction file, then the agent definition’s own default, then the session model.
There is no error surface: the chain terminates at the session model by construction. Agent definitions keep their model: field as the floor — what applies when nothing overrides — which is why a repo with no routing block behaves exactly as it always has.
A model this harness cannot reach — another vendor’s identifier, a retired one, one your account lacks — falls back to the session model, says so once, and continues. No probing, no question, no failure.
The review backend is separate: it keeps its own backend[:model[:effort]] configuration and its own documented precedence. The tiers never touch it.
Reach is documented once per harness, never inside a skill: a skill asks for a tier and never names a spawn primitive, a CLI flag, or a vendor path. The three mechanisms are the in-session model, an in-host subagent, and shelling out to another CLI.
| Harness | In-session model | In-host subagent | Shell out to another CLI |
|---|---|---|---|
| Claude Code | Yes | Yes — an agent definition’s model field is honored | Yes |
| OpenAI Codex | Yes | Yes, but per-spawn model selection is not dependable | Yes — the dependable route here |
| Factory Droid | Yes | Yes — reads flow-next’s agent definitions directly | Yes |
| Cursor | Yes | Yes, but an agent definition’s model field is ignored | Yes |
| xAI Grok Build | Yes | Yes — verified by a full planning fan-out | Yes |
| OpenCode (community port) | Yes | Port-dependent | Port-dependent |
| Anything else / undetectable | Assume yes | Assume no until observed | Assume no until observed |
An undetectable harness takes the last row and says so once. Guessing a harness is worse than naming the fallback: the generic row assumes the least reach and degrades cleanly.
Discovery beats declaration. Where a harness or a CLI can list what it offers, ask it at the moment of use — one command beats a stored fact that goes stale. This is why the tables and examples on this page name no model identifiers: which model fills a tier is a property of your account and your machine, not of a document.
Degradation is the same everywhere: a tier the harness cannot honor runs on the session model and says so once. That is the shipped default, so a harness with no dispatch mechanism at all still runs the whole pipeline — only the tier split is lost.
Two harnesses carry a caveat worth stating outright:
When the session is Cursor itself, orchestration differs from reaching Cursor models from another host via the headless cursor-agent CLI.
| Surface | What happens on a Cursor host |
|---|---|
| Agent-definition model fields | Ignored — subagents inherit the session model. There is no alias-to-slug rewrite mechanism and none is planned. |
| The escape hatch | Caller-side: name the model in the dispatch itself and the harness honors it (it also self-corrects a near-miss identifier). Slugs are volatile — ask cursor-agent --list-models immediately before pinning one rather than copying an identifier from a document. |
review.backend host | Bare only (host:<model> is rejected). Review runs as a host-native fresh-context subagent pinned to a family that did not write the diff — never the session model grading its own diff, no subprocess. Preferred default from inside Cursor. |
≠ the cursor CLI backend | review.backend cursor:… is a separate headless subprocess path (multi-family reach from outside Cursor; circular when you are already inside it). |
| Cross-family rule | Reviewer family ≠ writer family, measured from the writer. Fail-closed: without a cross-family pin, interactive setup asks; autonomous runs stop with NEEDS_HUMAN rather than silent same-family self-review. |
With no caller-side model in the dispatch, every tier resolves to the session model — which is exactly the shipped default and needs no configuration.
# In-session impl + host review (cross-family pin from the AGENTS.md routing block)flowctl config set review.backend host # or per-run: --review=host
# Bridges FROM a Cursor host - the same recipes, reverse directionclaude -p "<self-contained prompt>" --output-format text --allowedTools "Read,Bash" </dev/nullcodex exec -s read-only --skip-git-repo-check "<prompt>" </dev/nullDetails: Install → Cursor, Setup, Review workflow.
Skills are prompts executed by the host agent, not compiled code. That gives you two genuinely different routing methodologies — use both:
| Deterministic — parameters | Prompted — agentic intelligence | |
|---|---|---|
| What it is | Config keys, flags, per-spec/per-task fields. Machine-resolved, same answer every time | Policy described in natural language. The host judges per item — conditionally, mid-run |
| Example | flowctl config set review.backend codex | ”Work the three ready specs — decide per spec, by complexity, whether implementation goes out to a bridge or stays on the session model” |
| Reach | Exactly the surfaces that ship | Anything the host can do — including capabilities that don’t exist as parameters |
| When it wins | Headless/Ralph runs, stable team defaults, reproducibility | Per-item complexity calls, conditional escalation, inventing a routing the registry doesn’t have |
The two compose: parameters set the floor, prompting steers above it. Either can be made durable in CLAUDE.md / AGENTS.md — the host reads your instruction files every session, and flow-next skills inherit them automatically.
Most “will this override that?” questions dissolve once you see which layer you are talking to:
review.backend and the per-spec/per-task backend fields. This is what pilot ticks, Ralph runs, and unattended gates use when nobody is prompting. Standing changes for autonomous runs belong here, not in prose.The practical consequence: a prompt steers only the session it is typed in. If you want the 3am pilot tick to use a different reviewer, that is a config change — at 3am there is no prompt.
Two one-liners to start:
Route reviews to a different family than the writer
flowctl config set review.backend codex ✓ The writer never grades its own work; the verdict still lands as a receipt on disk.
Review workflow →Name an implementer tier once, in your own instruction file
implementer: <your model> at <effort> ✓ One line in CLAUDE.md / AGENTS.md, read every session including unattended ticks. Absent, the session model implements — nothing to enable.
The routing block →The review subsystem is the most routable surface — spec grammar backend[:model[:effort]] over rp | codex | copilot | cursor | host | none. This grammar is the one place in flow-next where a model identifier is a first-class configuration value:
flowctl config set review.backend codex # project defaultflowctl config set review.backend host # host-native fresh-context subagent (bare only)flowctl config set review.backend cursor:<model> # cursor folds effort into the model nameflowctl config set review.backend codex:<model>:xhigh # explicit model + effortflowctl config set review.maxIterations 6 # review-round cap (env MAX_REVIEW_ITERATIONS wins)Precedence, highest first: per-task review: / per-spec default_review → FLOW_REVIEW_BACKEND → config → backend env → default. A single task can pin its own reviewer and the override routes end-to-end. The cursor CLI backend reaches reviewer models from several families in one place on your existing subscription — ask its CLI for the current list rather than copying identifiers from a document. host is a model-less selection sentinel — bare only; pins live in your routing block, never on the backend string. Details: review workflow, Cursor host, configuration.
Rule of thumb: the model that writes is never the model that reviews. Route the reviewer to a different family than your session model and blind spots stop being correlated.
Offloading the token-heavy part (writing code) to a second CLI is a routing decision you write, not a subsystem you configure. There is no packaged delegation mode and no delegation config: name an implementer tier and drive the other CLI through a headless bridge, either ad hoc in the session or as standing policy in your instruction file.
codex exec -m <model> -c model_reasoning_effort=<effort> "<self-contained prompt>"cursor-agent --model <model> --force "<self-contained prompt>"claude -p "<self-contained prompt>" # the same bridge in reverse, from a Codex/Cursor hostTwo rules survive from the packaged path and are not optional:
Full recipes, including the wrapper pattern for unattended loops, ship into the repo you work in and are read on demand with flowctl usage (## Orchestration & model steering).
Coming from delegate:codex? The packaged mode and its work.delegate* keys were removed in 4.0.0. Leftover keys in .flow/config.json are inert — flowctl names them once in a non-blocking advisory and otherwise ignores them. Run /flow-next:setup, accept the routing-block scaffold, and use the bridge recipes above.
Raw bridge calls have a silent-failure class: outside a trusted git directory, codex exec refuses in about a second with the error only in its log, and cursor-agent blocks on an interactive workspace-trust prompt, then exits “successfully” with empty output. An interactive host sees the stderr and just fixes it; an autonomous loop dies silently. Wrap the bridge in a thin fast-scout-tier subagent instead of calling it raw: the wrapper composes the self-contained prompt, runs the bridge, verifies the output is non-empty and parseable, repairs the environment if not, and retries once.
Two rules are load-bearing:
This is a documented pattern, not a shipped agent type; quick interactive calls may stay raw.
Applies to ad-hoc bridge reviews only — a hand-rolled review whose output a human reads directly. Put two things in the prompt: P0-P3 severity tiers plus spec-grounded verdicts, so an edge-case finding does not flip a ship gate; and optionally a minimal suggested fix and blast radius per finding when no fix loop follows the review.
The packaged /flow-next:impl-review prompt is deliberately not this shape: its find-vs-fix split (the reviewer returns findings; the internal fix loop investigates and fixes, with validator and iteration caps) is by design.
This is the mode parameters can’t reach: routing policy that’s conditional and per-item, decided against the actual work rather than fixed up front.
Per-item complexity routing — the host classifies, then routes:
Work through the three ready specs. Decide per spec, based on complexity,how the work stage runs: anything touching auth or the migration youimplement yourself on the session model; plain CRUD goes out to theimplementer tier over a bridge. Reviews come from a different family either way.Focus and scope steering — instruction the skill never anticipated, read as intent:
/flow-next:plan fn-12 --depth=deep — focus the research on the migration path; I care about rollback/flow-next:interview fn-12 — push hard on failure modes and operational edges, skip UI polish/flow-next:work fn-12 — the UI tasks stay with you; send the API plumbing out to a bridgeConditional escalation — routing that reacts to outcomes:
Run /flow-next:work fn-12 and bridge implementation out. If a task's reviewcomes back NEEDS_WORK twice, stop bridging that task and implement it yourselfon the session model.Prompting a capability into existence — no registry entry exists for a session-model reviewer; that didn’t stop this repo’s own loop from running fresh-context, session-model-reviewed rounds:
/flow-next:plan-review fn-12 — don't use the configured backend; spawn afresh-context subagent on the session model with the same review criteria,and feed its verdict into the fix loop like any other reviewer.Backends, reviewers, and bridged implementers are prompts plus plumbing — when a rung you want is missing, describe it and the host builds the arrangement on the spot. The deterministic flags (--review=<backend>, --depth=short) still work inline for the parts that are parameterized; prompting composes around them.
The orchestration patterns that emerged in the wild through mid-2026 all have a direct flow-next expression — most need one config key or one sentence:
| Pattern from the field | The idea | flow-next expression |
|---|---|---|
| Orchestrator → executor | The frontier model plans and judges; a cheaper, highly steerable model writes the code | An implementer tier plus a bridge recipe, ad hoc or as standing prose. Host keeps gating/git/review |
| Orchestrator → reader | Token-hungry, low-judgment reads run on fast models that report summaries back | Already the default: scouts run on the fast scout tier and return digests |
| Cross-family reviewer | The model that writes is never the model that reviews | review.backend <backend>; per-task review: pins exceptions |
| Effort discipline | Orchestrator at high, not max — top effort tiers are token furnaces on routine work | Session effort is yours; a bridged child takes its effort inline, and the routing block’s at <effort> makes the floor durable |
| Token-hungry offload | Computer use and live-app verification go to other agents; results come back as evidence | /flow-next:qa drives the app in its own context; workers run fresh-context and return receipts |
The routing this repo runs, stated in tier terms. It names no model identifiers on purpose: which model fills a tier is a property of your account and your harness, and only you can name it.
| Stage | Tier | Why |
|---|---|---|
| Plan (capture / interview / plan / plan-review critique) | unset — the session model | Spec authoring is inline and judgment-heavy; this is the never-delegate-judgment default |
| Plan-review | reviewer, from a different family than the planner | Uncorrelated blind spots on the highest-leverage artifact |
| Work (implementation) | implementer | Well-specified work runs correctly on a cheaper or faster tier; the saving is real only when the spec is clear |
| Impl-review, first pass | reviewer, measured from the writer — not the host | A reviewer from the family that wrote the diff re-correlates the blind spots |
| Impl-review, final gate | unset — the session model | The verdict, the severity call, and the blast-radius judgment stay with the conductor |
Notes that keep this honest:
Pilot and land end every tick with machine-readable verdicts so a driver can compose them — a multi-model spec-to-merged-PR pipeline in one prompt:
/loop 30m — one tick: run /flow-next:pilot --review=codex --depth=deep. If PILOT_VERDICT=DEFERRED_TO_LAND, run /flow-next:land in the same tick. Send implementation tasks to the implementer tier, keep UI tasks on the session model, reviews come from codex. Stop when pilot prints NO_WORK and land prints LAND_VERDICT=NO_WORK, or on any NEEDS_HUMAN.DEFERRED_TO_LAND exists exactly for this hand-off. For the hardened overnight harness, see Ralph.
Session steering is a sentence you type; durable steering is the same sentence written once into CLAUDE.md / AGENTS.md, where the host reads it every turn. That is the routing block: <tier>: <model> lines, optionally at <effort>, interpreted by intelligence rather than parsed by a config loader — which is why it can be prose, and why an unreachable name degrades instead of failing.
/flow-next:setup offers to scaffold it: the four tier lines with their guidance, every value commented out, so nothing routes until you fill one in. Setup never asserts which models are installed and never overwrites a block a human has edited. Marker-fenced, so /flow-next:uninstall removes it cleanly.
Tier names are durable; model identifiers are volatile — that asymmetry is the whole reason routing is expressed as tiers here and as model names only in your file.
This page lives in the docs site — outside the repo you’re working in. At use time the host agent reads two things that are always current with the installed plugin:
flowctl usage (the always-loaded CLAUDE.md / AGENTS.md block points agents at it). Its ## Orchestration & model steering section carries the headless bridge commands — codex exec, cursor-agent, and the reverse claude -p — plus the flow-next shortcuts (review.backend, per-task review:) and prompted-orchestration examples. The bridges run in every direction: any harness that can run Bash can be the conductor.CLAUDE.md / AGENTS.md, holding the durable routing block above.flowctl done.