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.
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.
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.
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.
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.
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.
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.
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.
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.
CANNOT VERIFY is not a failure of the judge — it is the judge telling you which role you are missing.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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
cwd would simply queue, and the race would measure nothing.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.
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.
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.
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.
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.
| Role | Pick | Why |
|---|---|---|
| orchestrator | qwen3.8-max · medium | Holds the plan and every child report. Wants context, not peak reasoning. |
| worker, hard | qwen3.7-max · high | The only one with run evidence here. |
| worker, bounded | qwen3.8-flash · medium | Formatting, CLI surface, narrow edits. |
| worker, narrow | qwen3.8-27b · medium | 262K context is plenty for one file; -nvfp4 is the quantised tier below it. |
| judge | kimi-k3 · max | Reaches max, and is a different family from qwen workers — which is most of the point of a judge. |
| verifier | qwen3.8-flash · medium | It 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.
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.