3 min read · 604 words
Multi-agent systems are currently all the rage. Splitting a monolithic task—like building a web app or writing a research paper—into specialized agents (e.g., a Planner, a Coder, a Reviewer) sounds like the ultimate scaling trick.
When applied to modern LLMs, multi-agent architectures can be powerful, but they also introduce silent failure modes, runaway token usage, and frustrating debugging sessions.
Here is how to build practical, production-ready multi-agent workflows using claude-opus-5 and claude-sonnet-5, along with the patterns you should follow and the pitfalls to avoid.
The Architecture: Router-Worker Pattern
Instead of creating a tangled web where every agent talks to every other agent, stick to deterministic orchestrations. The Router-Worker pattern is one of the most reliable architectures. A primary router analyzes the user request and delegates sub-tasks to specialized worker agents.
Let's implement a clean, two-tier workflow using the official Python SDK: a Research Agent that gathers data, followed by a Synthesis Agent that writes the final report.
import anthropic
client = anthropic.Anthropic()
def run_researcher(topic: str) -> str:
"""Worker Agent 1: Gathers technical details."""
print(f"🤖 [Researcher] Investigating: {topic}")
response = client.messages.create(
model="claude-sonnet-5",
max_tokens=8000,
output_config={"effort": "medium"},
messages=[
{
"role": "user",
"content": f"Provide 3 key technical challenges and solutions for: {topic}"
}
]
)
return response.content[0].text
def run_synthesizer(topic: str, research_data: str) -> str:
"""Worker Agent 2: Synthesizes findings into a final document."""
print(f"🤖 [Synthesizer] Formatting final report...")
response = client.messages.create(
model="claude-opus-5",
max_tokens=16000,
output_config={"effort": "high"},
messages=[
{
"role": "user",
"content": f"Topic: {topic}\n\nResearch Data:\n{research_data}\n\nWrite a polished markdown report."
}
]
)
return response.content[0].text
# Execute the workflow
topic = "Scaling WebSockets in Distributed Systems"
raw_research = run_researcher(topic)
final_report = run_synthesizer(topic, raw_research)
print("\n--- FINAL OUTPUT ---\n")
print(final_report[:500] + "\n[...truncated for display...]")
Note: Notice how we omit parameters like temperature, top_p, and top_k. Modern API standards require us to steer behavior purely through prompt engineering and output_config={"effort": "..."}.
Structured JSON Outputs for Inter-Agent Communication
When agents pass data to each other, brittle string parsing will break your pipeline. Instead of letting agents reply in free-form text, enforce strict JSON schemas using output_config={"format": {...}}.
Here is how you can ensure an evaluator agent always returns a parseable evaluation object before passing it downstream:
import json
import anthropic
client = anthropic.Anthropic()
eval_schema = {
"type": "object",
"properties": {
"score": {"type": "integer", "description": "Score from 1 to 10"},
"approved": {"type": "boolean"},
"feedback": {"type": "string"}
},
"required": ["score", "approved", "feedback"]
}
def evaluate_code(code_snippet: str) -> dict:
response = client.messages.create(
model="claude-haiku-4-5",
max_tokens=4000,
output_config={"format": {"type": "json_schema", "schema": eval_schema}},
messages=[
{
"role": "user",
"content": f"Review this code for security vulnerabilities:\n\n{code_snippet}"
}
]
)
# Guaranteed to match the JSON schema
return json.loads(response.content[0].text)
result = evaluate_code("eval(user_input)")
print(result)
Major Pitfalls to Avoid
- Infinite Agent Loops: If Agent A reviews Agent B's work, and Agent B fixes Agent A's feedback, they can get stuck looping forever. Always set a hard step limit (e.g., maximum 3 iterations) in your orchestration code.
-
Over-Engineering: Don't use five agents when one well-prompted call to
claude-opus-5will do. Every handoff introduces latency, token costs, and a new point of failure. -
Ignoring Context Windows: While models like
claude-opus-5boast massive 1M token contexts, passing bloated conversation histories between multiple workers degrades reasoning focus. Summarize intermediate outputs before handing them off.
Summary Checklist
-
Model Selection: Use
claude-sonnet-5for high-volume worker tasks,claude-opus-5for deep reasoning/synthesis, andclaude-haiku-4-5for fast routing or validation. -
Control Depth: Use
output_config={"effort": "low"|"medium"|"high"}instead of legacy parameters. - Enforce Schemas: Use native JSON formatting configs rather than relying on regex to parse agent conversations.
What multi-agent patterns are you building? Drop a comment below or share your experiences!
Top comments (0)