Orchestrator Pattern: Coordinating Multiple Skills
Master the orchestrator pattern for AI skills that coordinate multiple sub-skills, managing parallel execution, dependencies, and result aggregation.
Orchestrator Pattern: Coordinating Multiple Skills
When complex tasks require multiple specialized skills working together, the orchestrator pattern takes command. An orchestrator does not do the detailed work itself—it delegates to specialized sub-skills, manages their execution, handles dependencies, and aggregates their results into a coherent whole.
Think of an orchestrator like a conductor leading an orchestra. The conductor does not play every instrument but ensures all musicians play at the right time, in harmony, to create something greater than any individual could produce alone.
In this guide, we will explore how to design and implement orchestrator skills that coordinate multiple sub-skills effectively, whether they run in sequence, in parallel, or in complex dependency graphs.
Understanding the Orchestrator Pattern
The orchestrator pattern follows a coordination flow:
Input → [Orchestrator]
│
┌─────────┼─────────┐
↓ ↓ ↓
[Skill A] [Skill B] [Skill C]
│ │ │
└─────────┼─────────┘
↓
[Aggregate]
↓
Output
The orchestrator:
- Receives the task
- Plans execution (which skills, what order)
- Dispatches to sub-skills
- Monitors execution
- Aggregates results
- Returns unified output
Core Characteristics
Orchestrator skills have distinct properties:
Delegation Focus: The orchestrator coordinates; sub-skills execute.
Dependency Management: Handles prerequisites between sub-skills.
Parallel Execution: Runs independent sub-skills concurrently when possible.
Result Aggregation: Combines sub-skill outputs into unified results.
Error Coordination: Manages failures across multiple sub-skills.
When to Use Orchestrator
The orchestrator pattern excels when:
- Tasks require multiple specialized capabilities
- Sub-skills can run independently
- Results need to be combined in specific ways
- Complex dependencies exist between components
- Different aspects require different expertise
When Not to Use Orchestrator
Avoid orchestrator when:
- A single skill can handle the task
- Sub-skills are tightly coupled (use chain instead)
- Overhead of coordination exceeds benefit
- Tasks are simple transformations
Designing Orchestrator Skills
Effective orchestrators require careful planning of skill coordination.
Defining Sub-Skills
Identify and define the sub-skills the orchestrator will manage:
## Sub-Skill Registry
### Available Skills
```yaml
skills:
code-analyzer:
capabilities: [complexity, security, style]
input: { code: string, language: string }
output: { issues: Issue[], metrics: Metrics }
timeout: 30s
retries: 2
documentation-generator:
capabilities: [api-docs, readme, changelog]
input: { code: string, existing: string? }
output: { documentation: string }
timeout: 45s
retries: 1
test-writer:
capabilities: [unit, integration, e2e]
input: { code: string, framework: string }
output: { tests: Test[] }
timeout: 60s
retries: 2
dependency-checker:
capabilities: [outdated, vulnerabilities, licenses]
input: { manifest: string }
output: { report: DependencyReport }
timeout: 20s
retries: 3
Skill Contracts
Each skill must:
- Have defined input/output schemas
- Respect timeout constraints
- Return structured errors
- Be independently testable
### Execution Planning
Plan how sub-skills execute:
```markdown
## Execution Planner
### Dependency Graph
```yaml
dependencies:
documentation-generator:
requires: [code-analyzer]
reason: "Uses analysis to document issues"
test-writer:
requires: [code-analyzer]
reason: "Tests should cover identified issues"
dependency-checker:
requires: []
reason: "Independent of code analysis"
Execution Order
Given dependencies, determine order:
- Identify skills with no dependencies (can start immediately)
- Group skills that can run in parallel
- Schedule dependent skills after prerequisites complete
Execution Plan Example
Phase 1 (parallel):
- code-analyzer
- dependency-checker
Phase 2 (parallel, after Phase 1):
- documentation-generator (needs code-analyzer)
- test-writer (needs code-analyzer)
Phase 3 (sequential):
- aggregate-results (needs all above)
### Result Aggregation
Define how sub-skill outputs combine:
```markdown
## Aggregation Strategy
### Merge Strategies
```yaml
strategies:
code-review:
merge: deep-merge
conflictResolution: priority-based
structure:
issues: concatenate
metrics: combine
summary: synthesize
report-generation:
merge: templated
template: |
# Analysis Report
## Code Quality: {code-analyzer.summary}
## Dependencies: {dependency-checker.summary}
## Documentation: {documentation-generator.status}
## Test Coverage: {test-writer.coverage}
Conflict Resolution
When sub-skills disagree:
- Priority: Higher-priority skill wins
- Voting: Majority of skills determines result
- Merge: Include both perspectives
- Escalate: Flag for human decision
## Implementing Orchestrator Skills
Let us build a complete orchestrator skill.
### Example: Comprehensive Code Review Orchestrator
```markdown
---
name: comprehensive-code-review
description: Orchestrates multiple skills for complete code review
version: 1.0.0
---
# Comprehensive Code Review Orchestrator
Coordinate multiple specialized reviewers for thorough code review.
## Architecture
┌───────────────────┐
│ Orchestrator │
│ (Coordinator) │
└─────────┬─────────┘
│
┌─────────────────────┼─────────────────────┐
│ │ │
↓ ↓ ↓
┌───────────────┐ ┌───────────────┐ ┌───────────────┐ │ Security │ │ Performance │ │ Style │ │ Reviewer │ │ Reviewer │ │ Reviewer │ └───────┬───────┘ └───────┬───────┘ └───────┬───────┘ │ │ │ └─────────────────────┼─────────────────────┘ ↓ ┌───────────────────┐ │ Result │ │ Aggregator │ └───────────────────┘
---
## Input
```json
{
"files": [
{
"path": "src/api/handler.ts",
"content": "source code..."
}
],
"options": {
"security": true,
"performance": true,
"style": true,
"documentation": true,
"tests": false
},
"config": {
"severity": "normal",
"maxIssues": 50,
"parallel": true
}
}
Phase 1: Planning
Skill Selection
Based on options, select active skills:
function selectSkills(options: Options): Skill[] {
const skills: Skill[] = [];
if (options.security) skills.push(securityReviewer);
if (options.performance) skills.push(performanceReviewer);
if (options.style) skills.push(styleReviewer);
if (options.documentation) skills.push(docReviewer);
if (options.tests) skills.push(testReviewer);
return skills;
}
Dependency Resolution
dependencies:
docReviewer:
after: [styleReviewer]
reason: "Documentation quality relates to code clarity"
testReviewer:
after: [securityReviewer, performanceReviewer]
reason: "Tests should verify security and performance"
# Security, Performance, Style have no dependencies
Execution Plan
execution:
phase1:
parallel: true
skills:
- securityReviewer
- performanceReviewer
- styleReviewer
phase2:
parallel: true
skills:
- docReviewer
waitFor: [styleReviewer]
phase3:
parallel: false
skills:
- testReviewer
waitFor: [securityReviewer, performanceReviewer]
Phase 2: Dispatch
Skill Invocation
For each skill in the execution plan:
## Dispatch Protocol
1. **Prepare Input**
- Extract relevant files for skill
- Include configuration
- Add context from previous phases if applicable
2. **Invoke Skill**
- Send request to skill
- Set timeout alarm
- Monitor for completion
3. **Handle Response**
- Success: Store result, mark complete
- Timeout: Retry or mark failed
- Error: Log, retry, or mark failed
4. **Update State**
- Mark skill complete
- Check if dependents can now run
- Trigger next phase if ready
Parallel Execution
async function executePhase(phase: Phase): Promise<Results> {
const promises = phase.skills.map(skill =>
executeSkill(skill)
.catch(error => ({
skill: skill.name,
success: false,
error
}))
);
return Promise.all(promises);
}
Progress Tracking
{
"status": "in_progress",
"phases": {
"phase1": {
"status": "complete",
"skills": {
"securityReviewer": { "status": "complete", "duration": 2500 },
"performanceReviewer": { "status": "complete", "duration": 3200 },
"styleReviewer": { "status": "complete", "duration": 1800 }
}
},
"phase2": {
"status": "in_progress",
"skills": {
"docReviewer": { "status": "running", "started": 1705312000 }
}
}
}
}
Phase 3: Monitor
Health Checks
## Monitoring
### Skill Health
- Check heartbeat/progress every 5s
- Detect hung skills (no progress for 30s)
- Handle timeouts gracefully
### Resource Usage
- Track token consumption per skill
- Enforce budget limits
- Warn before exhausting budget
### Error Detection
- Catch skill failures immediately
- Distinguish retriable vs. fatal errors
- Log context for debugging
Intervention
interventions:
timeout:
action: retry_or_skip
maxRetries: 2
skipMessage: "Skill timed out, continuing without"
error:
action: retry_or_fail
maxRetries: 1
failureImpact: "partial_results"
hung:
detection: "no_progress_30s"
action: terminate_and_skip
Phase 4: Aggregate
Collection
Gather all skill outputs:
{
"securityReviewer": {
"success": true,
"issues": [
{
"severity": "high",
"type": "security",
"message": "SQL injection vulnerability",
"location": { "file": "handler.ts", "line": 45 }
}
],
"score": 0.7
},
"performanceReviewer": {
"success": true,
"issues": [
{
"severity": "medium",
"type": "performance",
"message": "N+1 query pattern detected",
"location": { "file": "handler.ts", "line": 30 }
}
],
"score": 0.8
},
"styleReviewer": {
"success": true,
"issues": [
{
"severity": "low",
"type": "style",
"message": "Inconsistent naming convention",
"location": { "file": "handler.ts", "line": 10 }
}
],
"score": 0.85
}
}
Normalization
Ensure consistent format:
## Normalization Steps
1. **Standardize Issue Format**
All issues use common structure:
- severity: critical/high/medium/low
- type: security/performance/style/etc.
- message: Human-readable description
- location: { file, line, column? }
2. **Deduplicate**
Remove duplicate issues identified by multiple reviewers
3. **Priority Sort**
Order by severity, then by file order
4. **Limit Results**
Respect maxIssues configuration
Synthesis
Create unified output:
## Synthesis Process
1. **Merge Issues**
Combine all issues into single list
Deduplicate similar issues
Tag with originating reviewer
2. **Calculate Scores**
- Overall: Weighted average of skill scores
- By category: Average per type
- By file: Issues per file
3. **Generate Summary**
- Total issues by severity
- Key concerns
- Recommendations
- Positive observations
4. **Create Report**
Structured output with all details
Output
{
"success": true,
"summary": {
"overallScore": 0.78,
"issueCount": {
"critical": 0,
"high": 1,
"medium": 1,
"low": 1
},
"topConcerns": [
"SQL injection vulnerability requires immediate attention",
"N+1 query pattern may cause performance issues at scale"
],
"strengths": [
"Generally consistent code style",
"Good error handling in most areas"
]
},
"issues": [
{
"id": "sec-001",
"severity": "high",
"type": "security",
"message": "SQL injection vulnerability",
"location": { "file": "handler.ts", "line": 45 },
"suggestion": "Use parameterized queries",
"source": "securityReviewer"
}
// ... more issues
],
"scores": {
"security": 0.7,
"performance": 0.8,
"style": 0.85,
"overall": 0.78
},
"metadata": {
"skillsRun": ["securityReviewer", "performanceReviewer", "styleReviewer"],
"skillsFailed": [],
"totalDuration": 7500,
"tokensUsed": 15000
}
}
Error Handling
Partial Success
When some skills fail:
{
"success": true,
"partial": true,
"warnings": [
"Documentation review failed, results incomplete"
],
"summary": {
// ... based on successful skills
},
"failedSkills": [
{
"skill": "docReviewer",
"error": "Timeout after 45s",
"impact": "Documentation quality not assessed"
}
]
}
Complete Failure
When orchestration cannot complete:
{
"success": false,
"error": {
"type": "OrchestrationFailed",
"message": "Critical skills failed",
"details": {
"failed": ["securityReviewer", "performanceReviewer"],
"succeeded": ["styleReviewer"]
}
},
"partialResults": {
// ... whatever completed
}
}
## Advanced Orchestration Techniques
### Dynamic Skill Selection
Choose skills based on context:
```markdown
## Dynamic Selection
### Context Analysis
Analyze input to determine needed skills:
```typescript
function analyzeContext(input: Input): SkillSet {
const skills = new Set<Skill>();
// Always include basics
skills.add('styleReviewer');
// Language-specific
if (input.language === 'typescript') {
skills.add('typeChecker');
}
// Content-based
if (containsDatabase(input.code)) {
skills.add('sqlReviewer');
}
if (containsAuth(input.code)) {
skills.add('authReviewer');
}
// Size-based
if (input.files.length > 20) {
skills.add('architectureReviewer');
}
return skills;
}
### Adaptive Parallelism
Adjust parallelism based on resources:
```markdown
## Adaptive Parallelism
### Resource Monitoring
```typescript
interface ResourceState {
tokensRemaining: number;
timeRemaining: number;
activeSkills: number;
}
Parallelism Strategy
function getParallelism(state: ResourceState): number {
// Low resources: conservative
if (state.tokensRemaining < 10000) {
return 1; // Sequential
}
// Time pressure: maximize parallel
if (state.timeRemaining < 30000) {
return Math.min(state.activeSkills, 5);
}
// Normal: balanced
return 3;
}
### Skill Chaining Within Orchestration
Some sub-skills might form mini-chains:
```markdown
## Internal Chains
### Chained Skills
```yaml
chains:
deepSecurityReview:
skills:
- staticAnalyzer
- patternMatcher
- vulnerabilityScanner
aggregate: union-of-findings
comprehensiveDocReview:
skills:
- apiDocChecker
- readmeValidator
- exampleTester
aggregate: merge-reports
Orchestration Integration
Treat chains as single skills:
- Same interface as simple skills
- Internal orchestration hidden
- Aggregated result returned
### Priority-Based Execution
Execute high-priority skills first:
```markdown
## Priority Execution
### Priority Levels
```yaml
priorities:
critical:
skills: [securityReviewer]
mustComplete: true
timeout: 60s
high:
skills: [performanceReviewer]
mustComplete: true
timeout: 45s
normal:
skills: [styleReviewer, docReviewer]
mustComplete: false
timeout: 30s
low:
skills: [metricCollector]
mustComplete: false
timeout: 15s
Execution Order
- Start all critical skills
- If time permits, add high priority
- Fill remaining capacity with normal
- Low priority only if resources abundant
Early Termination
If critical skill finds blocking issue:
- Option: Stop lower priority skills
- Return early with critical findings
- Note: Other reviews skipped
## Testing Orchestrator Skills
Orchestrators need comprehensive testing.
### Unit Testing
Test orchestrator logic in isolation:
```markdown
## Unit Tests
### Planning Tests
- Correct skills selected for options
- Dependencies resolved correctly
- Execution order valid
### Dispatch Tests
- Skills invoked with correct input
- Timeout handling works
- Retry logic functions
### Aggregation Tests
- Results merged correctly
- Conflicts resolved properly
- Output format valid
Integration Testing
Test with real sub-skills:
## Integration Tests
### Happy Path
All skills succeed, results aggregated correctly
### Partial Failure
Some skills fail, partial results returned
### Complete Failure
Critical skills fail, appropriate error returned
### Timeout Handling
Skills timeout, orchestrator handles gracefully
### Large Input
Many files/skills, performance acceptable
Mock Testing
Test without real sub-skills:
## Mock Tests
### Mock Sub-Skills
```typescript
const mockSecurityReviewer = {
invoke: async (input) => ({
success: true,
issues: [mockIssue],
score: 0.8
})
};
Scenario Testing
- Fast success: All mocks return immediately
- Slow skill: One mock delays
- Failing skill: One mock throws
- Mixed: Combination of behaviors
## Conclusion
The orchestrator pattern transforms complex, multi-faceted tasks into manageable coordinated workflows. By delegating to specialized sub-skills and managing their execution, orchestrators achieve results that no single skill could produce alone.
Key principles for effective orchestrator skills:
1. **Clear delegation**: Orchestrators coordinate, sub-skills execute
2. **Smart planning**: Analyze dependencies, maximize parallelism
3. **Robust monitoring**: Track progress, handle failures gracefully
4. **Thoughtful aggregation**: Combine results meaningfully
5. **Partial success**: Return value even when some skills fail
Start with simple orchestrators coordinating two or three skills. As you gain experience, add dynamic skill selection, adaptive execution, and sophisticated aggregation. The goal is seamless coordination that feels like a single, powerful skill.
The orchestrator pattern is your tool for building complex AI systems from focused, specialized components.