Skip to content
Letta Platform Letta Platform Letta Docs
Sign up
Agents
Multi-agent patterns

The hierarchical teams pattern

Organize agents into hierarchical layers where managers coordinate work across levels with tag-based routing and shared memory.

Organize agents into hierarchical layers with clear reporting structures. Managers coordinate specialized teams using tag-based routing while sharing knowledge via common resources. Work flows both top-down through delegation and bottom-up through reporting.

Hierarchical Teams Pattern Architecture

The hierarchical teams pattern works when you need to:

  • Organize large agent systems with multiple specialized teams (such as engineering, marketing, and operations)
  • Maintain clear reporting structures and accountability across layers
  • Coordinate work across departments or functional areas
  • Scale agent systems beyond flat team structures
  • Delegate complex projects that require coordination at multiple levels

An executive agent oversees a product launch with two managers (an engineering manager and a marketing manager). The engineering manager coordinates backend and frontend engineers to build authentication features, while the marketing manager coordinates content writers and designers to create launch materials. The executive delegates strategic goals to managers, managers break down work for specialized workers, and all agents share findings through the common archival memory. Each layer maintains context across sessions while coordinating with the appropriate hierarchy levels.

The hierarchical teams pattern uses four key components:

  1. Hierarchical tagging: Agents are tagged by layer (such as ["executive"], ["manager", "engineering"], ["worker", "engineering", "backend"]) for organization and discovery.
  2. Shared memory blocks: Memory blocks make the coordination state visible across layers (guidelines, priorities, project status).
  3. Shared archival memory: Agents at all levels contribute findings to a searchable knowledge base.
  4. Tool rules for cascade prevention: Each hierarchy level has coordination limits that prevent runaway message loops while enabling effective delegation.

Each hierarchy level follows a distinct coordination strategy:

Executives delegate sequentially:

  • Process one department at a time to maintain control
  • Wait for each department to complete before delegating to the next
  • Use precise targeting (match_all=["manager"]) to message only direct reports, not workers
  • Higher tool limits (10) accommodate nested delegation flows

Managers delegate in parallel:

  • Can coordinate with multiple workers simultaneously
  • Provide specific, complete instructions so workers can complete tasks without asking questions
  • Moderate tool limits (5) allow multi-worker coordination
  • Report completion only after all workers finish

Workers complete immediately:

  • Execute tasks with reasonable assumptions when details are unclear
  • Store findings in shared archival memory
  • Low tool limits (2) for archival operations only, no coordination tools

The pattern’s key feature is controlled multi-layer coordination: Each manager uses the same send_message_to_agents_matching_tags tool to coordinate its team, but with different strategies. An executive delegates sequentially to managers using match_all=["manager"], match_some=["engineering"], who then delegate in parallel to workers using match_all=["worker", "engineering"], match_some=["backend"]. Tool rules at each layer prevent cascade messages where agents continuously respond to each other, consuming excessive tokens.

Implement the hierarchical teams pattern using the following steps.

All coordinating agents (executives and managers) need the send_message_to_agents_matching_tags tool:

from letta_client import Letta
import os
client = Letta(api_key=os.getenv("LETTA_API_KEY"))
# Get the coordination tool for all managers
tools = client.tools.list(name="send_message_to_agents_matching_tags")
broadcast_tool = tools.items[0]

This tool enables tag-based coordination at every hierarchy level. Executives delegate to managers, and managers delegate to workers using the same coordination mechanism.

Create shared resources that all hierarchy levels can access:

# Shared memory block for organizational guidelines
guidelines_block = client.blocks.create(
label="project_guidelines",
description="Project guidelines and priorities from executive leadership",
value="Priority: High-quality delivery. Timeline: 3 weeks. Coordinate across teams."
)
# Shared archive for project knowledge
project_archive = client.archives.create(
name="project_knowledge",
description="Shared knowledge base for all project contributors"
)

Create specialized workers at the bottom of the hierarchy:

