|
| 1 | +--- |
| 2 | +name: choosing-swarm-patterns |
| 3 | +description: Use when coordinating multiple AI agents and need to pick the right orchestration pattern - covers 10 patterns (fan-out, pipeline, hub-spoke, consensus, mesh, handoff, cascade, dag, debate, hierarchical) with decision framework and reflection protocol |
| 4 | +--- |
| 5 | + |
| 6 | +### Overview |
| 7 | + |
| 8 | +10 orchestration patterns for multi-agent workflows. Pick the simplest pattern that solves the problem — add complexity only when the system proves it's insufficient. |
| 9 | + |
| 10 | +### Quick Decision Framework |
| 11 | + |
| 12 | +#### ``` |
| 13 | + |
| 14 | +``` |
| 15 | +Is the task independent per agent? |
| 16 | + YES → fan-out (parallel workers) |
| 17 | +
|
| 18 | +Does each step need the previous step's output? |
| 19 | + YES → Is it strictly linear? |
| 20 | + YES → pipeline |
| 21 | + NO → dag (parallel where possible) |
| 22 | +
|
| 23 | +Does a coordinator need to stay alive and adapt? |
| 24 | + YES → Is there one level of management? |
| 25 | + YES → hub-spoke |
| 26 | + NO → hierarchical (multi-level) |
| 27 | +
|
| 28 | +Is the task about making a decision? |
| 29 | + YES → Do agents need to argue opposing sides? |
| 30 | + YES → debate (adversarial) |
| 31 | + NO → consensus (cooperative voting) |
| 32 | +
|
| 33 | +Does the right specialist emerge during processing? |
| 34 | + YES → handoff (dynamic routing) |
| 35 | +
|
| 36 | +Do all agents need to freely collaborate? |
| 37 | + YES → mesh (peer-to-peer) |
| 38 | +
|
| 39 | +Is cost the primary concern? |
| 40 | + YES → cascade (cheap model first, escalate if needed) |
| 41 | +``` |
| 42 | + |
| 43 | + |
| 44 | +### Pattern Reference |
| 45 | + |
| 46 | +| # | Pattern | Topology | Agents | Best For | |
| 47 | +|---|---------|----------|--------|----------| |
| 48 | +| 1 | **fan-out** | Star (SDK center) | N parallel | Independent subtasks (reviews, research, tests) | |
| 49 | +| 2 | **pipeline** | Linear chain | Sequential | Ordered stages (design → implement → test) | |
| 50 | +| 3 | **hub-spoke** | Star (live hub) | 1 lead + N workers | Dynamic coordination, lead reviews/adjusts | |
| 51 | +| 4 | **consensus** | Broadcast + vote | N voters | Architecture decisions, approval gates | |
| 52 | +| 5 | **mesh** | Fully connected | N peers | Brainstorming, collaborative debugging | |
| 53 | +| 6 | **handoff** | Routing chain | 1 active at a time | Triage, specialist routing, support flows | |
| 54 | +| 7 | **cascade** | Tiered escalation | Cheapest → most capable | Cost optimization, production workloads | |
| 55 | +| 8 | **dag** | Dependency graph | Parallel + joins | Complex projects with mixed dependencies | |
| 56 | +| 9 | **debate** | Adversarial rounds | 2+ debaters + judge | Rigorous evaluation, architecture trade-offs | |
| 57 | +| 10 | **hierarchical** | Tree (multi-level) | Lead → coordinators → workers | Large teams, domain separation | |
| 58 | + |
| 59 | +### Pattern Details |
| 60 | + |
| 61 | +#### 1. fan-out — Parallel Workers |
| 62 | + |
| 63 | +```ts |
| 64 | +fanOut([ |
| 65 | + { task: "Review auth.ts", name: "AuthReviewer" }, |
| 66 | + { task: "Review db.ts", name: "DbReviewer" }, |
| 67 | +], { cli: "claude" }); |
| 68 | +``` |
| 69 | + |
| 70 | +#### 2. pipeline — Sequential Stages |
| 71 | + |
| 72 | +```ts |
| 73 | +pipeline([ |
| 74 | + { task: "Design the API schema", name: "Designer" }, |
| 75 | + { task: "Implement the endpoints", name: "Implementer" }, |
| 76 | + { task: "Write integration tests", name: "Tester" }, |
| 77 | +]); |
| 78 | +``` |
| 79 | + |
| 80 | +#### 3. hub-spoke — Persistent Coordinator |
| 81 | + |
| 82 | +```ts |
| 83 | +hubAndSpoke({ |
| 84 | + hub: { task: "Coordinate building a REST API", name: "Lead" }, |
| 85 | + workers: [ |
| 86 | + { task: "Build database models", name: "DbWorker" }, |
| 87 | + { task: "Build route handlers", name: "ApiWorker" }, |
| 88 | + ], |
| 89 | +}); |
| 90 | +``` |
| 91 | + |
| 92 | +#### 4. consensus — Cooperative Voting |
| 93 | + |
| 94 | +```ts |
| 95 | +consensus({ |
| 96 | + proposal: "Should we migrate to Fastify?", |
| 97 | + voters: [ |
| 98 | + { task: "Evaluate performance", name: "PerfExpert" }, |
| 99 | + { task: "Evaluate DX", name: "DxExpert" }, |
| 100 | + ], |
| 101 | + consensusType: "majority", |
| 102 | +}); |
| 103 | +``` |
| 104 | + |
| 105 | +#### 5. mesh — Peer Collaboration |
| 106 | + |
| 107 | +```ts |
| 108 | +mesh({ |
| 109 | + goal: "Debug the auth flow returning 500", |
| 110 | + agents: [ |
| 111 | + { task: "Check server logs", name: "LogAnalyst" }, |
| 112 | + { task: "Review auth code", name: "CodeReviewer" }, |
| 113 | + { task: "Write repro test", name: "Tester" }, |
| 114 | + ], |
| 115 | +}); |
| 116 | +``` |
| 117 | + |
| 118 | +#### 6. handoff — Dynamic Routing |
| 119 | + |
| 120 | +```ts |
| 121 | +handoff({ |
| 122 | + entryPoint: { task: "Triage the request", name: "Triage" }, |
| 123 | + routes: [ |
| 124 | + { agent: { task: "Handle billing", name: "Billing" }, condition: "billing, payment" }, |
| 125 | + { agent: { task: "Handle tech issues", name: "TechSupport" }, condition: "error, bug" }, |
| 126 | + ], |
| 127 | + maxHandoffs: 3, |
| 128 | +}); |
| 129 | +``` |
| 130 | + |
| 131 | +#### 7. cascade — Cost-Aware Escalation |
| 132 | + |
| 133 | +```ts |
| 134 | +cascade({ |
| 135 | + tiers: [ |
| 136 | + { agent: { task: "Answer this", cli: "claude" }, confidenceThreshold: 0.7, costWeight: 1 }, |
| 137 | + { agent: { task: "Answer this", cli: "claude" }, confidenceThreshold: 0.85, costWeight: 5 }, |
| 138 | + { agent: { task: "Answer this", cli: "claude" }, costWeight: 20 }, |
| 139 | + ], |
| 140 | +}); |
| 141 | +``` |
| 142 | + |
| 143 | +#### 8. dag — Directed Acyclic Graph |
| 144 | + |
| 145 | +```ts |
| 146 | +dag({ |
| 147 | + nodes: [ |
| 148 | + { id: "scaffold", task: "Create project scaffold" }, |
| 149 | + { id: "frontend", task: "Build React UI", dependsOn: ["scaffold"] }, |
| 150 | + { id: "backend", task: "Build API", dependsOn: ["scaffold"] }, |
| 151 | + { id: "integrate", task: "Wire together", dependsOn: ["frontend", "backend"] }, |
| 152 | + ], |
| 153 | + maxConcurrency: 3, |
| 154 | +}); |
| 155 | +``` |
| 156 | + |
| 157 | +#### 9. debate — Adversarial Refinement |
| 158 | + |
| 159 | +```ts |
| 160 | +debate({ |
| 161 | + topic: "Monorepo vs polyrepo for the new platform?", |
| 162 | + debaters: [ |
| 163 | + { task: "Argue for monorepo", position: "monorepo" }, |
| 164 | + { task: "Argue for polyrepo", position: "polyrepo" }, |
| 165 | + ], |
| 166 | + judge: { task: "Judge and decide", name: "ArchJudge" }, |
| 167 | + maxRounds: 3, |
| 168 | +}); |
| 169 | +``` |
| 170 | + |
| 171 | +#### 10. hierarchical — Multi-Level Delegation |
| 172 | + |
| 173 | +```ts |
| 174 | +hierarchical({ |
| 175 | + agents: [ |
| 176 | + { id: "lead", task: "Coordinate full-stack app", role: "lead" }, |
| 177 | + { id: "fe-coord", task: "Manage frontend", role: "coordinator", reportsTo: "lead" }, |
| 178 | + { id: "be-coord", task: "Manage backend", role: "coordinator", reportsTo: "lead" }, |
| 179 | + { id: "fe-dev", task: "Build components", role: "worker", reportsTo: "fe-coord" }, |
| 180 | + { id: "be-dev", task: "Build API", role: "worker", reportsTo: "be-coord" }, |
| 181 | + ], |
| 182 | +}); |
| 183 | +``` |
| 184 | + |
| 185 | + |
| 186 | +### Reflection Protocol |
| 187 | + |
| 188 | +#### All patterns support reflection — periodic synthesis that enables course correction. Enabled via `reflectionThreshold` on WorkflowOptions. |
| 189 | + |
| 190 | +```ts |
| 191 | +{ |
| 192 | + reflectionThreshold: 10, // trigger after 10 agent messages |
| 193 | + onReflect: async (ctx) => { |
| 194 | + // Examine ctx.recentMessages, ctx.agentStatuses |
| 195 | + // Return adjustments or null |
| 196 | + }, |
| 197 | +} |
| 198 | +``` |
| 199 | + |
| 200 | + |
| 201 | +### Common Mistakes |
| 202 | + |
| 203 | +| Mistake | Why It Fails | Fix | |
| 204 | +|---------|-------------|-----| |
| 205 | +| Using mesh for everything | O(n^2) communication, debugging nightmare | Use hub-spoke for most tasks | |
| 206 | +| Pipeline for independent work | Sequential bottleneck | Use fan-out or dag | |
| 207 | +| Hub-spoke for simple parallel tasks | Hub is unnecessary overhead | Use fan-out | |
| 208 | +| Consensus for non-decisions | Voting on implementation tasks wastes time | Use hub-spoke, let lead decide | |
| 209 | +| No circuit breaker on handoff | Infinite routing loops | Always set maxHandoffs | |
| 210 | +| Cascade without confidence parsing | Agents don't report confidence | Convention injection handles this | |
| 211 | +| Hierarchical for 3 agents | Management overhead exceeds benefit | Use hub-spoke for small teams | |
| 212 | + |
| 213 | +### DAG Executor — Proven Pattern |
| 214 | + |
| 215 | +#### Agent Completion: Detect → Release → Collect |
| 216 | + |
| 217 | +``` |
| 218 | +Agent writes summary file → Orchestrator polls (5s) → Detects new mtime → |
| 219 | + Reads summary → Calls client.release(agent) → agent_exited fires → Node marked complete |
| 220 | +``` |
| 221 | + |
| 222 | +#### State & Resume |
| 223 | + |
| 224 | +```ts |
| 225 | +saveState(completed, depsOutput, results, startTime); |
| 226 | +// Restart with --resume to skip completed nodes |
| 227 | +``` |
| 228 | + |
| 229 | + |
| 230 | +### YAML Workflow Definition |
| 231 | + |
| 232 | +#### Any pattern can be defined in YAML for portability: |
| 233 | + |
| 234 | +```yaml |
| 235 | +version: "1.0" |
| 236 | +name: feature-dev |
| 237 | +pattern: hub-spoke |
| 238 | +agents: |
| 239 | + - id: lead |
| 240 | + role: lead |
| 241 | + cli: claude |
| 242 | + - id: developer |
| 243 | + role: worker |
| 244 | + cli: codex |
| 245 | + reportsTo: lead |
| 246 | +steps: |
| 247 | + - id: plan |
| 248 | + agent: lead |
| 249 | + prompt: "Create a development plan for: {{task}}" |
| 250 | + expects: "PLAN_COMPLETE" |
| 251 | + - id: implement |
| 252 | + agent: developer |
| 253 | + dependsOn: [plan] |
| 254 | + prompt: "Implement: {{steps.plan.output}}" |
| 255 | + expects: "DONE" |
| 256 | +reflection: |
| 257 | + enabled: true |
| 258 | + threshold: 10 |
| 259 | +trajectory: |
| 260 | + enabled: true |
| 261 | +``` |
0 commit comments