New! Jouzu — our CLI agentic coding harness, built for Japan. Connect in 60 seconds.Learn More

Eight shapes for an agent graph.

A catalogue of orchestration topologies — what each one is for, the failure it guards against, and whether the runtime enforces it or you do.

How to read this

A pattern is a role topology, an ownership rule and a stopping condition. Most of the value is in the second one.

Every pattern below carries two badges, because the two questions people actually ask are different questions.

kernel The runtime enforces the shape. You get it whether or not your prompt holds up.
prompt Expressible, but nothing enforces it. If the orchestrator drifts, the shape is gone and nothing will tell you.
run here We ran it on Jouzu and the write-up is on the companion page.
shipped Running in production as a skill, in this repo or globally on this machine.
reasoned Derived from the source. Not yet run. Treat accordingly.
The rule that governs five of the eight. Jouzu admits a child only if no write-capable run is already executing in the same working directory — manager.js:466-471, comparing cwd by exact string. And roleCanWrite is true for any role holding write, edit, bash or powershell, so a role that only runs tests still counts as a writer. Two writers in one workspace therefore never run at the same time, no matter how disjoint their files. Read-only children have no such restriction and genuinely do run together.

01 Disjoint-workspace fan-out

N writers, one working directory each.

kernelreasoned, not run

The only way to get writing agents genuinely running at the same time. Give each child its own cwd — a git worktree, a second clone, or just a different subtree — and the admission check stops matching, so they are admitted together up to maxConcurrent.

one workspace cwd = ~/repo ×3 coder A coder B coder C serialised — one lock per cwd three workspaces wt/a · wt/b · wt/c coder A coder B coder C concurrent — different keys
Same three agents, same work. The only difference is the cwd each was launched with.

The role set: an orchestrator, N identical worker roles, and a merge step you own. The children cannot merge their own work — they are in different trees and cannot see each other.

Guards against: nothing, on its own. This pattern is purely a throughput technique, and it adds a risk: N divergent trees that must be reconciled. Reach for it only when the work genuinely parallelises and the merge is cheap — independent modules, per-language translations, one deck per worker. If the merge is the hard part, serialising in one workspace is the better trade.

What the runtime gives you: workspace is a launch parameter, resolved relative to the parent and realpath’d, with no containment check — any readable directory is accepted (workspace.js:4-26). It is not a sandbox; tools and OS permissions still decide what a child can touch. resume cannot change it. Note also that the lock key is the exact path string, so ~/repo and ~/repo/web are different keys and will run concurrently in the same tree — convenient, and a trap if you did not mean it.

Real-world examples

  • engineeringBump a shared library across five service repositories at once — one worker per repo, one review at the end. Nothing is shared, so nothing has to be reconciled.
  • engineeringGenerate SDK clients for six languages from one API spec, each into its own output directory.
  • designPush a brand refresh through separate asset repositories — web, mobile, email templates — in a single pass.
  • marketingLocalise a landing page into eight markets, one worktree each. The merge is a directory copy, which is the cheap-merge test this pattern asks you to pass first.
  • salesBuild a tailored one-pager for each of twelve target accounts from one template, each in its own folder.
  • dataRun the same evaluation against four model configurations in four scratch directories, with no shared state to corrupt.

02 Blind review panel

One artifact, K read-only judges, one lens each, none of whom can see the others.

kernelshipped in this repo

The strongest pattern here, and the one with the most production mileage. Instead of one reviewer with a long checklist, run K reviewers with one checklist item each — and give none of them the author’s reasoning, the orchestrator’s opinion, or each other’s findings.

the artifact one draft reviewer · fidelity round1-fidelity.json reviewer · native_ja round1-native_ja.json reviewer · finance_legal round1-finance_legal.json adjudicator merges by location
Three reviewers, one lens each, disjoint output paths, launched in a single message. The crossed links are the point: no reviewer can be talked out of a finding by another.

In production: two translation-review workflows we run are exactly this — fidelity and native_<lang> always, plus a domain lens chosen by who the audience is, not what the document is about. The workflow definition is blunt about why: “Reviewers must never receive the translator’s summary or the orchestrator’s opinions — independence is the point.” The lens library adds the rule that keeps the panel statistically honest: “keep lenses orthogonal — if two lenses would raise the same finding, tighten one of them.”

