Skip to content
Sign up
Agents
Multi-agent patterns

The round-robin pattern

Distribute tasks evenly across multiple agents using a rotating sequence to ensure fair workload distribution and prevent any single agent from being overloaded.

Distribute incoming tasks evenly across multiple agents in a fixed rotation sequence. Each agent processes tasks in turn, ensuring fair workload distribution and preventing any single agent from being overwhelmed.

Round-Robin Pattern Architecture

The round-robin pattern works well when you need to:

  • Distribute high-volume tasks evenly across multiple agents
  • Prevent workload concentration on any single agent
  • Ensure fair processing where each agent gets equal opportunity
  • Maintain diverse perspectives by rotating agents through different tasks

A social media platform receives flagged content for moderation review. Three moderator agents review flagged posts in rotation:

  • Agent A reviews posts 1, 4, 7, 10…
  • Agent B reviews posts 2, 5, 8, 11…
  • Agent C reviews posts 3, 6, 9, 12…

This approach ensures each moderator handles an equal share of reviews, prevents any single moderator from being overloaded, and exposes each moderator to diverse content types. Each agent maintains memory of previous decisions, learning moderation patterns and policy edge cases over time.

The pattern uses three key components:

  1. A pool of agents with similar capabilities that process tasks independently.
  2. A rotation index maintained by the client to track which agent receives the next task.
  3. Client orchestration that distributes tasks sequentially to agents in the rotation order.

The client orchestrates the workflow:

  • The client maintains a list of agents in rotation order.
  • For each incoming task, the client sends it to the current agent in the sequence.
  • The client advances the rotation index to the next agent.
  • When the index reaches the end of the list, it wraps back to the first agent.

Implement a round-robin pattern using the following steps.

Create multiple agents with similar capabilities. These agents will process tasks in rotation:

from letta_client import Letta
import os
client = Letta(api_key=os.getenv("LETTA_API_KEY"))
# Create three moderator agents
moderator_a = client.agents.create(
name="moderator_a",
model="anthropic/claude-sonnet-4-5-20250929",
memory_blocks=[{
"label": "persona",
"value": "I review flagged social media posts for policy violations. I evaluate content against community guidelines and make moderation decisions."
}]
)
moderator_b = client.agents.create(
name="moderator_b",
model="anthropic/claude-sonnet-4-5-20250929",
memory_blocks=[{
"label": "persona",
"value": "I review flagged social media posts for policy violations. I evaluate content against community guidelines and make moderation decisions."
}]
)
moderator_c = client.agents.create(
name="moderator_c",
model="anthropic/claude-sonnet-4-5-20250929",
memory_blocks=[{
"label": "persona",
"value": "I review flagged social media posts for policy violations. I evaluate content against community guidelines and make moderation decisions."
}]
)

Each agent has the same capabilities but maintains independent memory of their own moderation history.

Create a list of agents and initialize the rotation index:

# Define rotation order
moderators = [moderator_a, moderator_b, moderator_c]
# Track current position in rotation
current_index = 0

The rotation index determines which agent receives the next task.

For each incoming task, send it to the current agent and advance the rotation:

# Example: flagged posts arriving for review
flagged_posts = [
"Post 1: User shared potentially misleading health information",
"Post 2: Comment contains targeted harassment",
"Post 3: Image may violate copyright",
"Post 4: Spam advertisement posted multiple times",
"Post 5: Hate speech reported by users"
]
# Distribute posts to moderators in round-robin fashion
for post in flagged_posts:
# Get current moderator
current_moderator = moderators[current_index]
# Send task to current moderator
response = client.agents.messages.create(
agent_id=current_moderator.id,
messages=[{"role": "user", "content": f"Review this flagged post: {post}"}]
)
print(f"{current_moderator.name} reviewed: {post}")
print(f"Decision: {response.messages[-1].content}\n")
# Advance to next moderator (with wraparound)
current_index = (current_index + 1) % len(moderators)

The modulo operation % len(moderators) ensures the index wraps back to 0 after reaching the last agent.

Each agent processes tasks independently and maintains its own memory:

# Check what each moderator remembers
for moderator in moderators:
messages = client.agents.messages.list(agent_id=moderator.id)
print(f"{moderator.name} has reviewed {len(messages)} posts")

Each agent builds up moderation experience from the posts it reviews.

Here’s a complete minimal example showing round-robin task distribution:

