agentsclimarketplace

Choosing swarm patterns

Skill AgentWorkforce/relay/.agents/skills/choosing-swarm-patterns

Real time communication for agents. Wake on message, channels, DMs and actions. Useful for orchestrating agents.

Install
npx -y skills add AgentWorkforce/relay --skill choosing-swarm-patterns

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

What its author says it does

Copied from the file, not written here

Use when coordinating multiple AI agents with Agent Relay's workflow engine and need to pick the right orchestration pattern - covers the 10 core patterns (fan-out, pipeline, hub-spoke, consensus, mesh, handoff, cascade, dag, debate, hierarchical) plus 14 specialized ones, with decision framework and accurate workflow/YAML examples.

SKILL.md

23.8 KB, as published. Nobody here has run it

Overview

The Agent Relay workflow engine (@relayflows/core) supports 24 swarm patterns via a single swarm.pattern field. Patterns are configured declaratively in YAML or programmatically via the workflow() fluent builder — there are no standalone fanOut(...) / hubAndSpoke(...) helpers. Pick the simplest pattern that solves the problem; add complexity only when the system proves it's insufficient.

Two ways to run a pattern

1. YAML (portable):

import { runWorkflow } from '@relayflows/core';

const run = await runWorkflow('workflows/feature-dev.yaml', {
  vars: { task: 'Add OAuth login' },
});

2. Fluent builder (programmatic):

import { workflow } from '@relayflows/core';

const run = await workflow('feature-dev')
  .pattern('hub-spoke')
  .channel('swarm-feature-dev')
  .agent('lead', { cli: 'claude', role: 'lead' })
  .agent('developer', { cli: 'codex', role: 'worker', interactive: false })
  .step('plan', { agent: 'lead', task: 'Plan {{task}}' })
  .step('implement', { agent: 'developer', task: 'Implement: {{steps.plan.output}}', dependsOn: ['plan'] })
  .run();

Both paths hit the same WorkflowRunner.

Quick Decision Framework

Is the task independent per agent?
  YES → fan-out (parallel workers, hub collects)

Does each step need the previous step's output?
  YES → Is it strictly linear?
    YES → pipeline
    NO  → dag (parallel where possible, `dependsOn` edges)

Does a coordinator need to stay alive and adapt?
  YES → hub-spoke (single-level hub + workers)
        hierarchical (structurally identical in current impl; use for naming/intent)

Is the task about making a decision?
  YES → Do agents need to argue opposing sides?
    YES → debate (adversarial, full mesh)
    NO  → consensus (cooperative, full mesh + coordination.consensusStrategy)

Does the right specialist emerge during processing?
  YES → handoff (sequential chain, one active at a time)

Do all agents need to freely collaborate?
  YES → mesh (full peer-to-peer edges)

Is cost the primary concern?
  YES → cascade (chain of increasingly capable agents; each step's prompt
        decides whether to pass through or redo the prior output)

Pattern Reference (Core 10)

#PatternTopology (actual edges)Best For
1fan-outHub broadcasts to N workers; workers reply to hub onlyIndependent subtasks (reviews, research, tests)
2pipelineLinear chain (agenti → agent{i+1})Ordered stages (design → implement → test)
3hub-spokeHub ↔ spokes (bidirectional); no spoke-to-spokeDynamic coordination, lead reviews/adjusts
4consensusFull mesh; decision via coordination.consensusStrategyArchitecture decisions, approval gates
5meshFull mesh (every agent ↔ every other)Brainstorming, collaborative debugging
6handoffChain; passes control forwardTriage, specialist routing
7cascadeChain of dependsOn steps; all run on success, downstream skipped on upstream failure (no built-in "fall through")Cost optimization: cheap first, each step's prompt passes through or redoes
8dagEdges from step dependsOnMixed dependencies, parallel where possible
9debateFull mesh (same topology as mesh; roles drive behavior)Rigorous adversarial examination
10hierarchicalHub + subordinates (single-level in current impl)Large teams; semantic distinction from hub-spoke

