Multi-Agent Orchestration: Conductor Patterns for AI Teams
By Diesel
multi-agentorchestrationarchitecture
## The Orchestra Problem
You've got five AI agents. They're all brilliant individually. Put them in a room together and they produce garbage. Sound familiar?
This is the orchestration problem. It's not new. Distributed systems engineers have been solving it for decades. But AI agents add a twist: they're non-deterministic, they hallucinate, and they have opinions. Orchestrating them isn't like orchestrating microservices. It's like herding cats that think they're conductors.
I've built multi-agent systems that coordinate 15+ agents in real-time. The patterns I'm about to walk through aren't theoretical. They're battle-tested. Some of them have the scars to prove it. For a deeper look, see [the supervisor pattern](/blog/supervisor-pattern-agent-managers).
## Pattern 1: The Central Conductor
The simplest pattern. One agent runs the show. Every other agent reports to it, receives tasks from it, and sends results back to it.
```python
class Conductor:
def orchestrate(self, task):
plan = self.planner.decompose(task)
results = {}
for step in plan.steps:
agent = self.router.select(step)
result = agent.execute(step)
results[step.id] = result
plan = self.planner.replan(plan, results)
return self.synthesizer.merge(results)
```
The conductor decomposes, delegates, collects, and synthesizes. Clean separation of concerns.
**When it works:** Tasks with clear decomposition. Research pipelines. Sequential workflows where step N depends on step N-1.
**When it breaks:** The conductor becomes a bottleneck. Every message routes through one agent. If the conductor hallucinates or misroutes, the entire pipeline goes sideways. And it will. At scale, the conductor's context window fills up tracking all the state, and quality degrades.
## Pattern 2: Choreography
No conductor. Agents communicate peer-to-peer through events. Each agent knows its trigger conditions and acts autonomously when those conditions are met.
```python
class ChoreographedAgent:
def __init__(self, event_bus):
self.bus = event_bus
self.bus.subscribe("code.written", self.on_code_written)
async def on_code_written(self, event):
review = await self.review(event.code)
await self.bus.publish("code.reviewed", review)
```
Think of it like a relay race. The baton passes from agent to agent based on events, not commands.
**When it works:** Loosely coupled workflows. CI/CD-style pipelines. Systems where agents have clear, non-overlapping responsibilities.
**When it breaks:** Debugging becomes a nightmare. When something goes wrong, there's no central log of "who did what and why." You're tracing events across a distributed system with non-deterministic participants. Good luck. This connects directly to [topology choices](/blog/multi-agent-topology-hierarchical-flat).
## Pattern 3: Hierarchical Delegation
A tree structure. The top-level agent delegates to mid-level managers, who delegate to specialists. Each level only communicates with the level directly above and below it.
```
Architect
/ \
Frontend Backend
/ \ / \
React CSS API Database
```
This is the pattern I use most in production. It naturally limits context contamination. The architect doesn't need to know about CSS specifics. The CSS agent doesn't need to know about database schemas. Each agent operates with a focused context window, which means better output quality.
**When it works:** Complex projects with clear domain boundaries. Enterprise systems. Anything where you'd have a team of human specialists.
**When it breaks:** Deep hierarchies add latency. If you're four levels deep, a simple question from the CSS agent takes four round trips to reach the architect. You need to balance depth against responsiveness.
## Pattern 4: The Blackboard
A shared workspace that all agents can read from and write to. Agents watch the blackboard for relevant changes and contribute their expertise.
```python
class BlackboardAgent:
def __init__(self, blackboard, expertise):
self.board = blackboard
self.expertise = expertise
async def observe_and_act(self):
while True:
state = await self.board.watch(self.expertise)
if self.can_contribute(state):
contribution = await self.analyze(state)
await self.board.write(contribution)
```
This is borrowed from classic AI. It works surprisingly well for creative and analytical tasks where you don't know the workflow in advance. Agents self-organize around the problem. For a deeper look, see [inter-agent communication](/blog/agent-communication-protocols).
**When it works:** Open-ended analysis. Brainstorming. Problems where the solution path isn't predetermined.
**When it breaks:** Race conditions. Two agents write conflicting analyses. Without conflict resolution (see my article on consensus), the blackboard becomes a mess. You also need careful access control. Not every agent should write everywhere.
## Pattern 5: Pipeline with Feedback Loops
A linear pipeline where output flows forward, but quality gates can send work backward for revision.
```python
class PipelineStage:
def __init__(self, agent, next_stage, quality_gate):
self.agent = agent
self.next = next_stage
self.gate = quality_gate
async def process(self, input, attempts=0):
result = await self.agent.execute(input)
if self.gate.passes(result):
return await self.next.process(result)
if attempts < 3:
feedback = self.gate.explain_failure(result)
return await self.process(
input.with_feedback(feedback),
attempts + 1
)
raise QualityGateFailure(result)
```
The feedback loop is what makes this production-grade. Without it, errors cascade forward and compound. A bad code generation at stage 2 means a bad review at stage 3 means a bad deployment at stage 4.
**When it works:** Any linear workflow where quality matters. Code generation pipelines. Content creation. Data processing.
**When it breaks:** Infinite loops. If the quality gate is too strict and the agent can't improve, you get stuck. Always cap retry attempts and have an escalation path.
## Choosing Your Pattern
There's no universal winner. The decision matrix looks like this:
- **Clear sequential workflow** → Pipeline with Feedback
- **Known decomposition, moderate complexity** → Central Conductor
- **Deep domain specialization needed** → Hierarchical Delegation
- **Loosely coupled, event-driven** → Choreography
- **Open-ended, exploratory** → Blackboard
Most production systems use hybrids. I run hierarchical delegation with a blackboard for shared context and pipelines within each delegation branch. The top-level architect uses conductor logic to coordinate branches, while the leaf agents run choreographed review cycles.
## The Part Nobody Talks About
The pattern matters less than the error handling. In every pattern above, the happy path is easy. It's the failure modes that kill you.
What happens when an agent times out? What happens when it returns confidently wrong results? What happens when two agents deadlock waiting on each other? What happens when the conductor agent gets compacted mid-orchestration and loses its plan?
Every pattern needs: retry logic with backoff, circuit breakers per agent, timeout budgets that cascade (if the total budget is 60 seconds, agent 3 of 5 doesn't get to burn 45 of them), result validation that doesn't trust agent self-assessment, and graceful degradation when agents fail.
The orchestration pattern is the skeleton. Error handling is the immune system. Build both, or build neither.
## What I'd Build Today
If I were starting a new multi-agent system tomorrow, I'd start with hierarchical delegation, add a shared memory layer (not a full blackboard, just key context), and implement pipeline-with-feedback at each leaf level. Central conductor only as a last resort. It's the pattern that scales worst and fails loudest.
The agent revolution isn't about smarter agents. It's about smarter coordination. Get the orchestra right, and even mediocre musicians sound good.