Orchestration
Patterns for coordinating single and multi-agent systems
Orchestration
Orchestration is how you coordinate agent execution — from a single agent handling everything, to specialized agents collaborating on complex tasks. The SDK supports five orchestration patterns, each with different trade-offs.
Start Simple
The golden rule of agent orchestration:
Start with a single agent. Add multi-agent structure only when you have a clear reason.
Most tasks don't need multi-agent systems. A single well-configured agent with good tools handles the majority of use cases. Add complexity only when you hit real limits.
Pattern 1: Single Agent
The simplest and most common pattern. One agent with tools and guardrails.
const agent = new Agent({
name: 'assistant',
model: claude('claude-sonnet-4-6'),
instructions: 'You are a helpful assistant.',
tools: [webSearch, calculator, fileReader],
})
const result = await Runner.run(agent, { messages })When to use: 90% of cases. Use until you can articulate why you need more.
Pattern 2: Sequential Pipeline
Agents run in sequence, each transforming the output for the next:
import { Pipeline } from 'assistme-agent-sdk'
const pipeline = Pipeline.create([
{
agent: researcher,
map: (input) => ({ messages: [{ role: 'user', content: `Research: ${input}` }] }),
},
{
agent: writer,
map: (researchResult) => ({
messages: [{ role: 'user', content: `Write an article based on: ${researchResult.output}` }],
}),
},
{
agent: editor,
map: (draft) => ({
messages: [{ role: 'user', content: `Edit and polish: ${draft.output}` }],
}),
},
])
const result = await pipeline.run('Quantum computing advances in 2026')
// researcher → writer → editor → final polished articleWhen to use: Assembly-line processing where each step has a clear input/output contract.
Pattern 3: Parallel Execution
Run independent agents concurrently for lower latency:
import { Parallel } from 'assistme-agent-sdk'
const results = await Parallel.run([
{ agent: newsAgent, input: { messages: [{ role: 'user', content: 'Latest tech news' }] } },
{ agent: weatherAgent, input: { messages: [{ role: 'user', content: 'Weather in SF' }] } },
{ agent: stockAgent, input: { messages: [{ role: 'user', content: 'Market summary' }] } },
])
// All three run concurrently
// Total time ≈ slowest agent, not sum of all three
console.log(results.map(r => r.output))Parallel with Aggregation
const briefing = await Parallel.run(
[
{ agent: newsAgent, input: newsInput },
{ agent: weatherAgent, input: weatherInput },
{ agent: stockAgent, input: stockInput },
],
{
aggregate: async (results) => {
// Combine results into a morning briefing
return Runner.run(summaryAgent, {
messages: [{
role: 'user',
content: `Create a morning briefing from:\n${results.map(r => r.output).join('\n---\n')}`,
}],
})
},
},
)When to use: Independent subtasks that can run concurrently. Same total token cost, ~60% lower wall-clock time.
Pattern 4: Router
A routing agent classifies the input and dispatches to specialists:
import { Router } from 'assistme-agent-sdk'
const router = Router.create({
model: claude('claude-haiku-4-5'), // Fast, cheap model for routing
routes: [
{
agent: codeAgent,
description: 'Questions about writing, debugging, or reviewing code',
},
{
agent: dataAgent,
description: 'Questions about data analysis, SQL, or statistics',
},
{
agent: writingAgent,
description: 'Writing tasks: emails, articles, summaries',
},
{
agent: generalAgent,
description: 'General knowledge questions and conversation',
},
],
fallback: generalAgent,
})
const result = await Router.run(router, { messages })The router uses a lightweight model to classify the request, then dispatches to the appropriate specialist. The specialist gets a clean context without the routing overhead.
When to use: Mixed-complexity requests where different types benefit from specialized agents.
Pattern 5: Supervisor (Hierarchical)
A supervisor agent manages a team, delegating tasks and synthesizing results:
const supervisor = new Agent({
name: 'supervisor',
model: claude('claude-sonnet-4-6'),
instructions: `You are a project manager. Break down complex requests into subtasks
and delegate them to your team. Synthesize the results into a coherent response.`,
tools: [
researcher.asTool({ name: 'research', description: 'Research a topic' }),
coder.asTool({ name: 'write_code', description: 'Write or review code' }),
analyst.asTool({ name: 'analyze_data', description: 'Analyze data or metrics' }),
],
})
const result = await Runner.run(supervisor, {
messages: [{
role: 'user',
content: 'Build a dashboard showing our top 10 customers by revenue with trend charts',
}],
})The supervisor decides which agents to involve, what to delegate, and how to combine results. Each sub-agent runs in isolation with its own context window.
When to use: Complex tasks requiring coordination across different skill domains.
Comparing Patterns
| Pattern | Latency | Token Cost | Error Recovery | Complexity |
|---|---|---|---|---|
| Single Agent | Low | Low | Simple | Lowest |
| Sequential | High | Moderate | Moderate | Low |
| Parallel | Low | Same total | Good (isolated) | Low |
| Router | Low | Low (cheap classifier) | Good | Moderate |
| Supervisor | Variable | Highest | Best | Highest |
Combining Patterns
Real systems often combine patterns:
// Router → dispatches to specialists
// Each specialist may use parallel sub-agents
// Results flow through a sequential pipeline
const router = Router.create({
routes: [
{
agent: new Agent({
name: 'research-team',
tools: [
// Sub-agents run in parallel
sourceA.asTool({ name: 'search_academic' }),
sourceB.asTool({ name: 'search_news' }),
sourceC.asTool({ name: 'search_patents' }),
],
}),
description: 'Research questions requiring multiple sources',
},
],
})Context Isolation
Each agent in a multi-agent system gets its own context window. This is critical for:
- Token efficiency — Sub-agents don't carry the parent's full context
- Focus — Agents perform better with relevant-only context
- Security — Agents can't see each other's tool results unless explicitly shared
// The researcher explores using 50,000 tokens internally
// But returns only a 2,000 token summary to the supervisor
const researcher = new Agent({
name: 'researcher',
model: claude('claude-sonnet-4-6'),
instructions: 'Research thoroughly, then return a concise summary of findings.',
tools: [webSearch, readUrl],
})
// The supervisor only sees the summary in its context
const supervisor = new Agent({
name: 'supervisor',
tools: [researcher.asTool({ name: 'research' })],
})Best Practices
-
Single agent first — Don't reach for multi-agent until single agent fails. The overhead of coordination often exceeds the benefit.
-
Use the cheapest pattern that works — Router > Pipeline > Parallel > Supervisor in terms of simplicity.
-
Isolate contexts — Never share full context between agents. Summarize and pass only what's needed.
-
Use cheap models for routing — Haiku-class models are excellent routers. Don't waste Opus-class on classification.
-
Set maxTurns on every agent — Especially sub-agents. A runaway sub-agent can blow up costs.
-
Monitor token usage — Multi-agent systems can use tokens faster than expected. Track per-agent and total usage.