Heads up: hierarchical resolves to the same edge structure as hub-spoke in coordinator.ts:313-319. Multi-level tree topology is not currently implemented — use pattern name for intent, but expect the same runtime graph.

Additional Patterns (role-driven)

These 14 additional patterns exist in SwarmPattern (types.ts:114-139). The coordinator has role-based auto-selection heuristics (coordinator.ts:51-165), but they only fire when swarm.pattern is omitted — YAML validation requires it (runner.ts:2105-2117), so auto-selection is effectively a programmatic-API feature. In YAML, set swarm.pattern explicitly.

Topology is still resolved per-pattern once selected; the "Triggering roles" column reflects what the coordinator looks for to shape edges (per coordinator.ts:250-450):

PatternRoles the topology keys offTopology
map-reducemapper + reducercoordinator → mappers → reducers → coordinator
scatter-gatherhub → workers → hub
supervisorsupervisorsupervisor ↔ workers
reflectioncritic or reviewer (auto-select uses critic only)producers → critic → producers (loop)
red-teamattacker/red-team + defender/blue-teamadversarial mesh with optional judges
verifierverifierproducers → verifiers → back to producers
auctionauctioneerauctioneer → bidders → auctioneer
escalationtier-*tiered chain, escalate up / report down
sagasaga-orchestrator, compensate-handlerorchestrator ↔ participants
circuit-breakerprimary + fallback/backuptry primary, fallback on failure
blackboardblackboard / shared-workspaceshared state hub
swarmhive-mind / swarm-agentstigmergy-style
competitive— (declared explicitly)independent parallel implementations + judge
review-loopimplement* + 2+ reviewer*implementer ↔ reviewers

Structured Squad Review Loop

  • Split the work into bounded implementation squads. Each squad owns a non-overlapping file or subsystem scope.
  • Give each squad an implementer plus a shadow/review partner. The shadow follows the implementer in real time, checks alignment with the spec, and posts concise feedback before the work drifts.
  • Require the implementer to self-reflect before external review: compare the final diff against the spec, AGENTS.md / CLAUDE.md, recent local conventions, tests, and declared non-goals.
  • Run an independent self-review/fresh-eyes agent that reads the actual files and recent repo context, not just the chat transcript.
  • Send that review back to the implementer for one repair round.
  • After squads converge, run a final two-agent review team, usually one Claude reviewer and one Codex reviewer, independently. They compare notes, merge findings, and produce one final verdict.
  • Spawn fresh fix agents for final-review findings. Those fix agents self-reflect, then the final reviewers re-check the post-fix state until the spec is fully satisfied or a blocker is documented.
  • Use supervisor or hub-spoke when a lead needs to coordinate live squads.
  • Use review-loop when the main risk is code quality and feedback iteration.
  • Use reflection when critic feedback should loop directly back to producers.
  • Use verifier when completion evidence matters more than design debate.
  • Use competitive only when independent alternative implementations are useful; otherwise split by ownership scope.

Pattern Details

1. fan-out — Parallel Workers

await workflow('review')
  .pattern('fan-out')
  .agent('lead', { cli: 'claude', role: 'lead' })
  .agent('auth-rev', { cli: 'claude', role: 'worker', interactive: false })
  .agent('db-rev', { cli: 'claude', role: 'worker', interactive: false })
  .step('review-auth', { agent: 'auth-rev', task: 'Review auth.ts' })
  .step('review-db', { agent: 'db-rev', task: 'Review db.ts' })
  .run();

2. pipeline — Sequential Stages

swarm: { pattern: pipeline }
agents:
  - { name: designer, cli: claude }
  - { name: implementer, cli: codex, interactive: false }
  - { name: tester, cli: codex, interactive: false }
