Skip to main content
The Orchestrator enables multi-agent systems where a planner agent coordinates specialized sub-agents to solve complex tasks. This is ideal for workflows that require different expertise areas.

Overview

The Orchestrator pattern uses:
  • Planner Agent: Meta-agent that coordinates the workflow
  • Sub-Agents: Specialized agents for specific tasks (research, coding, review, etc.)
  • Tool Exposure: Sub-agents are automatically exposed as tools to the planner
import { createAgent } from '@agentlib/core'
import { openai } from '@agentlib/openai'
import { Orchestrator } from '@agentlib/orchestrator'
import '@agentlib/reasoning'

const provider = openai({
  apiKey: process.env.OPENAI_API_KEY,
  model: 'gpt-4o',
})

// Define specialized sub-agents
const researcher = createAgent({
  name: 'researcher',
  description: 'Finds detailed information about specific topics.',
  systemPrompt: 'You are a researcher. Provide concise summaries of facts.',
}).provider(provider).reasoning('react')

const coder = createAgent({
  name: 'coder',
  description: 'Writes efficient code based on requirements.',
  systemPrompt: 'You are an expert coder. Wrap code in markdown blocks.',
}).provider(provider).reasoning('react')

// Define planner
const planner = createAgent({
  name: 'planner',
  description: 'Main coordinator that uses sub-agents.',
  systemPrompt: 'You are a project manager. Use available agents to solve tasks.',
}).provider(provider).reasoning('react')

// Initialize orchestrator
const orchestrator = new Orchestrator(planner, {
  agents: { researcher, coder },
  maxSteps: 10,
  exposeAgentsAsTools: true,
})

await orchestrator.run('Research JavaScript frameworks and write comparison code')

Creating an Orchestrator

1

Define Sub-Agents

Create specialized agents for different tasks:
import { createAgent } from '@agentlib/core'
import { openai } from '@agentlib/openai'
import '@agentlib/reasoning'

const provider = openai({
  apiKey: process.env.OPENAI_API_KEY,
  model: 'gpt-4o',
})

const researcher = createAgent({
  name: 'researcher',
  description: 'Finds detailed information about specific topics.',
  systemPrompt: 'You are a researcher. Provide concise summaries.',
}).provider(provider).reasoning('react')

const coder = createAgent({
  name: 'coder',
  description: 'Writes efficient code based on requirements.',
  systemPrompt: 'You are an expert coder.',
}).provider(provider).reasoning('react')

const critic = createAgent({
  name: 'critic',
  description: 'Reviews work and provides a score from 0 to 1.',
  systemPrompt: 'You are a critical reviewer. Always end with "Score: X.X"',
}).provider(provider).reasoning('react')
Give each sub-agent a clear name and description. The planner uses these to decide which agent to invoke.
2

Define the Planner Agent

Create a meta-agent that coordinates the sub-agents:
const planner = createAgent({
  name: 'planner',
  description: 'Main coordinator that uses sub-agents to solve complex tasks.',
  systemPrompt: 'You are a project manager. Use the available agents to research, code, and review.',
}).provider(provider).reasoning('react')
3

Initialize the Orchestrator

import { Orchestrator } from '@agentlib/orchestrator'

const orchestrator = new Orchestrator(planner, {
  agents: {
    researcher,
    coder,
    critic,
  },
  maxSteps: 10,
  summarize: true,
  exposeAgentsAsTools: true,
})
4

Run the Orchestrator

const result = await orchestrator.run(
  'Design and implement a scalable image processing system.'
)

console.log('Final output:', result)

Configuration Options

new Orchestrator(planner, {
  agents: {                    // Sub-agents available to planner
    researcher,
    coder,
    critic,
  },
  maxSteps: 10,                // Max orchestration steps
  summarize: true,             // Summarize agent outputs for context
  exposeAgentsAsTools: true,   // Auto-register agents as tools
  context: {                   // Shared context for all agents
    company: 'ACME Corp',
    constraints: 'Budget: $10k',
  },
  onStep: (step) => {          // Callback for each step
    console.log(`Step: ${step.agent} - ${step.type}`)
    if (step.error) return 'abort'  // Abort on error
  },
})

