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:
- The supervisor receives the task and the list of available workers.
- The supervisor decides which worker(s) to delegate to using a
DelegateTool. - Worker results return to the supervisor.
- 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)");
};
📚 Related Content
- What planning strategies can an AI agent use?: Reasoning strategies for individual agents.
- What is the difference between an AI agent and a chatbot?: When to use agents vs simple chat.
- Orchestrate Multi-Agent Workflows with Patterns: Detailed implementation guide for all patterns.
- Delegate Tasks Between Agents with DelegateTool: Step-by-step delegation guide.