Skip to content

Orchestration & Model Routing

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.

TierWhat it means
reviewerAnything 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.
implementerWork handed to another harness. The load-bearing case — plan on the session model, implement somewhere cheaper or faster. Absent, the session model implements.
fast scoutMechanical inventory scanning, where the cheapest model is the correct one.
thinking scoutAnalysis that degrades badly on a fast model.
unsetThe 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 dispatch

Highest 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.

HarnessIn-session modelIn-host subagentShell out to another CLI
Claude CodeYesYes — an agent definition’s model field is honoredYes
OpenAI CodexYesYes, but per-spawn model selection is not dependableYes — the dependable route here
Factory DroidYesYes — reads flow-next’s agent definitions directlyYes
CursorYesYes, but an agent definition’s model field is ignoredYes
xAI Grok BuildYesYes — verified by a full planning fan-outYes
OpenCode (community port)YesPort-dependentPort-dependent
Anything else / undetectableAssume yesAssume no until observedAssume 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:

  • Codex — an explicit per-spawn model or effort can be dropped silently, and whether a role profile was applied is not verifiable from inside the run. Treat a subagent’s model as best-effort and record what actually ran; a fresh non-interactive run of a CLI takes its model and effort on the command line, so nothing can strip them. Keep the child prompt flat — a child that fans out subagents of its own can return a result the parent cannot decode.
  • Grok Build — every model it can reach natively belongs to one family. That matters for exactly one tier: reviewer, whose whole point is a verdict from outside the writer’s family. When it cannot be satisfied natively, the honest outcomes are to shell out to another vendor’s CLI, or to state that the review is same-family and let a human decide. An attended session asks; an unattended one stops and says a human is needed.

When the session is Cursor itself, orchestration differs from reaching Cursor models from another host via the headless cursor-agent CLI.

SurfaceWhat happens on a Cursor host
Agent-definition model fieldsIgnored — subagents inherit the session model. There is no alias-to-slug rewrite mechanism and none is planned.
The escape hatchCaller-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 hostBare 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 backendreview.backend cursor:… is a separate headless subprocess path (multi-family reach from outside Cursor; circular when you are already inside it).
Cross-family ruleReviewer 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.

Terminal window
# 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 direction
claude -p "<self-contained prompt>" --output-format text --allowedTools "Read,Bash" </dev/null
codex exec -s read-only --skip-git-repo-check "<prompt>" </dev/null

Details: 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 — parametersPrompted — agentic intelligence
What it isConfig keys, flags, per-spec/per-task fields. Machine-resolved, same answer every timePolicy described in natural language. The host judges per item — conditionally, mid-run
Exampleflowctl 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”
ReachExactly the surfaces that shipAnything the host can do — including capabilities that don’t exist as parameters
When it winsHeadless/Ralph runs, stable team defaults, reproducibilityPer-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.

Two layers of steering — session vs machinery

Section titled “Two layers of steering — session vs machinery”

Most “will this override that?” questions dissolve once you see which layer you are talking to:

  • Session steering — your prompts and per-task pins. Top of the precedence chain, ephemeral, gone when the task is done. Naming a model for a tier in the moment — “implement via that CLI and review with the other family” — just works, and nothing persists afterward. Your routing block is this layer too: the deterministic plumbing never reads prose, but the agent reads it every turn and passes explicit values downward, so a routing block dominates everything the agent orchestrates by occupying the higher rung, not by editing config.
  • Machinery steering — config that deterministic plumbing resolves without an agent in the loop: 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:

Terminal window
flowctl config set review.backend codex # project default
flowctl 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 name
flowctl config set review.backend codex:<model>:xhigh # explicit model + effort
flowctl config set review.maxIterations 6 # review-round cap (env MAX_REVIEW_ITERATIONS wins)

Precedence, highest first: per-task review: / per-spec default_reviewFLOW_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.

Implementation offload — the bridge route

Section titled “Implementation offload — the bridge route”

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.

Terminal window
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 host