Two adjudication rules worth stealing. One of them resolves conflicts by kind of claim rather than by seniority: fidelity wins on meaning, native wins on phrasing, and the two are combined into one target. The other does the opposite on purpose — it keeps both reviewers’ reasoning and takes the higher severity, so that two lenses independently converging becomes visible evidence rather than being collapsed away.

Guards against: anchoring (a reviewer talked out of a real finding by a plausible explanation), checklist dilution (one reviewer spreading attention across nine criteria and missing the figures), herding (the second reviewer agreeing with the first), and self-grading. Also, concretely: a fluent, confident mistranslation of a risk disclosure — the failure a single reviewer reliably misses.

What the runtime gives you: real concurrency, unusually. Read-only children take no cross-session lock and do not block each other, so K judges in one workspace genuinely run at once — provided no writer is running there. Launch them after the writers have reported, not alongside.

Real-world examples

  • engineeringA pull request reviewed by one agent per concern — injection, authorisation, data handling, error paths. Give one reviewer all four and you reliably lose the last two.
  • legalA customer contract with separate lenses for liability, data processing and termination, kept apart so none of them softens another.
  • marketingLaunch copy with a claims lens (is every superlative substantiable?), a brand-voice lens, and a regulatory lens.
  • salesA proposal checked independently for pricing arithmetic, scope creep, and commitments the delivery team never agreed to.
  • designA new screen checked separately for contrast, touch-target size, and copy length in the longest supported locale.
  • financeA board deck where one lens checks every number against its source and another checks whether the narrative actually matches those numbers.

03 Judge and verifier

A read-only judge paired with a role that can execute.

kernelrun here

A judging role is restricted to read, grep, find and ls. It therefore cannot run the thing it is judging — which is fine for “is this logic right” and useless for “does it produce the right number”. Pair it with a cheap executing role and route each criterion to whichever can actually answer it.

the code judge read grep find ls PASS / FAIL CANNOT VERIFY verifier + bash criteria it can read criteria that need running
The judge’s honest non-answer is the routing signal. CANNOT VERIFY is not a failure of the judge — it is the judge telling you which role you are missing.
Guards against: a review that reads plausible and proves nothing. In our run the judge found two real defects nobody else had — a write into a read-only tree and an acceptance criterion that was never satisfiable — and correctly returned CANNOT VERIFY on the two criteria that mattered most, because both needed the program executed. Without a verifier those two simply go unanswered.

What the runtime gives you: a judging role also captures a git fingerprint of its workspace before and after (review.js:6-41), and the result is prefixed with changed / unverified if the tree moved under it. That is tamper-evidence on one directory — proof the reviewed thing still exists, not proof the review was right.

Real-world examples

  • engineeringThe judge reviews a migration’s logic; the verifier runs the suite and reports which tests actually pass. Only one of them can tell you.
  • dataThe judge reads whether a benchmark’s methodology is honest; the verifier re-runs it and reports the number.
  • designThe judge reviews layout markup; the verifier screenshots it at six viewport widths and reports what clips.
  • marketingThe judge reads a landing page for persuasion; the verifier measures the load time the copy is claiming.
  • financeThe judge checks a model’s assumptions; the verifier recomputes it and diffs against the figure that was published.
  • localisationThe judge reviews translated copy; the verifier renders it and reports which strings overflow their container. A reviewer reading text cannot see clipping.

04 Serial pipeline

A to B to C, each stage consuming the last stage’s structured output.

kernelshipped globally

The plainest pattern and often the right one. Each stage is a role with its own model and tool grant; the hand-off is a document, not a conversation. Where a later stage needs the same child’s context, resume continues it — but note that resume changes only the task text: role, model, workspace and context are pinned for the life of the run.

