Skip to main content

Lesson 14: Multi-Agent Automation

Learning Objectives

After completing this lesson, you will be able to:

  • Design multi-agent architectures for Claude Code
  • Implement automatic agent coordination systems
  • Create communication protocols between agents
  • Build orchestration scripts for autonomous collaboration
  • Handle conflicts and resolution between agents
  • Monitor and manage multi-agent workflows

Prerequisites

  • Completed Lessons 1-13 - Full Claude Code mastery
  • Shell scripting experience - For orchestration scripts
  • System architecture knowledge - Understanding distributed systems
  • Advanced use case - Complex project requiring parallel work

Estimated Time: 45 minutes Difficulty: Advanced


Understanding Multi-Agent Claude Code

Multi-agent automation means running multiple Claude Code instances that work together autonomously on different aspects of a project.

Why Use Multiple Agents?

Parallelization:

Single Agent: Feature takes 4 hours
├─ Backend: 2 hours
├─ Frontend: 1.5 hours
└─ Tests: 30 minutes
Total: 4 hours (sequential)

Multi-Agent: Feature takes 1.5 hours
├─ Backend Agent: 2 hours (parallel)
├─ Frontend Agent: 1.5 hours (parallel)
└─ Test Agent: 30 minutes (after)
Total: 2 hours (max of parallel tasks + dependencies)

Specialization:

  • Database Agent: Expert in schemas, migrations, optimization
  • API Agent: Expert in endpoints, REST, GraphQL
  • Frontend Agent: Expert in React, Vue, UI/UX
  • Test Agent: Expert in pytest, jest, coverage
  • Documentation Agent: Expert in technical writing

Resilience:

  • If one agent fails, others continue
  • Independent error recovery
  • Graceful degradation

Agent Architecture Patterns

Pattern 1: Hierarchical (Coordinator-Workers)

Orchestrator Agent
├─→ Worker Agent 1 (Backend)
├─→ Worker Agent 2 (Frontend)
└─→ Worker Agent 3 (Tests)

Pattern 2: Pipeline (Stage-by-Stage)

Agent 1 (Design) → Agent 2 (Implement) → Agent 3 (Test) → Agent 4 (Deploy)

Pattern 3: Peer-to-Peer (Collaborative)

Agent A (Backend) ←↔→ Agent B (Frontend)
↕ ↕
Shared State (API contract)

Communication Protocols

Agents need ways to communicate. Let's build them from simple to advanced.

Level 1: File-Based Messaging (Simplest)

How it works: Agents read/write files to coordinate.

Setup:

project/
├── .agents/
│ ├── coordinator.md # Coordinator state
│ ├── backend-status.md # Backend agent status
│ ├── frontend-status.md # Frontend agent status
│ ├── messages.md # Message queue
│ └── shared-state.json # Shared data
└── src/

Implementation:

1. Create agent startup script:

scripts/start-agent.sh:

#!/bin/bash
AGENT_NAME=$1
PROJECT_DIR=$2

cd "$PROJECT_DIR"

# Create agent workspace
mkdir -p .agents

# Start Claude Code with agent-specific context
claude << EOF
# Agent Identity
You are the $AGENT_NAME agent working in $PROJECT_DIR.

# Communication
- Read your status from: .agents/$AGENT_NAME-status.md
- Write updates to: .agents/$AGENT_NAME-status.md
- Send messages via: .agents/messages.md
- Check coordinator: .agents/coordinator.md

# Role
$(cat .agents/roles/$AGENT_NAME.md)

# Start working
Await instructions from coordinator.
EOF

2. Create coordinator script:

scripts/orchestrate.sh:

#!/bin/bash
PROJECT_DIR=$(pwd)

# Initialize agent system
mkdir -p .agents/roles

# Define agent roles
cat > .agents/roles/backend.md << 'EOF'
# Backend Agent Role

You are responsible for:
- API endpoints
- Business logic
- Database operations
- Backend testing

Workflow:
1. Read .agents/coordinator.md for tasks
2. Implement your assigned features
3. Update .agents/backend-status.md with progress
4. Commit when complete with "[Backend]" prefix
EOF

