Table of Contents

How Do Multiple AI Agents Work Together on a Single Task?


TL;DR

LM-Kit.NET provides four orchestration patterns: Pipeline (sequential, each agent feeds the next), Parallel (all agents process the same input simultaneously), Supervisor (a coordinator delegates to workers dynamically), and Router (routes input to the best single agent). Each pattern has a dedicated orchestrator class. Agents can also delegate directly to each other using the DelegateTool. Orchestrators can be nested for complex workflows.


The Four Orchestration Patterns

Pipeline (Sequential)

Each agent receives the previous agent's output as input. Data flows through the pipeline like an assembly line:

Input → [Agent A] → [Agent B] → [Agent C] → Output
using LMKit.Agents.Orchestration;

var pipeline = new PipelineOrchestrator()
    .AddStage(extractorAgent)       // Step 1: Extract key information
    .AddStage(summarizerAgent)      // Step 2: Summarize the extracted data
    .AddStage(translatorAgent);     // Step 3: Translate to target language

var result = await pipeline.ExecuteAsync("Process this quarterly report...");

Best for: Multi-step transformations (extract → summarize → translate), content creation pipelines (outline → write → edit → fact-check), data processing workflows with clear sequential dependencies.

Parallel (Fan-Out / Fan-In)

All agents receive the same input and execute concurrently. Results are aggregated:

           ┌─ [Agent A] ─┐
Input ─────┤  [Agent B]  ├───── Aggregated Output
           └─ [Agent C] ─┘
var parallel = new ParallelOrchestrator()
    .AddAgent(technicalReviewer)
    .AddAgent(securityReviewer)
    .AddAgent(performanceReviewer)
    .WithAggregator((results, ctx) =>
        string.Join("\n\n---\n\n", results.Select(r =>
            $"**{r.AgentName}:**\n{r.Content}")));

var result = await parallel.ExecuteAsync("Review this code for production readiness...");

Best for: Multi-perspective analysis (technical + legal + business review), ensemble approaches for improved accuracy, gathering independent opinions, any task where parallel processing saves time.

Supervisor (Adaptive Delegation)

A supervisor agent dynamically decides which worker agents to involve and in what order:

              ┌─ [Worker A]
[Supervisor] ─┤  [Worker B]    (supervisor decides dynamically)
              └─ [Worker C]
var supervisor = new SupervisorOrchestrator(coordinatorAgent)
    .AddWorker(researchAgent)
    .AddWorker(codeWriterAgent)
    .AddWorker(reviewerAgent);

var result = await supervisor.ExecuteAsync(
    "Build a REST API endpoint for user registration with input validation");

How it works:

  1. The supervisor receives the task and the list of available workers.
  2. The supervisor decides which worker(s) to delegate to using a DelegateTool.
  3. Worker results return to the supervisor.
  4. The supervisor delegates again, synthesizes, or produces a final answer.

Best for: Complex tasks where the execution path is not known in advance, collaborative problem-solving, intelligent task routing based on content analysis.

Router (Intent-Based)

Routes each input to the single most appropriate agent:

           ┌─ "code" → [Code Agent]
Input ─────┤  "data" → [Data Agent]
           └─ "general" → [General Agent]
var router = new RouterOrchestrator()
    .AddRoute("code", codeAgent)
    .AddRoute("data", dataAgent)
    .AddRoute("general", generalAgent)
    .WithDefaultRoute("general");

// Option A: Function-based routing
router.WithRoutingFunction((input, agents) =>
{
    if (input.Contains("code") || input.Contains("function")) return "code";
    if (input.Contains("data") || input.Contains("chart")) return "data";
    return "general";
});

// Option B: Agent-based routing (model decides)
router.WithRouterAgent(classifierAgent);

var result = await router.ExecuteAsync("Write a sorting algorithm in C#");

Best for: Intent-based routing to specialized agents, load distribution, skill-based task assignment, chatbot front-ends with domain-specific backends.


Decision Guide

Scenario Pattern
Step-by-step transformation Pipeline
Multiple perspectives on same input Parallel
Complex task, unknown execution path Supervisor
Route to the right specialist Router
Combination of the above Nested orchestrators

Direct Agent Delegation

Agents can delegate to each other without an orchestrator, using DelegateTool:

var coordinator = Agent.CreateBuilder(model)
    .WithPersona("Project Coordinator")
    .WithDelegates(delegates =>
    {
        delegates.Register("researcher", researchAgent);
        delegates.Register("coder", codeAgent);
    })
    .WithDelegationEnabled()   // Registers DelegateTool automatically
    .Build();

// The coordinator can now call: delegate_to_agent({ "agent": "researcher", "task": "..." })
var result = await coordinator.RunAsync("Research best practices for API rate limiting, then write a C# implementation");

Nesting Orchestrators

Orchestrators can be composed for complex workflows:

// Inner: parallel review from multiple perspectives
var reviewOrchestrator = new ParallelOrchestrator()
    .AddAgent(securityReviewer)
    .AddAgent(performanceReviewer)
    .AddAgent(styleReviewer);

// Outer: pipeline that writes, reviews, and refines
var pipeline = new PipelineOrchestrator()
    .AddStage(writerAgent)
    .AddStage(reviewOrchestrator)  // Nested parallel inside pipeline
    .AddStage(editorAgent);

Monitoring Execution

All orchestrators fire events before and after each agent runs:

pipeline.BeforeAgentExecution += (sender, args) =>
{
    Console.WriteLine($"Starting: {args.AgentName}");
};

pipeline.AfterAgentExecution += (sender, args) =>
{
    Console.WriteLine($"Completed: {args.AgentName} ({args.Duration.TotalSeconds:F1}s)");
};

Share