Orchestrator Pattern: Coordinating Multiple Skills
Master the orchestrator pattern for AI skills that coordinate multiple sub-skills, managing parallel execution, dependencies, and result aggregation.
Master the orchestrator pattern for AI skills that coordinate multiple sub-skills, managing parallel execution, dependencies, and result aggregation.
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.
The orchestrator pattern follows a coordination flow:
Input → [Orchestrator]
│
┌─────────┼─────────┐
↓ ↓ ↓
[Skill A] [Skill B] [Skill C]
│ │ │
└─────────┼─────────┘
↓
[Aggregate]
↓
Output
The orchestrator:
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.
The orchestrator pattern excels when:
Avoid orchestrator when:
Effective orchestrators require careful planning of skill coordination.
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
Each skill must:
### 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"
Given dependencies, determine order:
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}
When sub-skills disagree:
## 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
}
}
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;
}
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:
phase1:
parallel: true
skills:
- securityReviewer
- performanceReviewer
- styleReviewer
phase2:
parallel: true
skills:
- docReviewer
waitFor: [styleReviewer]
phase3:
parallel: false
skills:
- testReviewer
waitFor: [securityReviewer, performanceReviewer]
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
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);
}
{
"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 }
}
}
}
}
## 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
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
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
}
}
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
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
{
"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
}
}
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"
}
]
}
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;
}
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
Treat chains as single skills:
### 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
If critical skill finds blocking issue:
## 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
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
Test without real sub-skills:
## Mock Tests
### Mock Sub-Skills
```typescript
const mockSecurityReviewer = {
invoke: async (input) => ({
success: true,
issues: [mockIssue],
score: 0.8
})
};
## 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.
Teaches Claude how to use the linear-CLI tool for issue tracking