# Orchestration Patterns Reference ``` ┌─────────────────────────────────────────────────────────────┐ │ │ │ Patterns are your playbook. │ │ Master them, and you'll instinctively know how to │ │ decompose any task into elegant parallel execution. │ │ │ └─────────────────────────────────────────────────────────────┘ ``` ## Core Principles **All patterns build on Task Graph.** Every non-trivial task starts with `TaskCreate` to decompose work, then uses agents to execute. The patterns below describe how agents are orchestrated within that structure. **All agents run in background.** Always use `run_in_background=True`. This enables true async orchestration with automatic notifications when agents complete. ``` ┌────────────────────────────────────────────┐ │ Remember: │ │ • Users never see pattern names │ │ • Agents ALWAYS run in background │ │ • Notifications arrive when complete │ └────────────────────────────────────────────┘ ``` ## Table of Contents 1. [Task Graph Pattern (Default)](#task-graph-pattern) 2. [Fan-Out Pattern](#fan-out-pattern) 3. [Pipeline Pattern](#pipeline-pattern) 4. [Map-Reduce Pattern](#map-reduce-pattern) 5. [Speculative Pattern](#speculative-pattern) 6. [Background Pattern](#background-pattern) 7. [Parallelization Rules](#parallelization-rules) 8. [Pattern Combinations](#pattern-combinations) 9. [Error Recovery](#error-recovery) 10. [Result Synthesis](#result-synthesis) --- ## Task Graph Pattern **The foundation for all orchestration.** Complex dependencies managed through TaskCreate/TaskUpdate. ``` Task A ──► Task B ──► Task D │ │ └──► Task C ┘ ``` **When to use:** Always. Every multi-step task should be decomposed into TaskCreate. **Implementation:** ```python # 1. Create all tasks TaskCreate(subject="Setup database schema", description="...") TaskCreate(subject="Implement user model", description="...") TaskCreate(subject="Build API endpoints", description="...") # 2. Set dependencies TaskUpdate(taskId="2", addBlockedBy=["1"]) TaskUpdate(taskId="3", addBlockedBy=["2"]) # 3. Find unblocked tasks and spawn agents TaskList() # Find tasks with empty blockedBy Task(subagent_type="general-purpose", prompt="TaskId 1: Setup database...", model="sonnet", run_in_background=True) # 4. Agents mark complete, repeat TaskUpdate(taskId="1", status="resolved") TaskList() # Task 2 now unblocked ``` --- ## Fan-Out Pattern Launch multiple independent agents in parallel. Use when subtasks have no dependencies. ``` Orchestrator ├──► Agent A (subtask 1) ├──► Agent B (subtask 2) ← All launch simultaneously └──► Agent C (subtask 3) ``` **When to use:** Independent file analysis, parallel searches, multi-component implementation **Implementation:** ```python # Single message with multiple background agents (haiku for fast exploration) Task(subagent_type="Explore", prompt="Analyze auth module...", model="haiku", run_in_background=True) Task(subagent_type="Explore", prompt="Analyze database layer...", model="haiku", run_in_background=True) Task(subagent_type="Explore", prompt="Analyze API routes...", model="haiku", run_in_background=True) ``` **Critical:** All Task calls MUST be in ONE message AND use `run_in_background=True`. --- ## Pipeline Pattern Sequential agents where each output feeds the next. Use when steps have data dependencies. ``` Agent A → output → Agent B → output → Agent C → final result ``` **When to use:** Research→Plan→Implement, Analyze→Design→Build, Parse→Transform→Validate **Implementation:** ```python # Step 1: Research (haiku - fast exploration) Task(subagent_type="Explore", prompt="Find all API endpoints...", model="haiku", run_in_background=True) # → Notification arrives with result1 # Step 2: Plan (opus - needs critical thinking for design) Task(subagent_type="Plan", prompt=f"Given endpoints: {result1}, design...", model="opus", run_in_background=True) # → Notification arrives with result2 # Step 3: Implement (sonnet - well-structured from plan) Task(subagent_type="general-purpose", prompt=f"Implement this plan: {result2}", model="sonnet", run_in_background=True) ``` --- ## Map-Reduce Pattern Distribute work across agents, aggregate results. Use when processing collections. ``` ┌──► Agent A ──┐ Input ──►├──► Agent B ──┼──► Aggregator → Final Result └──► Agent C ──┘ ``` **When to use:** Analyzing multiple files, reviewing multiple PRs, processing data batches **Implementation:** ```python # MAP: Launch parallel agents (opus for security - needs critical thinking) Task(subagent_type="general-purpose", prompt="Analyze file1.ts for security issues", model="opus", run_in_background=True) Task(subagent_type="general-purpose", prompt="Analyze file2.ts for security issues", model="opus", run_in_background=True) Task(subagent_type="general-purpose", prompt="Analyze file3.ts for security issues", model="opus", run_in_background=True) # REDUCE: Collect and synthesize results = [TaskOutput(task_id=id) for id in task_ids] # Synthesize findings into unified report ``` --- ## Speculative Pattern Try multiple approaches simultaneously, use best result. Use when optimal approach is unclear. ``` ┌──► Approach A ──┐ Problem ─├──► Approach B ──┼──► Evaluate → Best Solution └──► Approach C ──┘ ``` **When to use:** Uncertain algorithms, multiple valid architectures, performance optimization **Implementation:** ```python # Launch competing approaches (sonnet for implementation) Task(subagent_type="general-purpose", prompt="Implement using recursive approach...", model="sonnet", run_in_background=True) Task(subagent_type="general-purpose", prompt="Implement using iterative approach...", model="sonnet", run_in_background=True) Task(subagent_type="general-purpose", prompt="Implement using memoization...", model="sonnet", run_in_background=True) # Notifications arrive → Evaluate and select best ``` --- ## Background Pattern Long-running agents while continuing foreground work. **When to use:** Test suites, builds, large analysis, external API calls **Implementation:** ```python # Launch background work (sonnet for test execution) Task(subagent_type="general-purpose", prompt="Run full test suite...", model="sonnet", run_in_background=True) # Continue foreground work # ... do other tasks ... # Check later TaskOutput(task_id="...", block=False) # Non-blocking check TaskOutput(task_id="...", block=True) # Block until complete ``` --- ## Parallelization Rules ### MUST Parallelize - Independent file reads - Independent searches (Glob, Grep) - Independent agent tasks - Independent API calls ### MUST NOT Parallelize - Tasks with data dependencies - Sequential workflow steps - Operations on same resource ### Syntax ```python # CORRECT: Single message, multiple tool calls Task(...task1...) Task(...task2...) Task(...task3...) # WRONG: Separate messages (sequential execution) Task(...task1...) Task(...task2...) ``` --- ## Pattern Combinations Complex tasks often combine multiple patterns: ### Pipeline + Fan-Out ``` Phase 1: PIPELINE (Research → Plan) ├─ Explore agent: Find existing patterns └─ Plan agent: Design architecture Phase 2: FAN-OUT (Parallel Implementation) ├─ Agent A: Implement component 1 ├─ Agent B: Implement component 2 └─ Agent C: Implement component 3 Phase 3: PIPELINE (Integration) └─ General-purpose agent: Wire components, test ``` ### Map-Reduce + Background ``` # Launch map phase in background Task(...file1..., run_in_background=True) Task(...file2..., run_in_background=True) # Do other work while waiting # Collect and reduce results = [TaskOutput(id) for id in task_ids] # Synthesize ``` ### Speculative + Pipeline ```python # Try multiple approaches (sonnet for implementation) Task(subagent_type="general-purpose", prompt="Approach A...", model="sonnet", run_in_background=True) Task(subagent_type="general-purpose", prompt="Approach B...", model="sonnet", run_in_background=True) # Notifications arrive → Evaluate and continue with winner winner = evaluate(approach_a, approach_b) Task(subagent_type="general-purpose", prompt=f"Refine and complete: {winner}", model="sonnet", run_in_background=True) ``` --- ## Error Recovery ### Failure Types | Failure | Cause | Recovery | | -------------- | --------------------------------- | -------------------------------------------- | | Timeout | Agent took too long | Retry with smaller scope or simpler model | | Incomplete | Agent returned partial work | Create follow-up task for remainder | | Wrong approach | Agent misunderstood | Retry with clearer prompt | | Blocked | Missing dependency | Check if blocker task failed | | Conflict | Multiple agents touched same file | Resolve manually or re-run with coordination | ### Retry Strategy ```python # Agent notification arrived with error or incomplete result # (Original was: Task(..., run_in_background=True)) if result.failed or result.incomplete: # Log the failure TaskUpdate(taskId="3", addComment={ "author": "orchestrator", "content": f"Attempt 1 failed: {result.error}. Retrying with adjusted approach." }) # Retry with more context (still background, same model as original) Task(subagent_type="general-purpose", prompt=f"""Previous attempt failed: {result.error} Try alternative approach: - [specific guidance based on failure] Original task: [task description]""", model="sonnet", run_in_background=True) ``` ### Escalation Rules 1. **After 2 failed retries** → Ask user for guidance 2. **If dependency failed** → Mark dependent tasks as blocked, surface to user 3. **If conflict detected** → Pause parallel work, resolve, then continue ### Partial Success Handling ```python # Agent completed some but not all work TaskUpdate(taskId="3", status="resolved", addComment={"author": "orchestrator", "content": "Partial: Completed X and Y, but Z needs separate handling"}) # Create new task for remaining work TaskCreate(subject="Complete remaining Z work", description="Agent completed X and Y but Z still needs...") ``` --- ## Result Synthesis After parallel agents complete, synthesize their outputs into coherent results. ### Synthesis Patterns | Pattern | How to Synthesize | | ------------------------ | ------------------------------------------------------------------------ | | Multi-dimensional review | Merge by severity, dedupe findings, format as unified review | | Parallel exploration | Combine file lists, identify overlaps, structure by area | | Parallel implementation | Check for conflicts, verify integration points, summarize what was built | | Competing approaches | Compare results, select winner, explain rationale | ### Collection ```python # Wait for all background agents result1 = TaskOutput(task_id="agent-1") result2 = TaskOutput(task_id="agent-2") result3 = TaskOutput(task_id="agent-3") ``` ### Aggregation Approaches **Simple aggregation (orchestrator does it):** ```python # Combine exploration results all_files = set() for result in [result1, result2, result3]: all_files.update(result.files_found) # Present unified list "Found these relevant files: {all_files}" ``` **Complex synthesis (spawn synthesis agent - opus for judgment):** ``` Task(subagent_type="general-purpose", prompt=f"""Synthesize these parallel review findings into a unified report: Security review findings: {result1} Performance review findings: {result2} Code quality findings: {result3} Create a single PR review with: - Summary - Risk assessment (security/performance/breaking) - Must-fix items (blocking) - Should-fix items (non-blocking) - Positive notes Prioritize by severity. Remove duplicates. Do not mention that multiple reviews were conducted.""", model="opus", run_in_background=True) ``` ### Conflict Resolution When parallel agents produce conflicting outputs: ```python # Detect conflict (e.g., both modified same file) if has_conflict(result1, result2): # Option 1: Present both to user "Two approaches were attempted. Which do you prefer? Approach A: {result1.summary} Approach B: {result2.summary}" # Option 2: Spawn resolution agent (opus for judgment) Task(subagent_type="general-purpose", prompt=f"""Two agents produced conflicting changes: Agent 1: {result1} Agent 2: {result2} Merge these changes, resolving conflicts by [priority rule]. Ensure the final result is consistent.""", model="opus", run_in_background=True) ``` ### Communication When presenting synthesized results to users: - **Lead with conclusion** - Summary first, details after - **Group by theme** - Not by agent or source - **Hide the machinery** - Don't mention "3 agents analyzed this" - **Present as unified analysis** - "Here's what I found" not "Agent 1 found X, Agent 2 found Y" --- ``` ─── ◈ Patterns Reference Complete ─────── ```