researcher read-only packet writer the only writer draft SEO check read-only quality score read-only both read the same draft — these two could run together
A content pipeline of the kind most teams end up with. Stages 3 and 4 are both read-only consumers of one finished draft, so nothing stops them running concurrently — the shipped skill runs them in sequence anyway. Worth noticing as an inconsistency rather than copying as a design.
Guards against: fabrication propagating downstream. The pipeline’s real trick is that the researcher is a separate read-only role with a source-tier ladder, and the writer is forbidden from adding statistics the researcher did not verify. Generator and checker hold the same rubric from opposite sides — the writer has a banned-phrase list, the scorer flags the same phrases.

What the runtime gives you: ordering, via launch sequence and agent_wait, and nothing else. There is no DAG, no dependsOn, no declarative stage definition anywhere in Jouzu — “Workflow” is a terminal panel over a flat role list. The sequence lives in the orchestrator’s head and in your prompt.

Real-world examples

  • marketingResearch → draft → SEO pass → quality score, each stage handing on a structured document rather than a conversation.
  • salesAccount research → tailored deck → claim check against that research → send-ready format.
  • engineeringSpec → implementation → test generation → review, with the test author deliberately a different role from the implementer.
  • supportTicket triage → drafted response → tone check → policy check, before anything reaches a customer.
  • researchSource gathering → structured comparison → synthesis → every claim checked back to a source by someone who did not write it.
  • designRequirements → wireframe → visual design → accessibility pass.

05 Concern-sharded sweep

N agents, each reading the whole corpus, each looking at one property.

kernelshipped globally

The instinct when auditing many documents is to split the documents. Often that is exactly wrong. Split the concerns instead: every agent reads everything, but each one only looks for a single class of defect.

every document → link graph freshness schema readability the arcs are why the top row cannot be split by document
Four concerns over twelve documents. Every agent reads every document; each one carries a single checklist.

The constraint that forces it. Some defects do not exist inside a document — they exist between documents. An orphaned page, a dead internal link, two posts competing for one keyword: none of these can be seen by an agent holding one page, because the evidence is the graph. The moment one concern needs the global view, sharding by document stops being an option for that concern, and sharding by concern handles every other one for free.

Guards against: the defect class that is structurally invisible from inside a single item. A reviewer reading one post at a time cannot find orphans, cannibalisation or a staleness distribution, however good it is.

What the runtime gives you: genuine concurrency if the agents are read-only — which they should be, since a sweep that writes is a sweep you cannot re-run safely. The cross-item analysis afterwards is the orchestrator’s job: it is a join over the agents’ outputs, not something any one of them can do.

Real-world examples

  • marketingOne agent per concern across an entire site: broken links, missing alt text, stale pricing, inconsistent product naming. Each reads every page.
  • financeEvery deck and page checked for figures that disagree with each other. No single-document reviewer can find this — the defect only exists between documents.
  • engineeringA whole codebase swept one concern at a time: leaked secrets, licence compatibility, deprecated APIs, missing error handling.
  • salesEvery proposal sent this quarter checked for discounts outside policy, commitments with no named owner, and dates that have already passed.
  • brandEvery public asset checked against the guidelines — logo clear space, colour values, typeface, approved claims.
  • legalEvery customer-facing page swept for regulated language in one pass, rather than page by page as each is edited.

06 Chunk-sharded map-reduce

Split the corpus by range, one worker per chunk, then a pass over the seams.

kernelshipped in this repo

The other way to split, and the right one when the work is genuinely per-item and the corpus is too big for one context. The cost is at the boundaries: two workers given adjacent chunks will make different choices about the same recurring term, and nothing in either chunk reveals the inconsistency.

worker 1 worker 2 worker 3 worker 4 one chunk each → seam seam seam
Block-diagonal coverage. The dashed lines are where two workers made independent choices about the same thing, and the reason this pattern always needs a pass that spans them.

In production: the translation workflow above only shards once a document passes 600 segments, splits it by section, hands every shard the same immutable glossary, and then runs a consistency pass. Those three details are the pattern: shard late, share the decisions that must not vary, and reconcile the seams explicitly.

Guards against: context exhaustion — and then introduces seam drift, which the consistency pass exists to remove. If you take only one thing from this pattern, take the shared immutable artifact: a glossary, a style guide, a schema. It is what converts N independent workers into one coherent output.

What the runtime gives you: if the workers write, they are writers, so they serialise unless you also give them separate workspaces — this pattern composes with 01, and usually has to.