from letta_client import Letta
import os
client = Letta(api_key=os.getenv("LETTA_API_KEY"))
# Create three agents
agents = []
for i in range(3):
agent = client.agents.create(
name=f"agent_{i}",
model="anthropic/claude-sonnet-4-5-20250929",
memory_blocks=[{
"label": "persona",
"value": f"I am agent {i}. I process tasks assigned to me."
}]
)
agents.append(agent)
# Distribute tasks in round-robin
tasks = ["Task 1", "Task 2", "Task 3", "Task 4", "Task 5", "Task 6"]
current_index = 0
for task in tasks:
current_agent = agents[current_index]
client.agents.messages.create(
agent_id=current_agent.id,
messages=[{"role": "user", "content": task}]
)
print(f"{current_agent.name} received {task}")
current_index = (current_index + 1) % len(agents)

Output:

agent_0 received Task 1
agent_1 received Task 2
agent_2 received Task 3
agent_0 received Task 4
agent_1 received Task 5
agent_2 received Task 6

This example demonstrates a complete content moderation system using round-robin distribution:

from letta_client import Letta
import os
client = Letta(api_key=os.getenv("LETTA_API_KEY"))
# Step 1: Create three moderator agents with shared guidelines
moderators = []
for i in range(3):
moderator = client.agents.create(
name=f"moderator_{chr(65 + i)}", # A, B, C
model="anthropic/claude-sonnet-4-5-20250929",
memory_blocks=[
{
"label": "persona",
"value": f"I am Moderator {chr(65 + i)}. I review flagged content and make moderation decisions."
},
{
"label": "guidelines",
"value": """Community Guidelines:
- Hate speech: Remove
- Harassment: Remove
- Misinformation: Flag for fact-check
- Spam: Remove
- Copyright violations: Flag for review
- Minor policy violations: Warn user"""
}
]
)
moderators.append(moderator)
# Step 2: Simulate incoming flagged content
flagged_content = [
{"id": 1, "content": "User posting spam links repeatedly"},
{"id": 2, "content": "Comment contains targeted harassment"},
{"id": 3, "content": "Potential copyright violation in shared image"},
{"id": 4, "content": "Misleading product claims in advertisement"},
{"id": 5, "content": "Hate speech targeting protected group"},
{"id": 6, "content": "Minor profanity in comment thread"}
]
# Step 3: Distribute reviews in round-robin fashion
current_index = 0
moderation_results = []
for item in flagged_content:
# Get current moderator in rotation
current_moderator = moderators[current_index]
# Send moderation task
response = client.agents.messages.create(
agent_id=current_moderator.id,
messages=[{
"role": "user",
"content": f"Review flagged content ID {item['id']}: {item['content']}. Provide your moderation decision."
}]
)
# Record result
decision = response.messages[-1].content
moderation_results.append({
"content_id": item["id"],
"moderator": current_moderator.name,
"decision": decision
})
print(f"Content ID {item['id']}{current_moderator.name}")
print(f"Decision: {decision}\n")
# Advance rotation
current_index = (current_index + 1) % len(moderators)
# Step 4: Verify workload distribution
print("Workload distribution:")
for moderator in moderators:
messages = client.agents.messages.list(agent_id=moderator.id)
count = len([m for m in messages if m.role == "user"])
print(f"{moderator.name}: {count} reviews")

Expected output:

Content ID 1 → moderator_A
Decision: Remove - Spam violation
Content ID 2 → moderator_B
Decision: Remove - Harassment policy violation
Content ID 3 → moderator_C
Decision: Flag for copyright review
Content ID 4 → moderator_A
Decision: Flag for fact-check - Health misinformation
Content ID 5 → moderator_B
Decision: Remove - Hate speech violation
Content ID 6 → moderator_C
Decision: Warn user - Minor profanity
Workload distribution:
moderator_A: 2 reviews
moderator_B: 2 reviews
moderator_C: 2 reviews
  • Define clear agent capabilities: Each agent in the pool should have similar capabilities. Round-robin assumes agents are interchangeable. Avoid mixing agents with different specializations in a round-robin pool. Use the supervisor-worker pattern instead for specialized routing.

  • Track rotation state: Maintain the rotation index as part of your application state. If your application restarts, persist the index to resume the rotation.

  • Monitor agent workload: Verify that tasks distribute evenly across agents. Large differences in task counts may indicate an issue with rotation logic.

  • Consider agent capacity: Round-robin assumes all agents have equal processing capacity. If agents process tasks at different speeds, the pattern will still distribute tasks evenly, which may lead to bottlenecks. For scenarios where agents have different capacities or availability, consider alternative patterns like weighted distribution or dynamic load balancing.

  • Use consistent agent ordering: Maintain a consistent rotation order across application restarts to ensure predictable task distribution over time.