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! 🎉