workflows:
  - name: build
    steps:
      - {
          name: design,
          agent: designer,
          task: 'Design the API schema',
          verification: { type: output_contains, value: DONE },
        }
      - {
          name: implement,
          agent: implementer,
          dependsOn: [design],
          task: 'Implement: {{steps.design.output}}',
        }
      - { name: test, agent: tester, dependsOn: [implement], task: 'Write integration tests' }

3. hub-spoke — Persistent Coordinator

await workflow('api-build')
  .pattern('hub-spoke')
  .channel('swarm-api')
  .agent('lead', { cli: 'claude', role: 'lead' })
  .agent('db-worker', { cli: 'claude', role: 'worker' }) // interactive by default — hub DMs it
  .agent('api-worker', { cli: 'claude', role: 'worker' }) // interactive by default — hub DMs it
  .step('models', { agent: 'db-worker', task: 'Build database models' })
  .step('routes', { agent: 'api-worker', task: 'Build route handlers', dependsOn: ['models'] })
  .step('review', { agent: 'lead', task: 'Review everything', dependsOn: ['routes'] })
  .run();

4. consensus — Cooperative Voting

swarm: { pattern: consensus }
agents:
  - { name: perf, cli: claude, role: reviewer }
  - { name: dx, cli: claude, role: reviewer }
  - { name: sec, cli: claude, role: reviewer }
coordination:
  consensusStrategy: majority # declarative marker: majority | unanimous | quorum
  votingThreshold: 0.66
workflows:
  - name: decide
    steps:
      - { name: evaluate-perf, agent: perf, task: 'Evaluate perf of Fastify migration' }
      - { name: evaluate-dx, agent: dx, task: 'Evaluate DX of Fastify migration' }
      - { name: evaluate-sec, agent: sec, task: 'Evaluate security of Fastify migration' }

5. mesh — Peer Collaboration

await workflow('debug-auth')
  .pattern('mesh')
  .channel('swarm-debug')
  .agent('logs', { cli: 'claude' })
  .agent('code', { cli: 'claude' })
  .agent('repro', { cli: 'claude' })
  .step('logs', { agent: 'logs', task: 'Check server logs' })
  .step('code', { agent: 'code', task: 'Review auth code' })
  .step('repro', { agent: 'repro', task: 'Write repro test' })
  .run();

6. handoff — Dynamic Routing

swarm: { pattern: handoff }
agents:
  - { name: triage, cli: claude }
  - { name: billing, cli: claude }
  - { name: tech, cli: claude }
workflows:
  - name: support
    steps:
      - { name: triage, agent: triage, task: 'Triage: {{request}}' }
      - { name: billing, agent: billing, dependsOn: [triage], task: 'Handle billing' }
      - { name: tech, agent: tech, dependsOn: [triage], task: 'Handle tech issues' }

7. cascade — Cost-Aware Fallthrough

await workflow('answer')
  .pattern('cascade')
  .agent('haiku', { cli: 'claude', model: 'claude-haiku-4-5-20251001' })
  .agent('sonnet', { cli: 'claude', model: 'claude-sonnet-4-6' })
  .agent('opus', { cli: 'claude', model: 'claude-opus-4-7' })
  .step('try-haiku', { agent: 'haiku', task: '{{question}}' })
  .step('try-sonnet', {
    agent: 'sonnet',
    task: 'If this is a complete answer, echo it verbatim. Otherwise answer anew:\n{{steps.try-haiku.output}}',
    dependsOn: ['try-haiku'],
  })
  .step('try-opus', {
    agent: 'opus',
    task: 'Final-tier answer, using prior attempts for context:\n{{steps.try-sonnet.output}}',
    dependsOn: ['try-sonnet'],
  })
  .run();

8. dag — Directed Acyclic Graph

await workflow('fullstack')
  .pattern('dag')
  .maxConcurrency(3)
  .agent('dev', { cli: 'codex', role: 'worker' })
  .step('scaffold', { agent: 'dev', task: 'Create project scaffold' })
  .step('frontend', { agent: 'dev', task: 'Build React UI', dependsOn: ['scaffold'] })
  .step('backend', { agent: 'dev', task: 'Build API', dependsOn: ['scaffold'] })
  .step('integrate', { agent: 'dev', task: 'Wire together', dependsOn: ['frontend', 'backend'] })
  .run();

