Benefits and Challenges of Multi-Agent Systems › A Balanced Example
Michael BrenndoerferJuly 29, 20253 min read
AI Agent HandbookAll chapters Part 10 of 15Multi-Agent Systems - Teamwork Among AIs
Benefits and Challenges of Multi-Agent Systems › A Balanced ExampleOne section · Sections in this chapter6 / 9 ↓
Sections in this chapter9
Let's bring this together with an example that shows both the benefits and the complexity management:
In[9]:
Code## Using Claude Sonnet 4.5 for a well-designed multi-agent system
import os
from anthropic import Anthropic
import json
from datetime import datetime
client = Anthropic(api_key=os.getenv("ANTHROPIC_API_KEY"))
class BalancedMultiAgentSystem:
"""
A multi-agent system with clear interfaces and error handling.
"""
def __init__(self):
self.model = "claude-sonnet-4-5"
self.log = []
def _log_event(self, agent, event, details=None):
"""
Centralized logging for observability.
"""
entry = {
"timestamp": datetime.utcnow().isoformat(),
"agent": agent,
"event": event,
"details": details
}
self.log.append(entry)
print(f"[{agent}] {event}")
def coordinator(self, user_request):
"""
Coordinates the workflow with clear error handling.
"""
self._log_event("coordinator", "Request received", user_request)
try:
# Step 1: Understand intent
intent = self.intent_agent(user_request)
if intent.get("error"):
return self._handle_error("intent", intent["error"])
# Step 2: Gather information
research = self.research_agent(intent["topic"])
if research.get("error"):
return self._handle_error("research", research["error"])
# Step 3: Formulate response
response = self.response_agent(research, intent)
if response.get("error"):
return self._handle_error("response", response["error"])
self._log_event("coordinator", "Request completed successfully")
return response
except Exception as e:
self._log_event("coordinator", "Unexpected error", str(e))
return {"error": "System error occurred", "details": str(e)}
def intent_agent(self, request):
"""
Understands user intent with structured output.
"""
self._log_event("intent_agent", "Processing intent")
try:
system_prompt = """Extract the intent from user requests.
Return JSON with:
- intent_type: "question", "task", or "command"
- topic: the main topic
- details: any specific requirements
Only return JSON, nothing else."""
response = client.messages.create(
model=self.model,
max_tokens=256,
system=system_prompt,
messages=[{"role": "user", "content": request}]
)
intent = json.loads(response.content[0].text)
self._log_event("intent_agent", "Intent extracted", intent.get("intent_type"))
return intent
except Exception as e:
self._log_event("intent_agent", "Failed", str(e))
return {"error": str(e)}
def research_agent(self, topic):
"""
Researches the topic with error handling.
"""
self._log_event("research_agent", "Researching", topic)
try:
system_prompt = """Research the given topic and provide key information.
Return JSON with:
- summary: brief overview
- key_points: list of main points
- confidence: 0-1 confidence score
Only return JSON, nothing else."""
response = client.messages.create(
model=self.model,
max_tokens=512,
system=system_prompt,
messages=[{"role": "user", "content": f"Research: {topic}"}]
)
research = json.loads(response.content[0].text)
self._log_event("research_agent", "Research completed",
f"confidence: {research.get('confidence')}")
return research
except Exception as e:
self._log_event("research_agent", "Failed", str(e))
return {"error": str(e)}
def response_agent(self, research, intent):
"""
Formulates the final response.
"""
self._log_event("response_agent", "Formulating response")
try:
system_prompt = """Create a clear, helpful response based on research and intent.
Be concise and directly address the user's needs."""
context = f"Intent: {json.dumps(intent)}\n\nResearch: {json.dumps(research)}"
response = client.messages.create(
model=self.model,
max_tokens=512,
system=system_prompt,
messages=[{"role": "user", "content": context}]
)
self._log_event("response_agent", "Response created")
return {"response": response.content[0].text}
except Exception as e:
self._log_event("response_agent", "Failed", str(e))
return {"error": str(e)}
def _handle_error(self, agent, error):
"""
Graceful error handling.
"""
self._log_event("coordinator", f"Handling error from {agent}")
return {
"response": f"I encountered an issue while processing your request. Could you try rephrasing?",
"internal_error": error
}
def get_log(self):
"""
Return the execution log for debugging.
"""
return self.log
## Example usage
system = BalancedMultiAgentSystem()
print("=== Balanced Multi-Agent System ===\n")
result = system.coordinator("What are the main benefits of renewable energy?")
print(f"\nFinal Response: {result.get('response')}")
print("\n=== Execution Log ===")
for entry in system.get_log():
print(f"{entry['timestamp']} | {entry['agent']}: {entry['event']}")Out[9]:
Console=== Balanced Multi-Agent System === [coordinator] Request received [intent_agent] Processing intent
[intent_agent] Failed [coordinator] Handling error from intent Final Response: I encountered an issue while processing your request. Could you try rephrasing? === Execution Log === 2025-12-07T12:09:04.783874 | coordinator: Request received 2025-12-07T12:09:04.783887 | intent_agent: Processing intent 2025-12-07T12:09:07.800100 | intent_agent: Failed 2025-12-07T12:09:07.800188 | coordinator: Handling error from intent
This example demonstrates the key principles:
Clear Interfaces: Each agent has a defined input/output contract.
Error Handling: Every agent can fail gracefully and return errors.
Observability: Comprehensive logging lets you trace execution.
Coordinator Pattern: One agent manages the workflow.
Structured Communication: All agents use JSON for predictable parsing.
The system is more complex than a single agent, but the complexity is managed. You can test each agent independently. You can trace failures through the logs. You can add new agents without rewriting everything.