Real-world examples

  • localisationA 200-page manual split by section, every worker handed the same locked glossary, then a pass that reconciles the seams where two sections chose different wording.
  • researchA hundred interview transcripts summarised in batches, then one reducer producing a single findings document and surfacing where sources contradict each other.
  • salesA year of call recordings split by quarter, then a pass that reconciles the objection categories each batch invented independently.
  • engineeringMigrate a large test suite in batches, every batch handed the same conventions document.
  • marketingRewrite several hundred product descriptions onto a new template, one worker per category, all sharing one tone guide.
  • supportA year of tickets classified in batches, then a reducer that merges the taxonomies the batches each invented.

07 Competing drafts

The same brief to M children; take the first, or judge between them.

prompt onlyreasoned, not run

For work with no single right answer — naming, copy, a layout, an API shape — variance is the product. Run the same brief on M different models and either take whichever lands first, or collect all M and have a judge choose.

one brief qwen3.8-max cwd = wt/a kimi-k3 cwd = wt/b glm-5.2 cwd = wt/c agent_wait mode: "any" first to finish wins · stop the rest agent_wait mode: "all" → judge compare M drafts · prompt-level or
Three models, three workspaces, two possible endings. The workspaces are not optional — writers in one cwd would simply queue, and the race would measure nothing.
Guards against: a single model’s blind spots and a single draft’s anchoring. You cannot tell whether a draft is good until you have seen a different one.

What the runtime gives you: less than you want. agent_wait does support mode: "any", so the race is real. But there is no N-of-M, voting or best-of primitive anywhere in Jouzu — the judging flag fingerprints exactly one workspace, which is tamper-evidence, not candidate comparison. Selecting a winner is something your orchestrator prompt does, and if it drifts, nothing will tell you. That is why this is the only prompt only pattern here.

Real-world examples

  • designThree layout directions for one screen, generated in parallel and judged against the brief — instead of refining a single guess ten times.
  • marketingTaglines, subject lines, ad headlines. Three to reject beats one to defend, and you cannot tell whether a draft is good until you have seen a different one.
  • engineeringThree shapes for a new API, each in its own branch, judged on call-site ergonomics rather than on the implementation.
  • salesThree framings of the same pitch for three buyer personas, so the strongest one is chosen rather than assumed.
  • productFeature and product names. Naming has no single right answer, which is exactly when variance is the deliverable.
  • researchThe same question put to three models, where disagreement between them is itself the finding.

08 Measured loop

Any of the above, wrapped in an iteration with a number attached.

kernelrun here

Not a topology — a wrapper for one. The distinction that matters is between /goal and /multiloop: a goal is an objective worked until done, a loop is for work that has a metric and a verify command. If you cannot name the command that scores an iteration, you want a goal.

run the topology any of 01–07 verify command must exit 0 or 1 score vs baseline one number keep or revert no silent keeps one lane, independent state, survives compaction <lane>/run-<timestamp>  ·  iterations  keeps  reverts  logs  crashes  blocks
The verify command is what separates this from “run it again”. Everything else is bookkeeping — useful bookkeeping, because a fan-out is long and the run record is what survives a compaction.
Guards against: unverifiable improvement — the loop that runs five times, reports progress each time, and leaves the metric exactly where it started. In our own run the number went 1,063 naive → 1,017 → 170 against a correct baseline of 67, and the only reason that is a finding rather than a vibe is that a command produced it.

What the runtime gives you: lanes with independent state, compaction-aware resume prompts, and a tally of keeps, reverts, crashes and blocks. A /goal --tokens cap pauses rather than stopping dead, which matters because per-role models make a fan-out spend fast and unevenly.

Real-world examples

  • engineeringA flaky suite or a lint backlog: loop until the pass rate clears your floor, scored by actually running it each time rather than by how the diff reads.
  • dataPrompt or model tuning against a held-out evaluation set, where the number is the only thing deciding whether an iteration survives.
  • marketingPage weight, load time or an accessibility score, measured every pass so a “faster” change that is not faster gets reverted automatically.
  • contentAny quality rubric that produces a number. Loop until it clears the floor, keeping or reverting on the score.
  • designAn accessibility audit across a component library, re-scored each pass so nothing regresses quietly.
  • opsAnything where you can name the command that measures it. If you cannot name that command, you want a goal, not a loop.