Orchestrator Events

Monitor orchestration with events:
orchestrator.on('agent:invoke', ({ agent, prompt }) => {
  console.log(`\n🚀 Invoking agent: ${agent}`)
  console.log(`Prompt: ${prompt}`)
})

orchestrator.on('agent:completed', ({ agent, output }) => {
  console.log(`\n✅ Agent ${agent} finished!`)
  console.log(`Output: ${output.substring(0, 100)}...`)
})

orchestrator.on('step', ({ step, agent }) => {
  console.log(`[${agent}] ${step.type}`)
})

orchestrator.on('error', ({ agent, error }) => {
  console.error(`❌ Agent ${agent} failed:`, error)
})

Step Control with onStep

Control orchestration flow with the onStep callback:
const orchestrator = new Orchestrator(planner, {
  agents: { researcher, coder, critic },
  onStep: (step) => {
    console.log(`[Step] Agent: ${step.agent} | Type: ${step.type}`)
    
    // Abort if quality is too low
    if (step.agent === 'critic' && step.content?.includes('Score: 0.3')) {
      console.warn('Low quality detected! Aborting...')
      return 'abort'
    }
    
    // Continue normally
    return undefined
  },
})

Step Structure

interface OrchestrationStep {
  agent: string           // Agent name
  type: string            // Step type (e.g., 'thought', 'tool_call')
  content?: string        // Step content
  error?: string          // Error message if failed
}

Accessing Agent States

Inspect the state of all agents after orchestration:
const result = await orchestrator.run('Complex task')

const states = orchestrator.getAllStates()

for (const state of states) {
  console.log(`\nAgent: ${state.name}`)
  console.log(`Status: ${state.status}`)
  console.log(`Steps: ${state.steps.length}`)
  console.log(`Tokens: ${state.usage?.totalTokens}`)
}

Shared Context

Pass shared data to all agents:
const orchestrator = new Orchestrator(planner, {
  agents: { researcher, coder },
  context: {
    company: 'ACME Corp',
    budget: 10_000,
    deadline: '2025-06-01',
  },
})

// All agents can access this context during execution

Custom Tool Integration

Combine sub-agents with regular tools:
import { defineTool } from '@agentlib/core'

const searchTool = defineTool({
  schema: {
    name: 'search',
    description: 'Search the web',
    parameters: {
      type: 'object',
      properties: { query: { type: 'string' } },
      required: ['query'],
    },
  },
  async execute({ query }) {
    return { results: [`Result for: ${query}`] }
  },
})

// Add tools to planner
const planner = createAgent({
  name: 'planner',
  systemPrompt: 'You are a coordinator.',
})
  .provider(provider)
  .reasoning('react')
  .tool(searchTool)  // Regular tool

// Orchestrator will expose both tools and sub-agents
const orchestrator = new Orchestrator(planner, {
  agents: { researcher, coder },
  exposeAgentsAsTools: true,
})

Complete Example

import 'dotenv/config'
import '@agentlib/reasoning'
import { createAgent } from '@agentlib/core'
import { openai } from '@agentlib/openai'
import { Orchestrator } from '@agentlib/orchestrator'

const provider = openai({
  apiKey: process.env.OPENAI_API_KEY,
  model: 'gpt-4o',
})

// Define sub-agents
const researcher = createAgent({
  name: 'researcher',
  description: 'Finds detailed information about specific topics.',
  systemPrompt: 'You are a researcher. Provide concise summaries of facts.',
}).provider(provider).reasoning('react')

const coder = createAgent({
  name: 'coder',
  description: 'Writes efficient code based on requirements.',
  systemPrompt: 'You are an expert coder. Wrap your code in markdown blocks.',
}).provider(provider).reasoning('react')