Two rules survive from the packaged path and are not optional:

  • The bridged child writes code; the host keeps git, judgment, and the verdict. The child never commits, never decides scope, never issues a review verdict, and never spawns a bridge of its own. Drop this and a bridge recipe becomes an unbounded second agent.
  • Which tier to bridge to: on well-specified work a value tier matches a strong tier on correctness for meaningfully less wall clock, so send clear, well-scoped tasks to the value tier and escalate to the strong tier only for genuinely gnarly ones. Spec quality is what makes the trade safe — a vague brief burns the saving on rework.

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.

The wrapper pattern — self-healing bridges for unattended loops

Section titled “The wrapper pattern — self-healing bridges for unattended loops”

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:

  • The wrapper MUST run the bridge in the foreground — one blocking call. A backgrounded bridge loses the completion signal and the wrapper idles forever on a finished (or silently dead) process.
  • The self-heal license covers environment and flags only, never judgment. In scope: git trust, sandbox flags, stale model ids, empty-output retry. Out of scope: rewriting the task prompt, interpreting review verdicts, or switching models on quality grounds.

This is a documented pattern, not a shipped agent type; quick interactive calls may stay raw.

Raw-bridge review prompts — demand severity tiers

Section titled “Raw-bridge review prompts — demand severity tiers”

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.

Prompted orchestration — routing with judgment

Section titled “Prompted orchestration — routing with judgment”

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 you
implement yourself on the session model; plain CRUD goes out to the
implementer 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 bridge

Conditional escalation — routing that reacts to outcomes:

Run /flow-next:work fn-12 and bridge implementation out. If a task's review
comes back NEEDS_WORK twice, stop bridging that task and implement it yourself
on 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 a
fresh-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 fieldThe ideaflow-next expression
Orchestrator → executorThe frontier model plans and judges; a cheaper, highly steerable model writes the codeAn implementer tier plus a bridge recipe, ad hoc or as standing prose. Host keeps gating/git/review
Orchestrator → readerToken-hungry, low-judgment reads run on fast models that report summaries backAlready the default: scouts run on the fast scout tier and return digests
Cross-family reviewerThe model that writes is never the model that reviewsreview.backend <backend>; per-task review: pins exceptions
Effort disciplineOrchestrator at high, not max — top effort tiers are token furnaces on routine workSession effort is yours; a bridged child takes its effort inline, and the routing block’s at <effort> makes the floor durable
Token-hungry offloadComputer 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.

StageTierWhy
Plan (capture / interview / plan / plan-review critique)unset — the session modelSpec authoring is inline and judgment-heavy; this is the never-delegate-judgment default
Plan-reviewreviewer, from a different family than the plannerUncorrelated blind spots on the highest-leverage artifact
Work (implementation)implementerWell-specified work runs correctly on a cheaper or faster tier; the saving is real only when the spec is clear
Impl-review, first passreviewer, measured from the writer — not the hostA reviewer from the family that wrote the diff re-correlates the blind spots
Impl-review, final gateunset — the session modelThe verdict, the severity call, and the blast-radius judgment stay with the conductor

Notes that keep this honest:

  • Single subscription? It still reads correctly. Every tier degrades to the session model, and the pipeline works exactly as shipped — routing is optional garnish, never a prerequisite.
  • Reach differs per harness, the tiers do not. The bridges run in both directions, so the same tier assignment holds everywhere; only how you get there changes. See Reach.
  • Scouting splits by kind of work, not by price. Mechanical inventory goes to the fast scout tier; analysis that degrades on a fast tier goes to the thinking scout tier.
  • Routing is checkable after the fact. Where the harness exposes it, a stage records the model that actually ran — a preference written in prose leaves evidence instead of a hope, and unavailable provenance is recorded as unknown, never as the configured value.

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.

Durable routing — the routing block in your instruction file

Section titled “Durable routing — the routing block in your instruction file”

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:

  • The usage guide, pulled live with 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.
  • Judgment stays with the host — a bridged child writes code; it never owns git, task state, review verdicts, or decisions.
  • Merge is human-gated everywhere except the explicitly opted-in land loop.
  • Verification is independent — a bridged diff is never trusted on the child’s own summary; the host re-runs the gates before flowctl done.
  • Escalation beats thrift — when you downgrade a tier, watch the first outputs and revert on the first quality miss.