# Backend engineer (Engineering team)
backend_engineer = client.agents.create(
name="backend_engineer",
model="anthropic/claude-sonnet-4-5-20250929",
memory_blocks=[{
"label": "persona",
"value": "I implement backend features: APIs, databases, authentication, and server logic. I complete tasks immediately with reasonable assumptions."
}],
block_ids=[guidelines_block.id, status_block.id],
tags=["worker", "engineering", "backend"],
tools=["archival_memory_insert", "archival_memory_search"],
tool_rules=[
{"tool_name": "archival_memory_insert", "type": "max_count_per_step", "max_count_limit": 2},
{"tool_name": "archival_memory_search", "type": "max_count_per_step", "max_count_limit": 2}
]
)
client.agents.archives.attach(project_archive.id, agent_id=backend_engineer.id)
# Frontend engineer (Engineering team)
frontend_engineer = client.agents.create(
name="frontend_engineer",
model="anthropic/claude-sonnet-4-5-20250929",
memory_blocks=[{
"label": "persona",
"value": "I implement frontend features: UI components, forms, and client-side logic. I complete tasks immediately with reasonable assumptions."
}],
block_ids=[guidelines_block.id, status_block.id],
tags=["worker", "engineering", "frontend"],
tools=["archival_memory_insert", "archival_memory_search"],
tool_rules=[
{"tool_name": "archival_memory_insert", "type": "max_count_per_step", "max_count_limit": 2},
{"tool_name": "archival_memory_search", "type": "max_count_per_step", "max_count_limit": 2}
]
)
client.agents.archives.attach(project_archive.id, agent_id=frontend_engineer.id)
# Content writer (Marketing team)
content_writer = client.agents.create(
name="content_writer",
model="anthropic/claude-sonnet-4-5-20250929",
memory_blocks=[{
"label": "persona",
"value": "I create marketing content: blog posts, documentation, and copy. I complete tasks immediately with reasonable assumptions."
}],
block_ids=[guidelines_block.id, status_block.id],
tags=["worker", "marketing", "content"],
tools=["archival_memory_insert", "archival_memory_search"],
tool_rules=[
{"tool_name": "archival_memory_insert", "type": "max_count_per_step", "max_count_limit": 2},
{"tool_name": "archival_memory_search", "type": "max_count_per_step", "max_count_limit": 2}
]
)
client.agents.archives.attach(project_archive.id, agent_id=content_writer.id)
# Designer (Marketing team)
designer = client.agents.create(
name="designer",
model="anthropic/claude-sonnet-4-5-20250929",
memory_blocks=[{
"label": "persona",
"value": "I create visual content: graphics, mockups, and design assets. I complete tasks immediately with reasonable assumptions."
}],
block_ids=[guidelines_block.id, status_block.id],
tags=["worker", "marketing", "design"],
tools=["archival_memory_insert", "archival_memory_search"],
tool_rules=[
{"tool_name": "archival_memory_insert", "type": "max_count_per_step", "max_count_limit": 2},
{"tool_name": "archival_memory_search", "type": "max_count_per_step", "max_count_limit": 2}
]
)
client.agents.archives.attach(project_archive.id, agent_id=designer.id)

The worker’s key features include:

  • Specialized expertise in specific domains (such as backend, frontend, content, or design)
  • Tags identifying both team membership (engineering or marketing) and specialty (backend, frontend, content, or design)
  • Access to the shared guidelines and project archive
  • No coordination tools (workers respond to managers; they do not delegate)

Create managers that coordinate their specialized teams:

# Engineering manager
eng_manager = client.agents.create(
name="engineering_manager",
model="anthropic/claude-sonnet-4-5-20250929",
memory_blocks=[{
"label": "persona",
"value": """I am the Engineering Manager coordinating technical development.
My team workers have tags: [worker, engineering]
- Backend engineers (tags: worker, engineering, backend)
- Frontend engineers (tags: worker, engineering, frontend)
PARALLEL DELEGATION:
- I can delegate to MULTIPLE workers SIMULTANEOUSLY
- I analyze tasks and determine which workers are needed
- I send SPECIFIC instructions to each worker (include framework, scope, defaults)
- I wait for ALL workers to complete before reporting back
I use send_message_to_agents_matching_tags to coordinate my team:
- For backend work: match_all=["worker", "engineering"], match_some=["backend"]
- For frontend work: match_all=["worker", "engineering"], match_some=["frontend"]
- For all engineering: match_all=["worker", "engineering"]
When delegating, I provide complete instructions so workers can complete tasks immediately without asking questions."""
}],
block_ids=[guidelines_block.id, status_block.id],
tags=["manager", "engineering"],
tool_ids=[broadcast_tool.id],
tool_rules=[
{"tool_name": "send_message_to_agents_matching_tags", "type": "max_count_per_step", "max_count_limit": 5}
]
)
client.agents.archives.attach(project_archive.id, agent_id=eng_manager.id)
# Marketing manager
marketing_manager = client.agents.create(
name="marketing_manager",
model="anthropic/claude-sonnet-4-5-20250929",
memory_blocks=[{
"label": "persona",
"value": """I am the Marketing Manager coordinating launch materials.
My team workers have tags: [worker, marketing]
- Content writers (tags: worker, marketing, content)
- Designers (tags: worker, marketing, design)
PARALLEL DELEGATION:
- I can delegate to MULTIPLE workers SIMULTANEOUSLY
- I analyze tasks and determine which workers are needed
- I send SPECIFIC instructions to each worker (include format, audience, key points)
- I wait for ALL workers to complete before reporting back
I use send_message_to_agents_matching_tags to coordinate my team:
- For written content: match_all=["worker", "marketing"], match_some=["content"]
- For design work: match_all=["worker", "marketing"], match_some=["design"]
- For all marketing: match_all=["worker", "marketing"]
When delegating, I provide complete instructions so workers can complete tasks immediately without asking questions."""
}],
block_ids=[guidelines_block.id, status_block.id],
tags=["manager", "marketing"],
tool_ids=[broadcast_tool.id],
tool_rules=[
{"tool_name": "send_message_to_agents_matching_tags", "type": "max_count_per_step", "max_count_limit": 5}
]
)
client.agents.archives.attach(project_archive.id, agent_id=marketing_manager.id)

Managers have the following critical requirements:

  • The persona must document which workers the manager coordinates with its tags.
  • The persona must show how to use match_all and match_some for targeting workers.
  • The persona must include parallel delegation instructions and guidance to provide specific instructions to workers.
  • Managers need both ["manager"] and a domain tag (such as ["engineering"] or ["marketing"]).
  • Managers must have the coordination tool and tool_rules with max_count_per_step: 5 to allow parallel delegation to multiple workers (and workers should not).
  • Managers have access to shared status blocks to track coordination state.

Create the executive agent that coordinates managers:

executive = client.agents.create(
name="executive_director",
model="anthropic/claude-sonnet-4-5-20250929",
memory_blocks=[{
"label": "persona",
"value": """I am the Executive Director coordinating high-level projects.
Available managers and their tags:
- Engineering manager (tags: manager, engineering) - Handles technical implementation
- Marketing manager (tags: manager, marketing) - Handles launch materials and marketing
SEQUENTIAL DELEGATION STRATEGY:
When I receive a task requiring multiple departments:
1. Analyze which departments are needed
2. Delegate to FIRST department and WAIT for completion
3. After first department completes, delegate to NEXT department
4. Continue until all departments complete
5. Synthesize final results
I use send_message_to_agents_matching_tags to coordinate managers:
- For technical work: match_all=["manager"], match_some=["engineering"]
- For marketing work: match_all=["manager"], match_some=["marketing"]
- For broad coordination: match_all=["manager"]
CRITICAL TARGETING:
- Always use match_all=["manager"], match_some=["department"] to target ONLY managers
- This prevents accidentally messaging workers directly
- Workers should only receive messages from their managers, not from me
I analyze projects and delegate to appropriate managers based on their expertise."""
}],
block_ids=[guidelines_block.id, status_block.id],
tags=["executive", "leadership"],
tool_ids=[broadcast_tool.id],
tool_rules=[
{"tool_name": "send_message_to_agents_matching_tags", "type": "max_count_per_step", "max_count_limit": 10}
]
)
client.agents.archives.attach(project_archive.id, agent_id=executive.id)