const critic = createAgent({
  name: 'critic',
  description: 'Reviews work and provides a score from 0 to 1.',
  systemPrompt: 'You are a critical reviewer. Always end your message with "Score: X.X"',
}).provider(provider).reasoning('react')

// Define planner
const planner = createAgent({
  name: 'planner',
  description: 'Main coordinator that uses sub-agents to solve complex tasks.',
  systemPrompt: 'You are a project manager. Use the available agents to research, code, and review.',
}).provider(provider).reasoning('react')

// Initialize orchestrator
const orchestrator = new Orchestrator(planner, {
  agents: {
    researcher,
    coder,
    critic,
  },
  maxSteps: 10,
  summarize: true,
  exposeAgentsAsTools: true,
  context: {
    company: 'ACME Corp',
    constraints: 'You are running on ACME Corp infrastructure',
  },
  onStep: (step) => {
    console.log(`[Step] Agent: ${step.agent} | Type: ${step.type}`)
    
    if (step.agent === 'critic' && step.content?.includes('Score: 0.3')) {
      console.warn('Low quality work detected! Aborting...')
      return 'abort'
    }
  },
})

// Add event listeners
orchestrator.on('agent:invoke', ({ agent, prompt }) => {
  console.log(`\n🚀 Invoking agent: ${agent}`)
  console.log(`Prompt: ${prompt}`)
})

orchestrator.on('agent:completed', ({ agent, output }) => {
  console.log(`\n✅ Agent ${agent} finished!`)
  console.log(`Output: ${output.substring(0, 100)}...`)
})

// Run orchestration
console.log('--- Starting Orchestration ---')
await orchestrator.run('Design and implement a scalable image processing system.')
console.log('\n--- Orchestration Finished ---')

// Inspect final states
const states = orchestrator.getAllStates()
console.log('\nFinal States:')
for (const state of states) {
  console.log(`${state.name}: ${state.status} (${state.steps.length} steps)`)
}

Use Cases

Software Development Workflow

const requirements = createAgent({
  name: 'requirements',
  description: 'Analyzes requirements and creates specifications.',
}).provider(provider).reasoning('planner')

const architect = createAgent({
  name: 'architect',
  description: 'Designs system architecture.',
}).provider(provider).reasoning('planner')

const developer = createAgent({
  name: 'developer',
  description: 'Implements features based on specs.',
}).provider(provider).reasoning('react')

const tester = createAgent({
  name: 'tester',
  description: 'Creates and runs tests.',
}).provider(provider).reasoning('react')

const orchestrator = new Orchestrator(planner, {
  agents: { requirements, architect, developer, tester },
})

await orchestrator.run('Build a REST API for user management')

Research and Writing

const factChecker = createAgent({
  name: 'fact_checker',
  description: 'Verifies claims and finds sources.',
}).provider(provider).reasoning('react')

const writer = createAgent({
  name: 'writer',
  description: 'Writes engaging content.',
}).provider(provider).reasoning('cot')

const editor = createAgent({
  name: 'editor',
  description: 'Edits for clarity and correctness.',
}).provider(provider).reasoning('reflect')

const orchestrator = new Orchestrator(planner, {
  agents: { factChecker, writer, editor },
})

await orchestrator.run('Write an article about quantum computing advancements')

Customer Support Triage

const classifier = createAgent({
  name: 'classifier',
  description: 'Classifies support tickets by urgency and category.',
}).provider(provider).reasoning('cot')

const technicalSupport = createAgent({
  name: 'technical_support',
  description: 'Handles technical issues.',
}).provider(provider).reasoning('react')

const billingSupport = createAgent({
  name: 'billing_support',
  description: 'Handles billing questions.',
}).provider(provider).reasoning('react')

const orchestrator = new Orchestrator(planner, {
  agents: { classifier, technicalSupport, billingSupport },
})

await orchestrator.run('User cannot access their account after payment')

Next Steps

Build docs developers (and LLMs) love