cat > .agents/roles/frontend.md << 'EOF'
# Frontend Agent Role

You are responsible for:
- UI components
- State management
- User interactions
- Frontend testing

Workflow:
1. Read .agents/coordinator.md for tasks
2. Monitor backend-status.md for API changes
3. Implement UI components
4. Update .agents/frontend-status.md with progress
5. Commit when complete with "[Frontend]" prefix
EOF

# Initialize coordinator state
cat > .agents/coordinator.md << 'EOF'
# Coordinator State

## Current Task: User Authentication Feature

### Backend Agent
- Status: Pending
- Task: Implement login/logout endpoints
- Dependencies: None
- Output needed: auth.py with login/logout functions

### Frontend Agent
- Status: Waiting
- Task: Create login form component
- Dependencies: Backend API endpoints
- Output needed: LoginForm.jsx component

### Communication Protocol
1. Backend completes → Updates backend-status.md → Frontend starts
2. Frontend completes → Updates frontend-status.md → Coordinator notified
3. Both complete → Integration test → Done

## Messages
(Leave empty for now)
EOF

# Start agents in background
gnome-terminal -- bash -c "cd $PROJECT_DIR && scripts/start-agent.sh backend $PROJECT_DIR" &
gnome-terminal -- bash -c "cd $PROJECT_DIR && scripts/start-agent.sh frontend $PROJECT_DIR" &

echo "Agents started. Monitor with:"
echo " tail -f .agents/backend-status.md"
echo " tail -f .agents/frontend-status.md"

3. Create monitoring script:

scripts/monitor-agents.sh:

#!/bin/bash

watch -n 2 'echo "=== Agent Status ===" && \
echo "" && \
echo "=== Backend ===" && \
cat .agents/backend-status.md 2>/dev/null || echo "Not started" && \
echo "" && \
echo "=== Frontend ===" && \
cat .agents/frontend-status.md 2>/dev/null || echo "Not started" && \
echo "" && \
echo "=== Coordinator ===" && \
cat .agents/coordinator.md 2>/dev/null || echo "Not initialized"'

Usage:

# Start multi-agent system
./scripts/orchestrate.sh

# Monitor in another terminal
./scripts/monitor-agents.sh

Level 2: MCP Server Message Bus (Robust)

How it works: Create an MCP server that agents use to exchange messages.

1. Create MCP message server:

mcp-message-bus/server.py:

#!/usr/bin/env python3
"""
MCP Message Bus for Agent Communication

Acts as a centralized message queue and coordination system.
"""

import json
import os
from datetime import datetime
from pathlib import Path
from typing import Dict, List, Optional

class MessageBus:
def __init__(self, state_dir: str = ".agents/message-bus"):
self.state_dir = Path(state_dir)
self.state_dir.mkdir(parents=True, exist_ok=True)
self.messages_file = self.state_dir / "messages.json"
self.status_file = self.state_dir / "status.json"
self.lock_file = self.state_dir / "lock"

def send_message(self, from_agent: str, to_agent: str, message: dict):
"""Send a message from one agent to another."""
messages = self._load_messages()
messages.append({
'id': f"msg_{len(messages)}_{datetime.now().timestamp()}",
'from': from_agent,
'to': to_agent,
'message': message,
'timestamp': datetime.now().isoformat(),
'status': 'pending'
})
self._save_messages(messages)
return messages[-1]['id']

def get_messages(self, agent_name: str, unread_only: bool = True):
"""Get messages for an agent."""
messages = self._load_messages()
agent_messages = [m for m in messages if m['to'] == agent_name]

if unread_only:
agent_messages = [m for m in agent_messages if m['status'] == 'pending']

return agent_messages

def mark_read(self, message_id: str):
"""Mark a message as read."""
messages = self._load_messages()
for msg in messages:
if msg['id'] == message_id:
msg['status'] = 'read'
self._save_messages(messages)

def update_status(self, agent_name: str, status: dict):
"""Update agent status."""
statuses = self._load_statuses()
statuses[agent_name] = {
**statuses.get(agent_name, {}),
**status,
'last_update': datetime.now().isoformat()
}
self._save_statuses(statuses)