The executive’s key features include:

  • Sequential delegation strategy - Delegates to one department at a time to maintain control and prevent cascade messages
  • Higher tool limit (max_count_limit: 10) - Accommodates nested delegation where executive messages trigger manager delegations to workers within the same coordination flow
  • Precise targeting - Uses match_all=["manager"] to ensure only managers receive executive messages, preventing workers from receiving out-of-hierarchy instructions
  • Shared resource access - Can update guidelines, search archives, and track status across all hierarchy levels

Step 6: The executive coordinates the hierarchy

Section titled “Step 6: The executive coordinates the hierarchy”

The executive agent receives high-level tasks and autonomously coordinates work across hierarchy levels:

# Send complex multi-team project to executive
response = client.agents.messages.create(
agent_id=executive.id,
messages=[{
"role": "user",
"content": """Build a user authentication feature and create launch materials.
Engineering requirements:
- Backend: Authentication API with JWT tokens and database schema
- Frontend: Login form, signup form, and session management
Marketing requirements:
- Launch blog post announcing the feature
- Social media graphics for promotion
Please delegate to your managers and coordinate the implementation."""
}],
timeout=180 # Complex hierarchies may take longer
)

This pattern implements a three-tier workflow optimized for controlled, efficient coordination:

Executive (Sequential delegation):

  1. Analyzes the project scope to identify which departments are needed.
  2. Delegates to FIRST department using precise tag-based routing (match_all=["manager"], match_some=["engineering"])
  3. Waits for manager completion before proceeding to next department.
  4. Delegates to NEXT department (such as match_all=["manager"], match_some=["marketing"])
  5. Synthesizes results across all departments after all complete.

Managers (Parallel delegation):

  1. Receive task from executive and analyze which workers are needed.
  2. Delegate to MULTIPLE workers SIMULTANEOUSLY using tag-based routing:
    • Backend work: match_all=["worker", "engineering"], match_some=["backend"]
    • Frontend work: match_all=["worker", "engineering"], match_some=["frontend"]
    • Content work: match_all=["worker", "marketing"], match_some=["content"]
    • Design work: match_all=["worker", "marketing"], match_some=["design"]
  3. Provide specific, complete instructions so workers can complete tasks without asking questions.
  4. Wait for ALL workers to complete before reporting back.
  5. Synthesize team results and report completion upward to executive.

Workers (Immediate completion):

  1. Receive task from manager with specific instructions.
  2. Execute immediately using reasonable assumptions for any unclear details.
  3. Store findings in shared archive for cross-functional knowledge sharing.
  4. Return results to manager synchronously.

This three-tier workflow (sequential → parallel → immediate) balances control with efficiency. The executive maintains strategic oversight by processing one department at a time, managers maximize team productivity by coordinating workers in parallel, and workers complete tasks promptly to avoid coordination delays.

Here is a minimal two-layer hierarchy with a manager and workers:

from letta_client import Letta
import os
client = Letta(api_key=os.getenv("LETTA_API_KEY"))
# Get coordination tool
tools = client.tools.list(name="send_message_to_agents_matching_tags")
broadcast_tool = tools.items[0]
# Create shared resources
guidelines = client.blocks.create(
label="guidelines",
value="Deliver high-quality work on schedule."
)
status = client.blocks.create(
label="status",
value="" # Agents populate during coordination
)
archive = client.archives.create(name="team_knowledge")
# Create two workers
backend_worker = client.agents.create(
model="anthropic/claude-sonnet-4-5-20250929",
memory_blocks=[{
"label": "persona",
"value": "I implement backend features. I complete tasks immediately with reasonable assumptions."
}],
block_ids=[guidelines.id, status.id],
tags=["worker", "engineering", "backend"],
tools=["archival_memory_insert", "archival_memory_search"],
tool_rules=[
{"tool_name": "archival_memory_insert", "type": "max_count_per_step", "max_count_limit": 2},
{"tool_name": "archival_memory_search", "type": "max_count_per_step", "max_count_limit": 2}
]
)
client.agents.archives.attach(archive.id, agent_id=backend_worker.id)
frontend_worker = client.agents.create(
model="anthropic/claude-sonnet-4-5-20250929",
memory_blocks=[{
"label": "persona",
"value": "I implement frontend features. I complete tasks immediately with reasonable assumptions."
}],
block_ids=[guidelines.id, status.id],
tags=["worker", "engineering", "frontend"],
tools=["archival_memory_insert", "archival_memory_search"],
tool_rules=[
{"tool_name": "archival_memory_insert", "type": "max_count_per_step", "max_count_limit": 2},
{"tool_name": "archival_memory_search", "type": "max_count_per_step", "max_count_limit": 2}
]
)
client.agents.archives.attach(archive.id, agent_id=frontend_worker.id)
# Create manager with coordination tool
manager = client.agents.create(
model="anthropic/claude-sonnet-4-5-20250929",
memory_blocks=[{
"label": "persona",
"value": """I coordinate engineering work.
Team workers:
- Backend engineers (tags: worker, engineering, backend)
- Frontend engineers (tags: worker, engineering, frontend)
I use send_message_to_agents_matching_tags to delegate:
- Backend work: match_all=["worker", "engineering"], match_some=["backend"]
- Frontend work: match_all=["worker", "engineering"], match_some=["frontend"]
I provide specific instructions so workers can complete tasks immediately without asking questions."""
}],
block_ids=[guidelines.id, status.id],
tags=["manager", "engineering"],
tool_ids=[broadcast_tool.id],
tool_rules=[
{"tool_name": "send_message_to_agents_matching_tags", "type": "max_count_per_step", "max_count_limit": 5}
]
)
client.agents.archives.attach(archive.id, agent_id=manager.id)
# Manager delegates to workers
response = client.agents.messages.create(
agent_id=manager.id,
messages=[{
"role": "user",
"content": "Build a login feature with backend API and frontend form."
}]
)
# Manager analyzes task and routes work to both backend and frontend workers
# Cleanup
client.agents.delete(backend_worker.id)
client.agents.delete(frontend_worker.id)
client.agents.delete(manager.id)
client.archives.delete(archive.id)
client.blocks.delete(guidelines.id)
client.blocks.delete(status.id)
  • Use tool rules to prevent cascades: Always configure tool_rules with max_count_per_step limits for coordination tools. Without these limits, agents may continuously message each other across hierarchy layers, consuming excessive tokens. Set executives to 10 (for nested delegation), managers to 5 (for parallel worker delegation), and workers to 2 (for archival tools only).

  • Design clear hierarchies: Limit hierarchy depth to three or four layers maximum. Deeper hierarchies increase coordination complexity and latency.

  • Use precise tag targeting: Executives must use match_all=["manager"], match_some=["department"] to target ONLY managers and prevent accidentally broadcasting to workers. Workers should only receive messages from their direct managers, never from executives.

  • Include coordination protocols in personas: Add explicit instructions about when to delegate, when to wait for completion, and when to report back. Executives should delegate sequentially (one department at a time), managers should delegate in parallel (multiple workers simultaneously), and workers should complete immediately with reasonable assumptions.

  • Use descriptive tags: Tag agents by layer and specialty (such as ["manager", "engineering"], ["worker", "engineering", "backend"]) for precise routing.

  • Document team structures in personas: Each manager’s persona should list its direct reports with complete tags. This ensures accurate delegation.

  • Use status blocks for coordination state: Shared status blocks help agents track task assignments and completion, preventing coordination loops and duplicate work.

  • Share knowledge through archives: Use archival memory for cross-functional knowledge sharing. Workers and managers insert findings that the executive can search.

  • Managers should provide specific instructions: When delegating to workers, managers should include all necessary details (framework, scope, defaults, format, audience) so workers can complete tasks immediately without asking clarifying questions.

  • Start with bounded tasks: When testing hierarchical patterns, use simple, focused tasks (1-2 deliverables) to verify coordination works before scaling to complex multi-deliverable projects.

  • Expect async coordination: Complex hierarchies involve many agents working asynchronously. Use appropriate timeouts and query message histories to track their progress.

  • Check actual message counts in cloud: After running hierarchical workflows, verify message counts in the cloud to detect cascades. If you see significantly more messages than expected, review your tool rules and targeting patterns.