Choosing one

Three questions decide it. The rest is taste.

Must writers run at the same time? more than one role holding write, edit or bash Then give each one its own cwd — 01 otherwise they queue, and the fan-out is decorative Does checking it require running it? a count, a benchmark, a test suite, a build Then a judge is not enough — 03 a read-only role cannot run what it is judging Is there a number for “better”? a command you could run twice and compare Then wrap it in a measured loop — 08 if not, use /goal and stop pretending

Two more, for the shape rather than the mechanics. Reviewing one artifact? Use 02 — several narrow reviewers beat one broad one, and the isolation costs nothing. Sweeping a corpus? Ask whether any defect you care about lives between items. If yes, shard by concern (05); if no, shard by chunk (06) and budget for the seams.

What you cannot do. There is no hierarchical orchestration: depth is exactly two. The subagent tool is registered once, in the main-session extension, and a child’s tool set is closed and hard-blocked at the call site. A sub-orchestrator is not a pattern you can reach for. For shell-capable roles this is additionally prohibited by instruction rather than prevented by the kernel — a child with bash could invoke jz as an unrelated process, which is a capability boundary, not a sandbox.

Which model, per role

Capability and family first. There are no benchmarks behind this — say so when you repeat it.

Only the nine tool-calling models in the Shisa catalogue can hold a role at all. Pick the thinking level against each model’s own supportedThinkingLevels — they are not uniform, and an unsupported level resolves to null without an error. The grid on the companion page has the full matrix.

RolePickWhy
orchestratorqwen3.8-max · mediumHolds the plan and every child report. Wants context, not peak reasoning.
worker, hardqwen3.7-max · highThe only one with run evidence here.
worker, boundedqwen3.8-flash · mediumFormatting, CLI surface, narrow edits.
worker, narrowqwen3.8-27b · medium262K context is plenty for one file; -nvfp4 is the quantised tier below it.
judgekimi-k3 · maxReaches max, and is a different family from qwen workers — which is most of the point of a judge.
verifierqwen3.8-flash · mediumIt runs commands and reports output.

Where Astra earns its place

gpt-6-astra is the one model with the full low → max thinking ladder plus explicit prompt-cache control. That makes it the strongest available judge, and the best orchestrator for a long multi-stage run where the plan has to survive a dozen child reports. On competing drafts it is also the most useful second family to put against the Shisa models — maximum independence between candidates.

And the trade, stated plainly. Jouzu only treats a model as official Astra when its baseUrl is https://api.openai.com/v1. Choosing it means that content leaves the Shisa platform and the Japan-sovereign path — which, for a company whose position is sovereign infrastructure on open models, is a decision rather than a footnote.

A defensible line: Astra is fine where the material is already public — judging open-source code, reviewing a published page, drafting external copy from released facts. It is not fine for customer data, unreleased research, pre-announcement material, or anything under an NDA. The patterns above do not care which you pick; your obligations do.

Provenance

Of the eight patterns here, one has been run on Jouzu end to end (03 and 08, in the same run — written up on the companion page). Three run in production as internal workflows — 02 as a translation review panel, 04 as a content pipeline, 05 as a site audit. 06 exists as the sharding path inside that translation workflow but has not been triggered, because no document has yet passed its 600-segment threshold. 01 and 07 are reasoned from the Jouzu source and have not been run.

Every claim about what the runtime does or does not support was read from the compiled source in the installed package — dist/subagents/manager.js for the admission check and the lock, dist/flow-control/wait-tools.js for agent_wait, dist/subagents/roles.js for role validation, dist/astra-compatibility.js for Astra. Where the answer was “not supported”, that is the absence of any implementation, not an absence of documentation.

This page exists because a page we had already published was wrong. multiagent.html claimed that disjoint file ownership is what makes concurrency real. It is not: the admission check compares working directories, not files, and a role holding only bash already counts as a writer. Two of the three children in our own run never overlapped. That correction is what pattern 01 is for, and the timeline diagram on the companion page has been redrawn to show what actually happened.