9. debate — Adversarial Refinement

swarm: { pattern: debate }
agents:
  - { name: pro, cli: claude, role: debater, task: 'Argue FOR monorepo' }
  - { name: con, cli: claude, role: debater, task: 'Argue FOR polyrepo' }
  - { name: judge, cli: claude, role: judge, task: 'Decide after 3 rounds' }
coordination:
  barriers:
    - { name: debate-done, waitFor: [pro-round-3, con-round-3] }

10. hierarchical — Multi-Level (structurally hub-spoke today)

await workflow('large-team')
  .pattern('hierarchical')
  .agent('lead', { cli: 'claude', role: 'lead' })
  .agent('fe-coord', { cli: 'claude', role: 'coordinator' })
  .agent('be-coord', { cli: 'claude', role: 'coordinator' })
  .agent('fe-dev', { cli: 'codex', role: 'worker', interactive: false })
  .agent('be-dev', { cli: 'codex', role: 'worker', interactive: false })
  .step('plan', { agent: 'lead', task: 'Coordinate full-stack app' })
  .step('fe-plan', { agent: 'fe-coord', task: 'Manage frontend', dependsOn: ['plan'] })
  .step('be-plan', { agent: 'be-coord', task: 'Manage backend', dependsOn: ['plan'] })
  .step('fe-impl', { agent: 'fe-dev', task: 'Build components', dependsOn: ['fe-plan'] })
  .step('be-impl', { agent: 'be-dev', task: 'Build API', dependsOn: ['be-plan'] })
  .run();

Verification & Completion Signals

An agent step can complete in several ways in the @relayflows/core runner:

verification:
  type: output_contains # or: exit_code | file_exists | custom
  value: DONE # or: PLAN_COMPLETE, IMPLEMENTATION_COMPLETE, REVIEW_COMPLETE

Agent Relay MCP - Correct Tool Names

The old category-expanded names are wrong. Current Agent Relay MCP tools are flat names. In a client that decorates MCP tools, the prefix comes from the configured server key; workflow prompts commonly show mcp__relaycast__send_dm, while an agent-relay server key may expose mcp__agent_relay__send_dm.

PurposeCanonical toolCommon workflow-prefixed form
Send DM to another agentsend_dmmcp__relaycast__send_dm
Check inboxcheck_inboxmcp__relaycast__check_inbox
List agentslist_agentsmcp__relaycast__list_agents
Post to a channelpost_messagemcp__relaycast__post_message
Reply in a threadreply_to_threadmcp__relaycast__reply_to_thread
Spawn sub-agentadd_agentmcp__relaycast__add_agent
Remove sub-agentremove_agentmcp__relaycast__remove_agent

interactive: false agents run as non-interactive subprocesses with no relay connection. They must not call Relay MCP tools.

Reflection (Trajectories)

Reflection is not a reflectionThreshold callback. It's configured via the trajectories: block:

trajectories:
  enabled: true
  reflectOnBarriers: true # config flag exists but runner does NOT currently invoke this path
  reflectOnConverge: true # fires at parallel convergence points (runner.ts:2762-2779)
  autoDecisions: true # record retry/skip/fail decisions

Common Mistakes

