Skip to main content
The Supervisor pattern lets you build multi-agent systems where a parent agent automatically routes requests to specialized child agents. Instead of one agent handling everything, you decompose complex domains into focused specialists — each with its own tools, knowledge base, and instructions.

How It Works

When you add the agents field to an Agent config, the parent becomes a supervisor. It uses an LLM call to analyze the user’s message against each child agent’s instructions and selects the best match.
User message arrives
       |
   Supervisor (LLM analyzes intent)
       |
   Which agent fits best?
  /       |        \
Agent A  Agent B  Agent C
(tools)  (RAG)   (tools+RAG)
       |
  Response returned
The routing happens in a single LLM call — the supervisor reads each agent’s name and instructions, compares them to the input, and picks one. If the LLM returns an invalid agent name, Runflow falls back to the first agent in the list.

Basic Setup

import { Agent, openai } from '@runflow-ai/sdk';

const agent = new Agent({
  name: 'Customer Service',
  instructions: `Route requests to the right specialist:
    - Sales: pricing, plans, purchases, demos
    - Support: technical issues, bugs, how-to questions
    - Billing: invoices, payments, refunds`,
  model: openai('gpt-4o-mini'), // Cheap model for routing
  agents: {
    sales: {
      name: 'Sales Agent',
      instructions: 'Handle sales inquiries. Be consultative, not pushy.',
      model: openai('gpt-4o'),
    },
    support: {
      name: 'Support Agent',
      instructions: 'Solve technical problems step by step.',
      model: openai('gpt-4o'),
    },
    billing: {
      name: 'Billing Agent',
      instructions: 'Handle invoices, payments, and refund requests.',
      model: openai('gpt-4o'),
    },
  },
});

const result = await agent.process({
  message: 'I need a refund for my last invoice',
  sessionId: 'session_abc',
});
// Supervisor routes to billing agent automatically

Specialist Agents with Tools and RAG

Each child agent can have its own tools, RAG configuration, memory, and model — completely independent from other agents:
import { Agent, openai, anthropic, createTool } from '@runflow-ai/sdk';
import { z } from 'zod';

const searchOrders = createTool({
  id: 'search-orders',
  description: 'Search orders by ID or email',
  inputSchema: z.object({
    orderId: z.string().optional(),
    email: z.string().email().optional(),
  }),
  execute: async ({ context }) => {
    const res = await fetch(`https://api.example.com/orders?id=${context.orderId || ''}`);
    return res.json();
  },
});

const checkInvoice = createTool({
  id: 'check-invoice',
  description: 'Look up invoice details',
  inputSchema: z.object({
    invoiceId: z.string(),
  }),
  execute: async ({ context }) => {
    const res = await fetch(`https://api.example.com/invoices/${context.invoiceId}`);
    return res.json();
  },
});

const supervisor = new Agent({
  name: 'Router',
  instructions: 'Analyze intent and route to the correct specialist.',
  model: openai('gpt-4o-mini'),

  agents: {
    support: {
      name: 'Technical Support',
      instructions: 'Resolve technical issues. Search the knowledge base first.',
      model: openai('gpt-4o'),
      tools: { searchOrders },
      rag: {
        vectorStore: 'support-docs',
        k: 5,
        threshold: 0.7,
      },
    },
    billing: {
      name: 'Billing Specialist',
      instructions: 'Handle billing inquiries. Always verify account first.',
      model: anthropic('claude-sonnet-4-20250514'),
      tools: { checkInvoice },
    },
    sales: {
      name: 'Sales Consultant',
      instructions: 'Help with plans, pricing, and demos. Be consultative.',
      model: openai('gpt-4o'),
    },
  },

  // Memory shared across the supervisor session
  memory: {
    maxTurns: 30,
    summarizeAfter: 20,
  },

  // Full observability for all routing + agent execution
  observability: 'full',
});

Cost Optimization: Cheap Router, Quality Specialists

The supervisor only classifies intent — it doesn’t generate user-facing responses. Use a fast, cheap model for routing and reserve powerful models for the specialists that do the real work:
const agent = new Agent({
  name: 'Supervisor',
  instructions: 'Route to the appropriate department.',
  model: openai('gpt-4o-mini'),      // ~$0.15/1M tokens - routing only
  agents: {
    analyst: {
      name: 'Data Analyst',
      instructions: 'Analyze data, generate reports, create visualizations.',
      model: anthropic('claude-sonnet-4-20250514'), // Quality for analysis
    },
    writer: {
      name: 'Content Writer',
      instructions: 'Write marketing copy, blog posts, email campaigns.',
      model: openai('gpt-4o'),          // Quality for writing
    },
    coder: {
      name: 'Code Assistant',
      instructions: 'Help with code generation, debugging, code review.',
      model: anthropic('claude-sonnet-4-20250514'), // Quality for code
    },
  },
});
This pattern can reduce costs by 50-80% compared to using a single powerful model for everything. The supervisor call is fast and cheap — the expensive model only runs for the task that actually needs it.

Routing Logic in Detail

The supervisor builds a prompt like this internally:
Available agents:
- support: Resolve technical issues. Search the knowledge base first.
- billing: Handle billing inquiries. Always verify account first.
- sales: Help with plans, pricing, and demos. Be consultative.

