| name | swarm |
| description | Spawn isolated agents for parallel task execution. Level 1: Task tool (pure Claude-native). Level 2: tmux + Agent Mail (process isolation, persistence). Triggers: "swarm", "spawn agents", "parallel work". |
Swarm Skill
Spawn isolated agents to execute tasks in parallel. Fresh context per agent (Ralph Wiggum pattern).
Execution Levels:
- Level 1 (default) - Pure Claude-native using Task tool background agents
- Level 2 (
--level=2) - tmux sessions + Agent Mail for robust coordination
Integration modes:
- Direct - Create TaskList tasks, invoke
/swarm
- Via Crank -
/crank creates tasks from beads, invokes /swarm for each wave
Architecture (Mayor-First)
Mayor (this session)
|
+-> Plan: TaskCreate with dependencies
|
+-> Identify wave: tasks with no blockers
|
+-> Spawn: Task tool (run_in_background=true) for each
| Each agent completes its task atomically
|
+-> Wait: <task-notification> arrives
|
+-> Validate: Review changes when complete
|
+-> Repeat: New plan if more work needed
Execution
Given /swarm:
Step 1: Ensure Tasks Exist
Use TaskList to see current tasks. If none, create them:
TaskCreate(subject="Implement feature X", description="Full details...")
TaskUpdate(taskId="2", addBlockedBy=["1"]) # Add dependencies after creation
Step 2: Identify Wave
Find tasks that are:
- Status:
pending
- No blockedBy (or all blockers completed)
These can run in parallel.
Step 3: Spawn Agents
For each ready task, spawn a background agent:
Task(
subagent_type="general-purpose",
run_in_background=true,
prompt="Execute task #<id>: <subject>
<description>
Work autonomously. Create/edit files as needed. Verify your work."
)
Important: Agents cannot access TaskList/TaskUpdate. Mayor must:
- Wait for
<task-notification>
- Verify work was done
- Call
TaskUpdate(taskId, status="completed")
Step 4: Wait for Notifications
Agents send <task-notification> automatically when complete:
- No polling needed
- Mayor receives notification with task result
- Then Mayor updates TaskList and spawns next wave
Step 5: Validate & Review
When agents complete:
- Check git status for changes
- Review diffs
- Run tests/validation
- Commit combined work if needed
Step 6: Repeat if Needed
If more tasks remain:
- Check TaskList for next wave
- Spawn new agents
- Continue until all done
Example Flow
Mayor: "Let's build a user auth system"
1. /plan → Creates tasks:
#1 [pending] Create User model
#2 [pending] Add password hashing (blockedBy: #1)
#3 [pending] Create login endpoint (blockedBy: #1)
#4 [pending] Add JWT tokens (blockedBy: #3)
#5 [pending] Write tests (blockedBy: #2, #3, #4)
2. /swarm → Spawns agent for #1 (only unblocked task)
3. Agent #1 completes → #1 now completed
→ #2 and #3 become unblocked
4. /swarm → Spawns agents for #2 and #3 in parallel
5. Continue until #5 completes
6. /vibe → Validate everything
Key Points
- Pure Claude-native - No tmux, no external scripts
- Background agents -
run_in_background=true for isolation
- Wave execution - Only unblocked tasks spawn
- Mayor orchestrates - You control the flow
- Atomic execution - Each agent works until task done
Integration with AgentOps
This ties into the full workflow:
/research → Understand the problem
/plan → Decompose into beads issues
/crank → Autonomous epic loop
└── /swarm → Execute each wave in parallel
/vibe → Validate results
/post-mortem → Extract learnings
Direct use (no beads):
TaskCreate → Define tasks
/swarm → Execute in parallel
The knowledge flywheel captures learnings from each agent.
Task Management Commands
# List all tasks
TaskList()
# Mark task complete after notification
TaskUpdate(taskId="1", status="completed")
# Add dependency between tasks
TaskUpdate(taskId="2", addBlockedBy=["1"])
When to Use Swarm
| Scenario | Use |
|---|
| Multiple independent tasks | /swarm (parallel) |
| Sequential dependencies | /swarm with blockedBy |
| Mix of both | /swarm spawns waves, each wave parallel |
Why This Works: Ralph Wiggum Pattern
This architecture follows the Ralph Wiggum Pattern for autonomous agents.
Core Insight: Each Task(run_in_background=true) spawn = fresh context.
Ralph's bash loop: Our swarm:
while :; do Mayor spawns Task → fresh context
cat PROMPT.md | claude Mayor spawns Task → fresh context
done Mayor spawns Task → fresh context
Both achieve the same thing: fresh context per execution unit.
Why Fresh Context Matters
| Approach | Context | Problem |
|---|
| Internal loop in agent | Accumulates | Degrades over iterations |
| Mayor spawns agents | Fresh each time | Stays effective at scale |
Making demigods loop internally would violate Ralph - context accumulates within the session. The loop belongs in Mayor (lightweight orchestration), fresh context belongs in demigods (heavyweight work).
Key Properties
- Mayor IS the loop - Orchestration layer, manages state
- Demigods are atomic - One task, one spawn, one result
- TaskList as memory - State persists in task status, not context
- Filesystem for artifacts - Files written, commits made
This is Ralph + parallelism: the while loop is distributed across wave spawns, with multiple agents per wave.
Integration with Crank
When /crank invokes /swarm:
- Crank bridges beads issues to TaskList tasks
- Swarm executes the TaskList wave with fresh-context agents
- Crank syncs results back to beads
/crank epic-123
└── bd ready → [ao-1, ao-2, ao-3]
└── TaskCreate for each issue
└── /swarm
└── Spawn agents (fresh context each)
└── Complete TaskList tasks
└── bd update --status closed
└── Loop until epic DONE
This gives you:
- Beads orchestration (crank) - Epic lifecycle, issue tracking
- Fresh-context execution (swarm) - Ralph pattern for each issue
Distinctions (Common Confusion)
| You Want | Use | Why |
|---|
| Fresh-context parallel execution | /swarm | Each spawned background agent is a clean slate |
| Autonomous epic loop | /crank | Loops waves via swarm until epic closes |
| Just swarm, no beads | /swarm directly | Use TaskList only, skip beads integration |
| RPI progress gates | /ratchet | Tracks/locks progress; does not execute work by itself |
Level 2 Mode: tmux + Agent Mail
When: MCP Agent Mail is available AND you want true process isolation, persistent workers, and robust coordination.
Level 2 mode spawns real tmux sessions instead of Task tool background agents. Each demigod runs in its own Claude process with full lifecycle management.
Why Level 2?
| Level 1 (Task tool) | Level 2 (tmux + Agent Mail) |
|---|
| Background agents in Mayor's process | Separate tmux sessions |
| Coupled to Mayor lifecycle | Persistent if Mayor crashes |
| No inter-agent coordination | Agent Mail messaging |
| No file conflict prevention | File reservations |
| Simple, fast to spawn | More setup, more robust |
| Good for small jobs | Better for large/long jobs |
Level Detection
At skill start, detect which level to use:
LEVEL=1
if mcp-tools 2>/dev/null | grep -q "mcp-agent-mail"; then
AGENT_MAIL_AVAILABLE=true
fi
if curl -s http://localhost:8765/health >/dev/null 2>&1; then
AGENT_MAIL_HTTP=true
fi
if [ "$LEVEL_FLAG" = "2" ] && [ "$AGENT_MAIL_AVAILABLE" = "true" -o "$AGENT_MAIL_HTTP" = "true" ]; then
LEVEL=2
fi
Decision matrix:
--level | Agent Mail | Result |
|---|
| Not set | Not available | Level 1 |
| Not set | Available | Level 1 (explicit opt-in required) |
--level=1 | Any | Level 1 |
--level=2 | Not available | Error: Agent Mail required |
--level=2 | Available | Level 2 |
Level 2 Invocation
/swarm --level=2 [--max-workers=N]
/swarm --level=2 --bead-ids ol-527.1,ol-527.2,ol-527.3
Parameters:
| Parameter | Description | Default |
|---|
--level=2 | Enable tmux + Agent Mail mode | Required |
--max-workers=N | Max concurrent demigods | 5 |
--bead-ids | Specific beads to work (comma-separated) | Auto from bd ready |
--wait | Wait for all demigods to complete | false |
--timeout | Max time to wait (if --wait) | 30m |
Level 2 Architecture
Mayor Session (this session)
|
+-> Level Detection: Agent Mail available → Level 2
|
+-> Identify wave: bd ready → [ol-527.1, ol-527.2, ol-527.3]
|
+-> Spawn: tmux new-session for each (via /spawn skill internally)
| demigod-ol-527-1 → runs /demigod ol-527.1
| demigod-ol-527-2 → runs /demigod ol-527.2
| demigod-ol-527-3 → runs /demigod ol-527.3
|
+-> Coordinate: Agent Mail messages
| Each demigod sends ACCEPTED, PROGRESS, DONE/FAILED
| Mayor monitors via fetch_inbox
| File reservations prevent conflicts
|
+-> Validate: On DONE, optionally run /vibe --remote
|
+-> Repeat: New wave when workers complete
Level 2 Execution Steps
Given /swarm --level=2:
L2 Step 1: Pre-flight Checks
which tmux >/dev/null 2>&1 || {
echo "Error: tmux required for Level 2. Install: brew install tmux"
exit 1
}
which claude >/dev/null 2>&1 || {
echo "Error: claude CLI required for Level 2"
exit 1
}
AGENT_MAIL_OK=false
if curl -s http://localhost:8765/health >/dev/null 2>&1; then
AGENT_MAIL_OK=true
fi
if [ "$AGENT_MAIL_OK" != "true" ]; then
echo "Error: Agent Mail required for Level 2"
echo "Start server: cd ~/gt/acfs-research/tier1/mcp_agent_mail && uv run python -m mcp_agent_mail.http"
exit 1
fi
L2 Step 2: Register Mayor with Agent Mail
Register the Mayor session to receive messages from demigods.
MCP Tool: register_agent
Parameters:
project_key: <absolute path to project>
program: "claude-code"
model: "opus-4.5"
task_description: "Mayor orchestrating swarm for wave"
Store the returned agent name as MAYOR_NAME.
L2 Step 3: Identify Wave (Ready Beads)
Same as Level 1, get the beads to work:
READY_BEADS=$(bd ready --json 2>/dev/null | jq -r '.[].id' | head -$MAX_WORKERS)
if [ -n "$BEAD_IDS" ]; then
READY_BEADS=$(echo "$BEAD_IDS" | tr ',' '\n')
fi
WAVE_SIZE=$(echo "$READY_BEADS" | wc -l | tr -d ' ')
If no ready beads, exit with message.
L2 Step 4: Spawn Demigods via tmux
For each ready bead, spawn a demigod session:
for BEAD_ID in $READY_BEADS; do
SESSION_NAME="demigod-$(echo $BEAD_ID | tr '.' '-')"
if tmux has-session -t "$SESSION_NAME" 2>/dev/null; then
echo "Session $SESSION_NAME already exists, skipping"
continue
fi
tmux new-session -d -s "$SESSION_NAME" "claude -p '/demigod $BEAD_ID'"
if tmux has-session -t "$SESSION_NAME" 2>/dev/null; then
echo "Spawned: $SESSION_NAME for $BEAD_ID"
SPAWNED_COUNT=$((SPAWNED_COUNT + 1))
else
echo "Failed to spawn: $SESSION_NAME"
fi
sleep 2
done
Key points:
- Use
-d for detached sessions (run in background)
- Session names derived from bead IDs for easy correlation
- Rate limit spawns (2 seconds) to avoid API rate limits
- Verify each session started before continuing
L2 Step 5: Monitor via Agent Mail
Poll Agent Mail inbox for demigod messages:
MCP Tool: fetch_inbox
Parameters:
project_key: <project path>
agent_name: <MAYOR_NAME>
limit: 50
include_bodies: true
Process messages by type:
| Subject Pattern | Action |
|---|
[<bead-id>] ACCEPTED | Log demigod started work |
[<bead-id>] PROGRESS | Log progress, check health |
[<bead-id>] HELP_REQUEST | Alert for manual intervention or route to Chiron |
[<bead-id>] DONE | Mark complete, check if wave finished |
[<bead-id>] FAILED | Log failure, decide on retry or escalate |
L2 Step 6: Track Completion
Maintain completion state:
declare -A BEAD_STATUS
for BEAD_ID in $READY_BEADS; do
BEAD_STATUS[$BEAD_ID]="spawned"
done
DONE_COUNT=0
FAILED_COUNT=0
for BEAD_ID in "${!BEAD_STATUS[@]}"; do
case "${BEAD_STATUS[$BEAD_ID]}" in
done) DONE_COUNT=$((DONE_COUNT + 1)) ;;
failed) FAILED_COUNT=$((FAILED_COUNT + 1)) ;;
esac
done
if [ $((DONE_COUNT + FAILED_COUNT)) -eq $WAVE_SIZE ]; then
WAVE_COMPLETE=true
fi
L2 Step 7: Report Results
When wave completes (or on --wait timeout):
## Swarm Level 2 Results
**Wave completed:** <timestamp>
**Beads in wave:** <WAVE_SIZE>
**Successful:** <DONE_COUNT>
**Failed:** <FAILED_COUNT>
### Completed Beads
| Bead ID | Demigod | Commit | Summary |
|---------|---------|--------|---------|
| ol-527.1 | GreenCastle | abc123 | Added auth middleware |
| ol-527.2 | BlueMountain | def456 | Fixed rate limiting |
### Failed Beads
| Bead ID | Demigod | Reason | Recommendation |
|---------|---------|--------|----------------|
| ol-527.3 | RedValley | Tests failed | Re-run with spec clarification |
### Active Sessions
| Session | Bead | Status | Runtime |
|---------|------|--------|---------|
| demigod-ol-527-1 | ol-527.1 | done | 15m |
| demigod-ol-527-2 | ol-527.2 | done | 12m |
| demigod-ol-527-3 | ol-527.3 | failed | 18m |
L2 Step 8: Cleanup Completed Sessions
Optionally clean up tmux sessions for completed beads:
for BEAD_ID in "${!BEAD_STATUS[@]}"; do
if [ "${BEAD_STATUS[$BEAD_ID]}" = "done" ]; then
SESSION_NAME="demigod-$(echo $BEAD_ID | tr '.' '-')"
tmux kill-session -t "$SESSION_NAME" 2>/dev/null
fi
done
Or keep all sessions for review: Use --keep-sessions flag to preserve all tmux sessions for post-mortem analysis.
Level 2 Helper Skills
Use these companion skills with Level 2 swarm:
| Skill | Purpose |
|---|
/attach <session> | Attach to a running demigod session for debugging |
/attach --list | List all running demigod sessions |
/inbox | Check Agent Mail for pending messages |
/vibe --remote <session> | Validate demigod's work before accepting |
Level 2 File Reservations
File reservations prevent conflicts when multiple demigods edit files.
How it works:
- Each demigod claims files before editing (via Agent Mail
file_reservation_paths)
- If another demigod tries to claim the same file, it sees a conflict warning
- Demigods release reservations when done
Mayor can view reservations:
MCP Tool: get_file_reservations (if available)
Parameters:
project_key: <project path>
On conflict:
- Demigod sends PROGRESS message noting the conflict
- Mayor decides: wait, reassign, or allow parallel work
- Advisory reservations don't block, just warn
Level 2 Error Handling
Demigod Session Crashes
If a tmux session dies unexpectedly:
tmux has-session -t "$SESSION_NAME" 2>/dev/null || {
echo "Session $SESSION_NAME died"
STATUS=$(bd show $BEAD_ID --json 2>/dev/null | jq -r '.status')
if [ "$STATUS" = "in_progress" ]; then
bd update $BEAD_ID --status open --assignee "" 2>/dev/null
echo "Bead $BEAD_ID released for retry"
fi
}
Agent Mail Server Crashes
If Agent Mail becomes unavailable mid-swarm:
- Demigods continue working (graceful degradation)
- Messages queue locally (if supported)
- Mayor loses visibility but work continues
- On restart, poll beads status directly:
for BEAD_ID in $READY_BEADS; do
STATUS=$(bd show $BEAD_ID --json 2>/dev/null | jq -r '.status')
echo "$BEAD_ID: $STATUS"
done
Timeout Handling
If --wait times out:
## Swarm Timeout
Wave did not complete within <timeout>.
### Still Running
| Session | Bead | Runtime | Action |
|---------|------|---------|--------|
| demigod-ol-527-3 | ol-527.3 | 32m | Consider `/attach` to check status |
### Options
1. Continue waiting: `/swarm --wait --timeout 60m`
2. Attach to slow workers: `/attach demigod-ol-527-3`
3. Kill and retry: `tmux kill-session -t demigod-ol-527-3`
Level 2 vs Level 1 Summary
| Behavior | Level 1 | Level 2 |
|---|
| Spawn mechanism | Task(run_in_background=true) | tmux new-session -d |
| Worker entry point | Inline prompt | /demigod <bead-id> |
| Process isolation | Shared parent | Separate processes |
| Persistence | Tied to Mayor | Survives Mayor crash |
| Coordination | None | Agent Mail messages |
| File conflicts | Race conditions | File reservations |
| Debugging | Limited | /attach to inspect |
| Resource overhead | Low | Medium (N tmux sessions) |
| Setup requirements | None | tmux + Agent Mail |
When to Use Level 2
| Scenario | Recommendation |
|---|
| Quick parallel tasks (<5 min each) | Level 1 |
| Long-running work (>10 min each) | Level 2 |
| Need to debug stuck workers | Level 2 |
| Multi-file changes across workers | Level 2 (file reservations) |
| Mayor might disconnect | Level 2 (persistence) |
| Complex coordination needed | Level 2 |
| Simple, isolated tasks | Level 1 |
Example: Full Level 2 Swarm
cd ~/gt/acfs-research/tier1/mcp_agent_mail
uv run python -m mcp_agent_mail.http --host 127.0.0.1 --port 8765 &
/swarm --level=2 --max-workers=3 --wait
Fallback Behavior
If Level 2 requested but requirements not met:
Error: Level 2 requires tmux and Agent Mail.
Missing:
- [ ] tmux: Install with `brew install tmux`
- [x] Agent Mail: Running at localhost:8765
Falling back to Level 1? [y/N]
If user confirms, degrade to Level 1 execution. Otherwise, exit with error.