def get_status(self, agent_name: Optional[str] = None):
"""Get agent status(es)."""
statuses = self._load_statuses()
if agent_name:
return statuses.get(agent_name, {})
return statuses

def get_all_agents(self):
"""Get list of all active agents."""
statuses = self._load_statuses()
return list(statuses.keys())

def _load_messages(self) -> List:
if self.messages_file.exists():
return json.loads(self.messages_file.read_text())
return []

def _save_messages(self, messages: List):
self.messages_file.write_text(json.dumps(messages, indent=2))

def _load_statuses(self) -> Dict:
if self.status_file.exists():
return json.loads(self.status_file.read_text())
return {}

def _save_statuses(self, statuses: Dict):
self.status_file.write_text(json.dumps(statuses, indent=2))

# MCP Server interface (simplified)
def handle_message_bus_request(request: dict) -> dict:
"""Handle incoming message bus requests."""
bus = MessageBus()

action = request.get('action')

if action == 'send':
result = bus.send_message(
request['from'],
request['to'],
request['message']
)
return {'success': True, 'message_id': result}

elif action == 'receive':
messages = bus.get_messages(request['agent'])
return {'success': True, 'messages': messages}

elif action == 'update_status':
bus.update_status(request['agent'], request['status'])
return {'success': True}

elif action == 'get_status':
status = bus.get_status(request.get('agent'))
return {'success': True, 'status': status}

elif action == 'list_agents':
agents = bus.get_all_agents()
return {'success': True, 'agents': agents}

else:
return {'success': False, 'error': 'Unknown action'}

if __name__ == '__main__':
# Simple CLI interface for testing
import sys

if len(sys.argv) < 2:
print("Usage: server.py <action> [args...]")
sys.exit(1)

action = sys.argv[1]

if action == 'send' and len(sys.argv) >= 4:
from_agent = sys.argv[2]
to_agent = sys.argv[3]
message = {'text': ' '.join(sys.argv[4:])}
result = handle_message_bus_request({
'action': 'send',
'from': from_agent,
'to': to_agent,
'message': message
})
print(f"Message sent: {result['message_id']}")

elif action == 'receive' and len(sys.argv) >= 3:
agent = sys.argv[2]
result = handle_message_bus_request({
'action': 'receive',
'agent': agent
})
print(f"Messages: {json.dumps(result['messages'], indent=2)}")

elif action == 'status':
result = handle_message_bus_request({
'action': 'get_status',
'agent': sys.argv[2] if len(sys.argv) > 2 else None
})
print(f"Status: {json.dumps(result['status'], indent=2)}")

2. Register as MCP server in Claude Code config:

~/.config/claude-code/settings.json:

{
"mcpServers": {
"message-bus": {
"command": "python3",
"args": ["/path/to/mcp-message-bus/server.py"],
"env": {
"MESSAGE_BUS_DIR": ".agents/message-bus"
}
}
}
}

3. Agent uses message bus:

Backend Agent:

You: Use the message-bus MCP server. Send a message to frontend agent:
"I've completed the /api/login endpoint. It accepts POST with email/password
and returns a JWT token. Endpoint is ready for integration."

Frontend Agent:

You: Check message-bus for messages from backend agent.
[Receives message]

You: Great! I'll now create the login form component that calls
/api/login. I'll handle the JWT token in localStorage.

Level 3: HTTP/WebSocket API (Advanced)

For production systems, build a proper HTTP API:

agent-coordinator/api.py:

from flask import Flask, request, jsonify
from message_bus import MessageBus

app = Flask(__name__)
bus = MessageBus()

@app.route('/send', methods=['POST'])
def send_message():
"""Send message to agent."""
data = request.json
msg_id = bus.send_message(data['from'], data['to'], data['message'])
return jsonify({'message_id': msg_id})

@app.route('/receive/<agent_name>', methods=['GET'])
def receive_messages(agent_name):
"""Get pending messages for agent."""
messages = bus.get_messages(agent_name)
return jsonify({'messages': messages})

@app.route('/status/<agent_name>', methods=['GET', 'PUT'])
def agent_status(agent_name):
"""Get or update agent status."""
if request.method == 'PUT':
bus.update_status(agent_name, request.json)
return jsonify({'success': True})
else:
status = bus.get_status(agent_name)
return jsonify(status)