User input: "I need a refund for my last invoice"

Which agent should handle this? Respond with just the agent name.
The supervisor’s own instructions are used as the system prompt, so you can add domain-specific routing rules:
const supervisor = new Agent({
  name: 'Healthcare Router',
  instructions: `Route patient requests to specialists.

## Routing Rules
- **triage**: symptoms, emergencies, "I feel sick"
- **appointments**: scheduling, rescheduling, cancellations
- **records**: medical history, test results, prescriptions
- **billing**: insurance claims, copays, payment plans

## Special Rules
- If the patient mentions chest pain or breathing issues, ALWAYS route to triage
- Prescription refills go to records, not appointments
- Insurance questions go to billing, even if mentioned alongside appointments`,

  model: openai('gpt-4o-mini'),
  agents: {
    triage: { /* ... */ },
    appointments: { /* ... */ },
    records: { /* ... */ },
    billing: { /* ... */ },
  },
});

Shared Memory and Context

Memory is configured on the supervisor and shared across the entire session. If a customer starts with support and then asks about billing, the billing agent has full context of what was discussed:
const supervisor = new Agent({
  name: 'Support Hub',
  instructions: 'Route to the right team.',
  model: openai('gpt-4o-mini'),
  agents: { /* specialists */ },
  memory: {
    maxTurns: 30,
    summarizeAfter: 20,
    summarizePrompt: 'Summarize: customer intent, which specialist handled it, actions taken, and pending issues.',
    summarizeModel: openai('gpt-4o-mini'),
  },
});

// Conversation 1: Support handles the issue
await supervisor.process({ message: 'My API integration is failing', sessionId: 'user_123' });

// Conversation 2: Same session, billing agent sees prior context
await supervisor.process({ message: 'Can you check my invoice too?', sessionId: 'user_123' });

Observability

The supervisor generates traces automatically. With observability: 'full', you get:
  • Supervisor span: which agents were available, which was selected
  • LLM call span: the routing decision (model, tokens, latency)
  • Child agent span: the full execution trace of the selected agent
  • Tool call spans: every tool the child agent invoked
const supervisor = new Agent({
  name: 'Traced Router',
  instructions: 'Route requests.',
  model: openai('gpt-4o-mini'),
  agents: { /* ... */ },
  observability: 'full', // or 'standard' or 'minimal'
});
See Observability for details on trace levels and custom event tracking.

Fallback Behavior

If the LLM returns an agent name that doesn’t match any key in the agents config, Runflow automatically falls back to the first agent in the list. Design your agent order accordingly — put the most general-purpose agent first:
agents: {
  general: { /* catch-all agent - first in list */ },
  sales: { /* specific domain */ },
  billing: { /* specific domain */ },
},

When to Use Multi-Agent vs Single Agent

ScenarioRecommendation
Single-purpose bot (FAQ, scheduling, order status)Single agent
Multiple domains with different toolsMulti-agent
Domains that need different models (code vs writing)Multi-agent
Different response styles per departmentMulti-agent
Simple Q&A with a knowledge baseSingle agent with RAG
Complex routing with domain-specific rulesMulti-agent

Supervisor vs Workflow

The SDK offers two patterns for multi-agent orchestration:
FeatureSupervisor (agents config)Workflow (flow())
RoutingLLM-based, automaticCode-based, explicit
Setup complexityMinimal (just add agents)More code (steps, switches)
Control over routingInstructions-basedFull programmatic control
Multi-step pipelinesNo (single routing hop)Yes (chain steps, parallel, branch)
Conditional logicLLM decidesExplicit conditions
Best forRequest routing, customer serviceData pipelines, approval flows
Use the supervisor when you need simple, intent-based routing. Use Workflows when you need multi-step pipelines with explicit branching, parallel execution, or data transformations.

Configuration Reference

Supervisor Agent

PropertyTypeDescription
namestringSupervisor identifier
instructionsstring | PromptRefRouting rules and behavior — used as the system prompt for routing decisions
modelModelProviderLLM for routing (use a cheap, fast model)
agentsRecord<string, AgentConfig>Child agents keyed by name
memoryMemoryConfigShared memory across the session
observability'full' | 'standard' | 'minimal' | ObservabilityConfigTrace level
debugboolean | DebugConfigEnable debug logging

Child Agent (within agents)

Each child agent supports the full AgentConfig:
PropertyTypeDescription
namestringAgent display name
instructionsstring | PromptRefSpecialist behavior and domain expertise
modelModelProviderLLM for this agent (can differ from supervisor)
modelConfigModelConfigTemperature, maxTokens, topP, etc.
toolsRecord<string, RunflowTool>Agent-specific tools
ragRAGConfigKnowledge base search
memoryMemoryConfigAgent-specific memory (optional, usually shared from supervisor)
mediaMediaConfigImage/audio processing
streamingStreamingConfigStreaming responses
maxToolIterationsnumberMax tool call loops
debugboolean | DebugConfigAgent-specific debug

Next Steps

Multi-Agent Example

Complete real-world example with supervisor + 3 specialists

Tools

Create tools for your specialist agents

Knowledge (RAG)

Add knowledge bases to specialists

Workflows

Multi-step pipelines with explicit routing