Day 2 of 5
⏱ ~60 minutes
Multi-Agent Systems — Day 2

The Orchestrator Pattern: Planning and Delegating Tasks

The orchestrator pattern uses one agent to plan and delegate work to specialist agents. Day 2 builds a real orchestrator that breaks complex tasks into subtasks and manages their execution.

The Orchestrator's Job

An orchestrator receives a complex goal, breaks it into subtasks, assigns each to the right specialist agent, and synthesizes the results. It is the AI equivalent of a project manager.

orchestrator.js
import Anthropic from '@anthropic-ai/sdk';
import * as dotenv from 'dotenv';
dotenv.config();

const client = new Anthropic();

async function callAgent(systemPrompt, userMessage) {
  const response = await client.messages.create({
    model: 'claude-opus-4-5',
    max_tokens: 2048,
    system: systemPrompt,
    messages: [{ role: 'user', content: userMessage }]
  });
  return response.content[0].text;
}

const AGENTS = {
  planner: 'You break complex goals into 3-5 concrete subtasks. Output as JSON array: [{"task": "...", "agent": "researcher|writer|analyst"}]',
  researcher: 'You research topics thoroughly. Provide facts, examples, and relevant context.',
  writer: 'You write clear, engaging content. Use concrete examples. Avoid jargon.',
  analyst: 'You analyze information and extract insights, patterns, and recommendations.'
};

async function orchestrate(goal) {
  console.log('Orchestrator: Planning...');
  
  // Step 1: Plan
  const planJson = await callAgent(AGENTS.planner, 
    `Break this goal into subtasks: ${goal}`);
  
  let plan;
  try {
    plan = JSON.parse(planJson);
  } catch {
    // If not valid JSON, extract the array
    const match = planJson.match(/\[[\s\S]*\]/);
    plan = match ? JSON.parse(match[0]) : [{ task: goal, agent: 'writer' }];
  }
  
  console.log('Plan:', plan.map(p => p.task).join(', '));
  
  // Step 2: Execute each subtask
  const results = [];
  for (const subtask of plan) {
    console.log(`Executing: ${subtask.task} (${subtask.agent})`);
    const result = await callAgent(
      AGENTS[subtask.agent] || AGENTS.writer,
      subtask.task
    );
    results.push({ task: subtask.task, result });
  }
  
  // Step 3: Synthesize
  console.log('Synthesizing results...');
  const synthesis = await callAgent(
    'You synthesize multiple pieces of work into a coherent whole.',
    `Combine these results into a final deliverable:

${
      results.map(r => `## ${r.task}
${r.result}`).join('

')
    }`
  );
  
  return synthesis;
}

const output = await orchestrate(
  'Create a comprehensive guide to starting a small online business'
);
console.log(output);
Day 2 Exercise
Build and Test the Orchestrator
  1. Run orchestrator.js with the example goal.
  2. Log the plan before executing it — read the subtasks the planner created.
  3. Try a goal in a domain you know well. Does the planner break it down sensibly?
  4. Add a new agent type (e.g., "critic" or "summarizer") to the AGENTS object and use it in a subtask.

Day 2 Summary

  • The orchestrator breaks goals into subtasks, assigns them to specialists, and synthesizes results.
  • The planner agent outputs a JSON plan — always validate/handle malformed JSON gracefully.
  • Sequential execution is simplest; add parallel execution once the pattern is working.
Finished this lesson?