
Cloud Edventures
Agent Teams, subagents, coordinator-subagent β everyone's confused. Here's the foundational pattern with working code, and when each approach actually makes sense.
Claude shipped Agent Teams. Everyone is excited.
Nobody is explaining the foundational pattern that makes all of it work.
Before you use Agent Teams or Claude Code subagents, you need to understand the coordinator-subagent pattern at the API level.
This is the mental model everything else is built on β and it works in production today.
A single agent handling everything is inefficient.
It has to:
This leads to context overload and weaker outputs.
The coordinator-subagent pattern solves this.
One coordinator agent:
Each subagent:
The coordinator doesnβt do the work.
It decides who does.
Flow:
Key rule: Subagents never talk to each other. Everything routes through the coordinator.
import boto3
client = boto3.client("bedrock-runtime", region_name="us-east-1")
SUBAGENT_PROMPTS = {
"research_agent": "You are a research specialist. Be factual.",
"writer_agent": "You are a writing specialist. Use only provided context.",
"reviewer_agent": "You are a reviewer. Return APPROVED or NEEDS_REVISION."
}
def run_subagent(agent_name, **kwargs):
content = "\n".join(f"{k}: {v}" for k, v in kwargs.items())
response = client.converse(
modelId="anthropic.claude-3-sonnet-20240229-v1:0",
system=[{"text": SUBAGENT_PROMPTS[agent_name]}],
messages=[{"role": "user", "content": [{"text": content}]}]
)
return response["output"]["message"]["content"][0]["text"]
def run_coordinator(user_request):
messages = [{"role": "user", "content": [{"text": user_request}]}]
for _ in range(15):
response = client.converse(
modelId="anthropic.claude-3-sonnet-20240229-v1:0",
messages=messages
)
stop_reason = response["stopReason"]
output = response["output"]["message"]
messages.append(output)
if stop_reason == "end_turn":
return output["content"][0]["text"]
elif stop_reason == "tool_use":
# Example routing logic
result = run_subagent("research_agent", task="example")
messages.append({
"role": "user",
"content": [{"text": result}]
})
return "Safety cap reached"
Same concept, different environment.
Inside Claude Code:
Key rule: Subagents report upward β no sideways communication.
Best for: local development workflows like testing, security checks, documentation.
Agent Teams introduce peer-to-peer communication.
Agents can talk directly to each other:
Tradeoffs:
| Pattern | Peer Communication | Production Ready | Best Use Case |
|---|---|---|---|
| Coordinator-Subagent | No | Yes | Production API agents |
| Claude Code Subagents | No | Yes | Developer workflows |
| Agent Teams | Yes | Experimental | Collaborative agents |
Subagents share nothing.
You must explicitly pass context.
# WRONG
research = run_subagent("research_agent", task="research AWS")
writer = run_subagent("writer_agent", task="write blog")
# RIGHT
research = run_subagent("research_agent", task="research AWS")
writer = run_subagent("writer_agent", task="write blog", context=research)
This isolation prevents context pollution β but requires deliberate design.
Once you understand this pattern, advanced systems become straightforward:
Everything builds on the same loop.
This pattern is covered in the Claude Certified Architect (CCA-001) track.
22 hands-on labs, real AWS Bedrock sandboxes, automated validation.
Start building multi-agent systems β
What are you building β production API agents or Claude Code workflows?
42 people reacted to this article
Written by Cloud Edventures
Previous
No more articles
Next
No more articles