@app.route('/agents', methods=['GET'])
def list_agents():
"""List all agents."""
agents = bus.get_all_agents()
return jsonify({'agents': agents})

if __name__ == '__main__':
app.run(port=5555)

Agent uses curl to communicate:

# Send message
curl -X POST http://localhost:5555/send \
-H "Content-Type: application/json" \
-d '{"from": "backend", "to": "frontend", "message": {"text": "API ready"}}'

# Check messages
curl http://localhost:5555/receive/frontend

Complete Multi-Agent System

Let's build a complete automated system with 4 agents.

System Architecture

┌─────────────────────────────────────────────────────────┐
│ Orchestrator (Main Terminal) │
│ - Starts all agents │
│ - Monitors progress │
│ - Handles conflicts │
└────────┬────────────────────────────────────────────────┘

├──────────────────┬──────────────────┬──────────────────┐
│ │ │ │
┌────▼────┐ ┌────▼────┐ ┌────▼────┐ ┌────▼────┐
│ Backend │ │Frontend │ │ Test │ │ Docs │
│ Agent │ │ Agent │ │ Agent │ │ Agent │
└────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘
│ │ │ │
└──────────────────┴──────────────────┴──────────────────┘

┌─────────▼──────────┐
│ Message Bus (MCP) │
│ + Shared Files │
└─────────────────────┘

Implementation

1. Create project structure:

multi-agent-project/
├── .agents/
│ ├── roles/ # Agent role definitions
│ ├── workspace/ # Agent working directories
│ │ ├── backend/
│ │ ├── frontend/
│ │ ├── tests/
│ │ └── docs/
│ └── state/ # Shared state
├── src/
├── scripts/
│ ├── orchestrate.sh # Main orchestrator
│ ├── start-agent.sh # Agent launcher
│ ├── monitor.sh # Status monitor
│ └── resolve-conflicts.sh # Conflict handler
└── claude-agents.json # Agent configuration

2. Agent configuration:

claude-agents.json:

{
"agents": [
{
"name": "backend",
"role": "Backend Development",
"specialty": "APIs, databases, business logic",
"terminal": "1",
"working_dir": ".agents/workspace/backend",
"dependencies": [],
"output": "src/backend/",
"startup_prompt": "Start by reading the API specification in specs/api.md"
},
{
"name": "frontend",
"role": "Frontend Development",
"specialty": "UI components, state management",
"terminal": "2",
"working_dir": ".agents/workspace/frontend",
"dependencies": ["backend"],
"output": "src/frontend/",
"startup_prompt": "Wait for backend agent to complete API, then build UI"
},
{
"name": "tests",
"role": "Testing & QA",
"specialty": "Unit tests, integration tests",
"terminal": "3",
"working_dir": ".agents/workspace/tests",
"dependencies": ["backend", "frontend"],
"output": "tests/",
"startup_prompt": "Wait for implementation, then create comprehensive tests"
},
{
"name": "docs",
"role": "Documentation",
"specialty": "API docs, user guides",
"terminal": "4",
"working_dir": ".agents/workspace/docs",
"dependencies": ["backend", "frontend"],
"output": "docs/",
"startup_prompt": "Document the implementation as it's completed"
}
],
"communication": {
"method": "mcp",
"message_bus": "message-bus",
"update_interval": 5
},
"coordination": {
"mode": "hierarchical",
"conflict_resolution": "human-in-loop",
"checkpoint_interval": 300
}
}

3. Orchestrator script:

scripts/orchestrate.sh:

#!/bin/bash
set -e

PROJECT_ROOT=$(pwd)
CONFIG_FILE="$PROJECT_ROOT/claude-agents.json"
AGENTS_DIR="$PROJECT_ROOT/.agents"

echo "🚀 Starting Multi-Agent Claude Code System"
echo "============================================="

# Load configuration
if [ ! -f "$CONFIG_FILE" ]; then
echo "❌ Error: claude-agents.json not found"
exit 1
fi

# Initialize workspace
echo "📁 Initializing workspace..."
mkdir -p "$AGENTS_DIR"/{roles,workspace,state}