MistakeWhy It FailsFix
Using mesh/debate for everythingFull-mesh blows up message volume past ~5 agentsUse hub-spoke or dag for most tasks
Pipeline for independent workSequential bottleneckUse fan-out or dag
Hub-spoke for 2 agentsHub is unnecessary overheadUse pipeline or fan-out
Expecting consensusStrategy to tally votesRunner has no vote-tally logic; field only affects coordinator auto-selectionAggregate votes in a judge/lead step that reads {{steps.*.output}}
Handoff with "routing = skip other branches"Skipping only fires on upstream failure, not routing decisionsEmit a routing token in triage output; downstream prompts self-no-op if token doesn't match
Cascade expecting skip-on-successRunner has no cascade skip logic; failed upstream skips downstreamChain downstream prompts to pass-through or redo based on {{steps.previous.output}}
Relying on reflectOnBarriersConfig flag exists but runner never calls itUse reflectOnConverge for convergence reflection; use reflection pattern for critic loops
interactive: false agent calling MCPNon-interactive subprocess has no relayUse interactive: true (default) or emit output on stdout
Relying on multi-level hierarchicalTopology is single-level hub in current implUse pattern for naming; model levels via dependsOn graph
Writing mcp__relaycast__send(...)Wrong tool nameUse post_message / mcp__relaycast__post_message or send_dm / mcp__relaycast__send_dm

Resume & Re-run

```ts

// Resume a failed run:
await runWorkflow('feature-dev.yaml', { resume: '<runId>' });

// Skip ahead, re-using cached outputs from an earlier run:
await runWorkflow('feature-dev.yaml', {
  startFrom: 'review',
  previousRunId: '<runId>',
});

Complete YAML Example

```yaml

version: '1.0'
name: feature-dev
description: 'Blueprint-style feature development with quality gates.'
swarm:
  pattern: hub-spoke
  maxConcurrency: 2
  timeoutMs: 3600000
  channel: swarm-feature-dev
  idleNudge: { nudgeAfterMs: 120000, escalateAfterMs: 120000, maxNudges: 1 }
agents:
  - { name: lead, cli: claude, role: lead, permissions: { access: full } }
  - { name: planner, cli: codex, role: planner, interactive: false, permissions: { access: readonly } }
  - { name: developer, cli: codex, role: worker, interactive: false, permissions: { access: readwrite } }
  - { name: reviewer, cli: claude, role: reviewer, permissions: { access: readonly } }
workflows:
  - name: feature-delivery
    onError: retry
    preflight:
      - { command: 'git status --porcelain', failIf: non-empty, description: 'Clean worktree' }
    steps:
      - name: plan
        agent: planner
        task: 'Plan: {{task}}'
        verification: { type: output_contains, value: PLAN_COMPLETE }
      - name: implement
        agent: developer
        dependsOn: [plan]
        task: 'Implement: {{steps.plan.output}}'
        verification: { type: output_contains, value: IMPLEMENTATION_COMPLETE }
      - name: test
        type: deterministic
        dependsOn: [implement]
        command: npm test
      - name: review
        agent: reviewer
        dependsOn: [test]
        task: 'Review implementation'
        verification: { type: output_contains, value: REVIEW_COMPLETE }
coordination:
  barriers:
    - { name: delivery-ready, waitFor: [plan, implement, review], timeoutMs: 900000 }
trajectories:
  enabled: true
  reflectOnBarriers: true
  reflectOnConverge: true
errorHandling:
  strategy: retry
  maxRetries: 2
  retryDelayMs: 5000

Source of Truth

ClaimFile
Pattern enum (24 patterns)@relayflows/core/dist/schema.d.ts (SwarmPattern)
Topology resolution per pattern@relayflows/core/dist/coordinator.js
Interactive-only topology edges@relayflows/core/dist/coordinator.js filters interactive: false agents
Pattern auto-selection heuristics@relayflows/core/dist/coordinator.js
WorkflowBuilder fluent API@relayflows/core/dist/builder.d.ts
runWorkflow(yamlPath, options)@relayflows/core/dist/run.d.ts
YAML validation requires version + name + swarm.pattern@relayflows/core/dist/runner.js
MCP tool namespackages/cli/src/cli/agent-relay-mcp.ts, @relayflows/core/dist/channel-messenger.js
Completion modes (verification / evidence / owner / process-exit)@relayflows/core/dist/runner.js, @relayflows/core/dist/step-executor.js
Trajectory reflection@relayflows/core/dist/trajectory.js, @relayflows/core/dist/runner.js

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.