The Orchestration Question
Multi-agent systems need coordination. The fundamental question: should agent sequencing be predetermined (static) or decided at runtime (dynamic)?
Neither is universally better. The choice depends on task characteristics, cost constraints, and debugging requirements. This analysis covers how major frameworks handle orchestration and when to use each approach.
Definitions
Static Orchestration
Predetermined flows where agent sequencing is defined at design time.
User Request → Lead Agent → Worker A → Worker B → Output
↓ (fixed) ↓ (fixed)
GitHub Issue PR Creation
Characteristics:
- Predictable execution path
- Easy to debug and monitor
- Lower token cost per task
- May not adapt to unexpected situations
Dynamic Orchestration
LLM-driven routing where agent selection happens at runtime based on task state.
User Request → Orchestrator LLM → [Evaluates] → Agent X
↓ (decides)
[Evaluates result] → Agent Y or Z
↓ (decides)
[Continues until done]
Characteristics:
- Adapts to task complexity
- Can handle unexpected situations
- Higher token cost (routing decisions)
- Harder to predict and debug
Framework Comparison
How major frameworks handle orchestration:
| Framework | Static Options | Dynamic Options | Hybrid |
|---|---|---|---|
| Claude Agent SDK | Programmatic agents, MD files | Task tool auto-delegation | Yes |
| OpenAI Agents SDK | Code-driven chaining | LLM-driven handoffs | Yes |
| LangGraph | Sequential, Parallel nodes | Conditional routing | Yes |
| CrewAI | Sequential process | Hierarchical (manager) | Yes |
| AutoGen | RoundRobin, Swarm | SelectorGroupChat | Yes |
| Google ADK | SequentialAgent, ParallelAgent | LLM Transfer, AgentTool | Yes |
All major frameworks support both patterns. The question isn’t capability—it’s which to use when.
Claude Agent SDK (Anthropic)
Static Pattern (Programmatic/Filesystem Agents):
const options = {
agents: {
'code-reviewer': {
description: 'Security-focused code reviewer',
prompt: 'You are a security expert...',
tools: ['Read', 'Grep', 'Glob'],
model: 'sonnet'
}
}
};
Dynamic Pattern (Task Tool Auto-Delegation): The orchestrator decides when to spawn sub-agents. Sub-agents run with isolated contexts and return summaries.
Key differentiators:
- Context isolation: Each sub-agent has its own context window
- Native parallelization: Sub-agents run concurrently
- Hooks system: Fine-grained control (PreToolUse, SubagentStop, PostToolUse)
- No infrastructure: Markdown-based agents vs microservices
Performance: Orchestrator-worker pattern with Claude Opus 4 + Sonnet 4 sub-agents shows 90% improvement on complex research tasks vs single-agent.
OpenAI Agents SDK
Code-Driven (Static):
result = await research_agent.run(query)
outline = await outline_agent.run(result)
content = await writer_agent.run(outline)
final = await critic_agent.run(content)
LLM-Driven (Dynamic):
coordinator = Agent(
instructions="Route requests to specialists",
handoffs=[billing_agent, support_agent, technical_agent]
)
# LLM decides: "This is a billing question" → hands off
LangGraph
Graph-based with explicit edges for static flows, conditional functions for dynamic routing:
graph.add_conditional_edges(
"classifier",
route_based_on_category,
{"billing": "billing_agent", "technical": "tech_agent"}
)
CrewAI
Sequential (Static): Tasks execute linearly Hierarchical (Dynamic): Manager agent delegates and validates
Trade-off: Hierarchical adds a manager LLM call for every delegation decision.
Cost/Benefit Analysis
| Aspect | Static | Dynamic |
|---|---|---|
| Token cost | Lower | Higher (routing decisions) |
| Latency | Lower | Higher (routing overhead) |
| Predictability | High | Low |
| Adaptability | Low | High |
| Debug complexity | Simple | Complex |
| Error recovery | Explicit handling | May self-correct |
Evidence: Dynamic orchestration adds 15-25% token overhead for routing decisions. For simple tasks, this overhead exceeds the benefit.
When to Use Each
Use Static Orchestration When:
| Scenario | Why Static Works |
|---|---|
| Predictable workflows | Monitoring → Analysis → Report |
| Cost-sensitive operations | No routing overhead |
| Debugging/compliance needs | Clear execution trace |
| Writing-intensive tasks | Shared context crucial |
| Well-defined pipelines | Issue → Fix → PR → Review |
LangChain research confirms “writing-intensive tasks” and “domains requiring shared context” favor single/static agents.
Use Dynamic Orchestration When:
| Scenario | Why Dynamic Works |
|---|---|
| Unpredictable task scope | Don’t know which agents needed upfront |
| Complex research | May need multiple directions |
| User-facing routing | ”What’s my billing status?” |
| Multi-domain problems | Combine specialists as needed |
| Exploration tasks | Unknown number of steps |
Academic research (arXiv:2505.19591) shows dynamic orchestration “achieves superior performance with reduced computational costs” for complex problems where the path isn’t known upfront.
The Hybrid Approach
Most production systems benefit from hybrid orchestration:
Keep Static For:
| Workflow | Pattern | Rationale |
|---|---|---|
| Monitoring | Scheduled → Report | Predictable, cost-sensitive |
| PR Review | Event → Review → Decision | Fixed checklist |
| Issue Solving | Issue → Solution → PR | Well-defined pipeline |
| Content Updates | Brief → Issues → Build | Sequential dependency |
Add Dynamic For:
| Workflow | Pattern | Rationale |
|---|---|---|
| Research | Route to investigators | Unknown scope |
| User Requests | LLM routes to squad | Unpredictable intent |
| Complex Debugging | Route by error type | Need different specialists |
| Cross-Domain Work | Coordinator selects squads | Multi-domain |
Implementation
Phase 1: Enhanced Lead Pattern (Low Effort)
Enhance static leads with conditional sub-agent spawning:
## Enhanced Lead Pattern
1. Lead receives request
2. Lead analyzes: "What type of task is this?"
3. Lead spawns appropriate worker(s)
4. Lead evaluates results
5. Lead decides: done, or spawn more workers?
6. Lead synthesizes final output
This adds adaptability without full dynamic orchestration. The lead is still the single point of coordination, but it can adjust based on task needs.
Phase 2: Router Agent (Medium Effort)
Central router for user requests:
## Router Pattern
User: "Help me understand our agent costs"
Router LLM evaluates:
- Involves costs → finance squad?
- Involves agents → engineering squad?
- Internal analysis → intel squad?
Router: Spawns intel-lead with request context
The router handles the initial classification. Once routed, the receiving squad uses its normal (often static) workflows.
Phase 3: Full Dynamic (High Effort, Defer)
Full dynamic orchestration (RL-trained coordinators, learned routing) requires significant training data. Wait until you have enough execution traces to train on.
Handoff Protocol
For any orchestration pattern, handoffs need structure:
Handoff Message
{
"from_agent": "research-lead",
"to_agent": "technical-investigator",
"task": {
"objective": "Investigate context engineering patterns",
"constraints": ["Max 2 hours", "Focus on practical"],
"expected_output": "Deep-dive document with evidence",
"context_summary": "Building multi-agent systems, need context optimization"
},
"callback": {
"on_complete": "Update GitHub issue #2",
"on_failure": "Escalate to human"
}
}
Handoff Response
{
"from_agent": "technical-investigator",
"to_agent": "research-lead",
"status": "complete",
"result_summary": "Created deep-dive covering 4 techniques...",
"artifacts": ["research/analyses/context-engineering/..."],
"follow_up_needed": ["Update skill", "Add tracking"]
}
Structured handoffs work for both static and dynamic patterns. The difference is who decides the next step.
Anti-Patterns
1. Over-Dynamic
Pattern: Using LLM routing for every decision Problem: High token cost, unpredictable behavior Fix: Reserve dynamic for genuinely unpredictable tasks
2. Under-Dynamic
Pattern: Rigid static flows that can’t adapt Problem: Fails on edge cases Fix: Add conditional branches for known variations
3. Delegation Without Context
Pattern: Routing to specialist without enough context Problem: Agent lacks information to succeed Fix: Use explicit handoff protocol
4. No Fallback
Pattern: Dynamic routing without error handling Problem: Infinite loops, stuck states Fix: Max iterations, timeout, human escalation
5. Shared Context Pollution
Pattern: All agents see all context Problem: Context rot, confusion, high cost Fix: Fresh context per worker, summaries for handoffs
Metrics to Track
| Metric | What It Measures | Target |
|---|---|---|
| Routing accuracy | % correct agent selection | > 90% |
| Handoff success | % handoffs completing | > 85% |
| Dynamic overhead | Additional tokens for routing | < 20% |
| Escalation rate | % requiring human intervention | < 10% |
Decision Framework
Is the workflow predictable?
├── Yes → Use static orchestration
└── No → Is cost critical?
├── Yes → Use enhanced lead (Phase 1)
└── No → Is scope bounded?
├── Yes → Use router pattern (Phase 2)
└── No → Consider full dynamic (Phase 3)
Most workflows are predictable. Start static, add dynamism only where needed.
Summary
| Approach | Best For | Token Overhead | Debugging |
|---|---|---|---|
| Static | Predictable workflows | Baseline | Simple |
| Enhanced Lead | Semi-predictable | +10-15% | Moderate |
| Router | User requests | +15-20% | Moderate |
| Full Dynamic | Complex exploration | +20-30% | Complex |
The hybrid approach works: static for predictable workflows, dynamic for unpredictable ones. Start with Phase 1 (enhanced leads) and add complexity only when measurements show it’s needed.
Sources: Claude Agent SDK (Anthropic), OpenAI Agents SDK, LangGraph, CrewAI, AutoGen, Google ADK documentation. Academic: arXiv:2505.19591 (Multi-Agent Collaboration via Evolving Orchestration).