# Extract agent count
AGENT_COUNT=$(jq '.agents | length' "$CONFIG_FILE")
echo "📊 Found $AGENT_COUNT agents to start"

# Function to start an agent
start_agent() {
local index=$1
local agent_name=$(jq -r ".agents[$index].name" "$CONFIG_FILE")
local role=$(jq -r ".agents[$index].role" "$CONFIG_FILE")
local working_dir=$(jq -r ".agents[$index].working_dir" "$CONFIG_FILE")
local terminal=$(jq -r ".agents[$index].terminal" "$CONFIG_FILE")
local startup_prompt=$(jq -r ".agents[$index].startup_prompt" "$CONFIG_FILE")
local dependencies=$(jq -r ".agents[$index].dependencies | join(\", \")" "$CONFIG_FILE")

echo "🤖 Starting agent: $agent_name ($role)"

# Create agent workspace
mkdir -p "$PROJECT_ROOT/$working_dir"

# Create role file
cat > "$AGENTS_DIR/roles/$agent_name.md" << EOF
# $agent_name Agent

## Role
$role

## Dependencies
$([ -n "$dependencies" ] && echo "$dependencies" || echo "None")

## Instructions
1. Monitor .agents/state/coordinator.md for tasks
2. Send updates via message-bus MCP server
3. Update your status in .agents/state/$agent_name-status.md
4. Commit your work with "[$agent_name]" prefix

## Initial Task
$startup_prompt

## Communication
- Use message-bus MCP to communicate with other agents
- Check for messages every 30 seconds
- Respond to queries within 1 minute
EOF

# Start Claude Code in new terminal
# Note: Terminal command varies by OS
if command -v gnome-terminal &> /dev/null; then
gnome-terminal --title="$agent_name Agent" -- bash -c "
cd '$PROJECT_ROOT'
claude << AGENT_EOF
# Agent Initialization
You are the $agent_name agent.

$(cat "$AGENTS_DIR/roles/$agent_name.md")

# Start working now.
Await further instructions.
AGENT_EOF
exec bash
" &
elif command -v tmux &> /dev/null; then
tmux new-window -n "$agent_name" "cd '$PROJECT_ROOT' && claude"
else
# Fallback: run in background
(
cd "$PROJECT_ROOT"
claude << AGENT_EOF
# Agent Initialization
You are the $agent_name agent.

$(cat "$AGENTS_DIR/roles/$agent_name.md")

# Start working now.
AGENT_EOF
) &
fi

# Record agent PID
echo $! > "$AGENTS_DIR/state/$agent_name.pid"
}

# Start all agents
for ((i=0; i<$AGENT_COUNT; i++)); do
start_agent $i
sleep 2 # Stagger startup
done

echo ""
echo "✅ All agents started!"
echo ""
echo "📊 Monitor agents with:"
echo " ./scripts/monitor.sh"
echo ""
echo "🛑 Stop agents with:"
echo " ./scripts/stop.sh"
echo ""
echo "💬 Communicate with agents:"
echo " ./scripts/talk-to-agent.sh <agent-name>"
echo ""

# Start coordinator in current terminal
echo "🎯 Starting coordinator..."
cat > "$AGENTS_DIR/state/coordinator.md" << 'EOF'
# Coordinator State

## Active Agents
- backend: Implementing APIs
- frontend: Building UI (waiting for backend)
- tests: Creating tests (waiting for implementation)
- docs: Writing docs (waiting for implementation)

## Current Task
Build a user authentication system

## Workflow
1. Backend agent implements login/register endpoints
2. Frontend agent builds login form
3. Tests agent creates test suite
4. Docs agent writes API documentation

## Progress
- Backend: 0%
- Frontend: 0%
- Tests: 0%
- Docs: 0%
EOF

# Launch monitor
./scripts/monitor.sh

4. Monitor script:

scripts/monitor.sh:

#!/bin/bash

clear
echo "🤖 Multi-Agent Claude Code Monitor"
echo "=================================="
echo ""

