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
-
What's the main benefit of multiple Claude Code agents?
- They're cheaper
- Parallelization and specialization
- They use less memory
- No setup required
-
What's the simplest communication method between agents?
- WebSocket
- File-based messaging
- HTTP API
- Telepathy
-
What does the orchestrator do?
- Write all the code
- Coordinate and monitor agents
- Only handle conflicts
- Nothing
-
True or False: Agents can work completely independently without coordination.**
- True
- False - they need coordination to avoid conflicts
-
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:
- Start with 2 agents (backend + frontend)
- Add third agent (tests)
- Build custom communication protocols
- Create specialized agents for your domain
- Implement automatic conflict resolution
Further Reading
Congratulations! You've mastered the most advanced Claude Code techniques! 🎉