while true; do
clear
echo "🤖 Multi-Agent Claude Code Monitor"
echo "=================================="
echo ""
echo "Time: $(date '+%Y-%m-%d %H:%M:%S')"
echo ""

# Check agent processes
echo "📊 Agent Status:"
echo "---------------"
if [ -d ".agents/state" ]; then
for pidfile in .agents/state/*.pid; do
if [ -f "$pidfile" ]; then
agent_name=$(basename "$pidfile" .pid)
pid=$(cat "$pidfile")
if ps -p "$pid" > /dev/null 2>&1; then
echo "✅ $agent_name: Running (PID: $pid)"
else
echo "❌ $agent_name: Stopped"
fi
fi
done
fi
echo ""

# Show agent status files
echo "📋 Agent Progress:"
echo "-----------------"
for statusfile in .agents/state/*-status.md; do
if [ -f "$statusfile" ]; then
agent_name=$(basename "$statusfile" -status.md)
echo "### $agent_name:"
tail -n 5 "$statusfile" | sed 's/^/ /'
echo ""
fi
done

# Show coordinator state
echo "🎯 Coordinator:"
echo "--------------"
if [ -f ".agents/state/coordinator.md" ]; then
tail -n 10 ".agents/state/coordinator.md" | sed 's/^/ /'
fi
echo ""

# Show recent messages
echo "💬 Recent Messages:"
echo "------------------"
if [ -f ".agents/state/messages.json" ]; then
jq -r '.[-3:] | .[] | "\(.from) → \(.to): \(.message.text // .message)"' \
.agents/state/messages.json 2>/dev/null | sed 's/^/ /' || echo " No messages yet"
fi
echo ""

# Show conflicts
echo "⚠️ Conflicts:"
echo "-------------"
if [ -f ".agents/state/conflicts.json" ]; then
jq -r '.[] | "- \(.type): \(.description)"' \
.agents/state/conflicts.json 2>/dev/null | sed 's/^/ /' || echo " No conflicts"
else
echo " None"
fi
echo ""

sleep 5
done

5. Conflict resolution script:

scripts/resolve-conflicts.sh:

#!/bin/bash

echo "🔧 Agent Conflict Resolution"
echo "============================"
echo ""

# Check for conflicts
if [ ! -f ".agents/state/conflicts.json" ]; then
echo "✅ No conflicts detected"
exit 0
fi

CONFLICT_COUNT=$(jq '. | length' .agents/state/conflicts.json)

if [ "$CONFLICT_COUNT" -eq 0 ]; then
echo "✅ No conflicts detected"
exit 0
fi

echo "⚠️ Found $CONFLICT_COUNT conflict(s)"
echo ""

jq -r '.[] | "\n### \(.type)\nAgents: \(.agents | join(", "))\nDescription: \(.description)\nOptions:\n\(.options | .[] | "- \(.action): \(.description)")"' \
.agents/state/conflicts.json

echo ""
echo "Choose resolution:"
echo "1. Open files and manual merge"
echo "2. Let Agent A win"
echo "3. Let Agent B win"
echo "4. Create hybrid solution"
echo "5. Escalate to human"

read -p "Select option (1-5): " choice

case $choice in
1)
echo "Opening files for manual merge..."
# Open editor with conflicting files
;;
2|3)
echo "Applying resolution..."
# Apply chosen agent's version
;;
4)
echo "Creating hybrid solution..."
# Ask Claude to create hybrid
;;
5)
echo "⚠️ Conflict escalated to human"
echo "Please review and resolve manually"
;;
esac

Usage

1. Start the multi-agent system:

./scripts/orchestrate.sh

2. Watch agents work: The monitor shows real-time progress:

🤖 Multi-Agent Claude Code Monitor
==================================

Time: 2025-02-04 14:30:45

📊 Agent Status:
---------------
✅ backend: Running (PID: 12345)
✅ frontend: Running (PID: 12346)
✅ tests: Running (PID: 12347)
✅ docs: Running (PID: 12348)

📋 Agent Progress:
-----------------
### backend:
✓ Created auth.py
✓ Implemented login endpoint
→ Working on logout endpoint

### frontend:
⏳ Waiting for backend API completion

### tests:
⏳ Waiting for implementation

### docs:
⏳ Waiting for implementation

💬 Recent Messages:
------------------
backend → frontend: "Login API ready at /api/login"
backend → coordinator: "Login endpoint complete"

3. Agents communicate automatically:

Backend Agent completes task:

You> Update your status and notify frontend agent

Claude: [Updates backend-status.md]
[Uses message-bus MCP to send message]
[Notifies coordinator]

Frontend Agent receives message:

Claude: [Checks message-bus]
[New message from backend: "Login API ready"]
[Starting frontend implementation]

Advanced Patterns

Pattern 1: Dynamic Agent Spawning

Spawn new agents as needed:

scripts/spawn-agent.sh:

#!/bin/bash

# Spawn temporary specialist agent
AGENT_TYPE=$1
TASK=$2

case $AGENT_TYPE in
"security")
ROLE="Security specialist"
;;
"performance")
ROLE="Performance optimizer"
;;
"database")
ROLE="Database administrator"
;;
*)
echo "Unknown agent type: $AGENT_TYPE"
exit 1
esac

# Spawn agent with temporary role
gnome-terminal -- bash -c "
claude << EOF
You are a temporary $ROLE agent.

Task: $TASK

Complete this task, then:
1. Document your changes
2. Send results via message-bus
3. Exit when complete
EOF
"

Usage:

./scripts/spawn-agent.sh security "Audit authentication code for vulnerabilities"

Pattern 2: Hierarchical Teams

Create teams of agents:

Frontend Team Leader
├─→ Component Agent
├─→ State Management Agent
└─→ Styling Agent

Backend Team Leader
├─→ API Agent
├─→ Database Agent
└─→ Auth Agent

Implementation:

# Start team leaders
./scripts/orchestrate.sh --mode=leaders-only

# Team leaders spawn their team members
# Frontend leader spawns component, state, styling agents
# Backend leader spawns API, database, auth agents

Pattern 3: Peer Review System

Agents review each other's work:

Implementation Agent → Review Agent → Fix Agent
↑ ↓
└──────────────────────┘
(Iterate until approved)

Script: scripts/setup-review-cycle.sh

#!/bin/bash

# Agent 1: Implement
./scripts/start-agent.sh implementer "Build feature X"

# Agent 2: Review
./scripts/start-agent.sh reviewer "Review feature X implementation"

# If reviewer finds issues:
# - Sends message to implementer
# - Implementer fixes
# - Reviewer reviews again

# Loop until approved

Conflict Resolution

When agents disagree, you need strategies.

Detection

Agents report conflicts to coordinator:

// .agents/state/conflicts.json
[
{
"type": "naming_conflict",
"agents": ["backend", "frontend"],
"description": "Different naming for user object",
"backend_version": {"name": "User", "fields": ["id", "email"]},
"frontend_version": {"name": "UserProfile", "fields": ["id", "email"]},
"options": [
{"action": "use_backend", "description": "Use backend naming, update frontend"},
{"action": "use_frontend", "description": "Use frontend naming, update backend"},
{"action": "create_alias", "description": "Create UserProfile as alias to User"}
]
}
]

Resolution Strategies

1. Automatic (Based on Rules)

{
"resolution_rules": [
{
"conflict_type": "naming_conflict",
"priority": "backend_wins",
"reason": "Backend is source of truth"
},
{
"conflict_type": "api_conflict",
"priority": "human_decision",
"reason": "Requires architectural decision"
}
]
}

2. Voting (Democratic)

# Get all agents to vote on resolution
./scripts/vote-on-resolution.sh "naming_conflict"

3. Human-in-the-Loop

# Pause agents, ask human to decide
./scripts/escalate-to-human.sh "naming_conflict"

Best Practices

1. Clear Agent Boundaries

✅ Good:

Backend Agent: API, database, business logic
Frontend Agent: UI, state, user interaction

❌ Bad:

Agent 1: Everything
Agent 2: Also everything (conflict!)

2. Dependency Management

Define clear dependencies:

{
"agent": "frontend",
"dependencies": ["backend"],
"wait_condition": "backend-status.md contains '[READY]'"
}

3. Communication Frequency

Balance between coordination and overhead:

  • High frequency (5s): Critical path tasks
  • Medium frequency (30s): Normal collaboration
  • Low frequency (5min): Async tasks

4. State Management

Use immutable state:

state-v1.json
state-v2.json
state-v3.json

Not:

state.json (constantly changing)

5. Monitoring and Logging

Log everything:

.agents/logs/
├── backend-2025-02-04.log
├── frontend-2025-02-04.log
└── coordinator-2025-02-04.log

Real-World Example: E-Commerce Feature

Let's build a complete shopping cart feature with 4 agents.

Setup:

mkdir multi-agent-ecommerce
cd multi-agent-ecommerce

# Initialize multi-agent system
./scripts/init-multi-agent.sh

Configuration: claude-agents.json

{
"agents": [
{
"name": "database",
"role": "Database Schema Designer",
"tasks": [
"Design cart_items table",
"Create migrations",
"Add indexes"
]
},
{
"name": "backend",
"role": "API Developer",
"dependencies": ["database"],
"tasks": [
"POST /api/cart (add item)",
"GET /api/cart (get items)",
"DELETE /api/cart/:id (remove item)",
"PUT /api/cart/:id (update quantity)"
]
},
{
"name": "frontend",
"role": "UI Developer",
"dependencies": ["backend"],
"tasks": [
"Cart component",
"Add to cart button",
"Cart page",
"Quantity controls"
]
},
{
"name": "tests",
"role": "QA Engineer",
"dependencies": ["backend", "frontend"],
"tasks": [
"API integration tests",
"Frontend unit tests",
"E2E tests with Playwright"
]
}
]
}

Execution:

./scripts/orchestrate.sh

# Watch agents work:
# 1. Database agent creates schema (5 min)
# 2. Backend agent builds API (parallel with DB, waits for schema) (15 min)
# 3. Frontend agent builds UI (parallel, waits for API) (20 min)
# 4. Tests agent creates tests (waits for implementation) (10 min)

# Total time: ~35 minutes (vs 50+ minutes sequentially)

Monitor output:

🤖 Multi-Agent Monitor
=====================

✅ database: Schema created
→ cart_items table designed
→ Migration file created
→ Indexes added

✅ backend: API endpoints ready
→ POST /api/cart ✓
→ GET /api/cart ✓
→ DELETE /api/cart/:id ✓
→ PUT /api/cart/:id ✓

✅ frontend: UI components built
→ Cart component ✓
→ Add to cart button ✓
→ Cart page ✓

✅ tests: Test suite complete
→ API tests passing (15/15)
→ Frontend tests passing (8/8)
→ E2E tests passing (5/5)

🎉 Feature complete in 34 minutes!

✅ Check Your Understanding

  1. What's the main benefit of multiple Claude Code agents?

    • They're cheaper
    • Parallelization and specialization
    • They use less memory
    • No setup required
  2. What's the simplest communication method between agents?

    • WebSocket
    • File-based messaging
    • HTTP API
    • Telepathy
  3. What does the orchestrator do?

    • Write all the code
    • Coordinate and monitor agents
    • Only handle conflicts
    • Nothing
  4. True or False: Agents can work completely independently without coordination.**

    • True
    • False - they need coordination to avoid conflicts
  5. What's a good strategy for agent conflicts?

    • Let them fight it out
    • Clear priority rules or human-in-the-loop
    • Ignore conflicts
    • Stop all agents

Answers: 1-b, 2-b, 3-b, 4-False, 5-b


Summary

In this lesson, you learned:

  • Multi-agent architectures - Hierarchical, pipeline, peer-to-peer
  • Communication protocols - File-based, MCP message bus, HTTP API
  • Orchestration - Starting, monitoring, stopping agents
  • Automation scripts - Complete system implementation
  • Conflict resolution - Detection and resolution strategies
  • Real-world workflows - Practical e-commerce example

Next Steps

Experiment with:

  1. Start with 2 agents (backend + frontend)
  2. Add third agent (tests)
  3. Build custom communication protocols
  4. Create specialized agents for your domain
  5. Implement automatic conflict resolution

Further Reading


Congratulations! You've mastered the most advanced Claude Code techniques! 🎉