Skip to content

MultiAgent

Expose a full multi-agent workflow as a single tool inside a parent agent using the [MultiAgent] attribute. The parent agent invokes the whole workflow like any other tool call — it just describes the task and the workflow handles the rest.

┌─────────────────────────────┐
│         Parent Agent        │
│  "Research quantum computing"│
└──────────────┬──────────────┘
               │ invokes ResearchPipeline (tool call)

┌─────────────────────────────┐
│          Workflow            │
│  ┌──────────────────────┐   │
│  │      researcher      │   │
│  └──────────┬───────────┘   │
│             │               │
│  ┌──────────▼───────────┐   │
│  │        writer        │   │
│  └──────────────────────┘   │
└──────────────┬──────────────┘
               │ final result

┌─────────────────────────────┐
│         Parent Agent        │
│   "Here's what I found..."  │
└─────────────────────────────┘

Basic Usage

csharp
public class ResearchToolkit
{
    [MultiAgent("Run a full research and writing pipeline")]
    public async Task<AgentWorkflowInstance> ResearchPipeline()
    {
        return await AgentWorkflow.Create()
            .AddAgent("researcher", new AgentConfig
            {
                SystemInstructions = "Research the topic thoroughly."
            })
            .AddAgent("writer", new AgentConfig
            {
                SystemInstructions = "Write a clear answer based on the research."
            })
            .From("researcher").To("writer")
            .BuildAsync();
    }
}

var agent = await new AgentBuilder()
    .WithToolkit<ResearchToolkit>()
    .BuildAsync();

The parent agent sees ResearchPipeline as a callable tool. When invoked, the full workflow runs and all its events bubble up into the parent's RunAsync stream.


[MultiAgent] Attribute

PropertyTypeDefaultDescription
Descriptionstring?Method nameDescription shown to the LLM — be specific so the agent knows when to use it
Namestring?Method nameCustom tool name
StreamEventsbooltrueStream inner workflow events into the parent's event stream
TimeoutSecondsint300Workflow execution timeout
csharp
[MultiAgent(
    "Analyze documents and produce a structured report",
    Name = "DocumentAnalysis",
    TimeoutSeconds = 600
)]
public async Task<AgentWorkflowInstance> AnalysisPipeline() { ... }

Provider Inheritance

Agents inside the workflow that don't have their own Provider configured automatically inherit the parent agent's chat client — no extra configuration needed:

csharp
// These agents use whatever model the parent uses
.AddAgent("researcher", new AgentConfig
{
    SystemInstructions = "..."
    // No Provider — inherits from parent at runtime
})

Event Bubbling

All workflow events and each node's agent events flow into the same RunAsync loop — no separate stream. Use ExecutionContext on AgentEvent to identify which agent emitted what:

csharp
await foreach (var evt in agent.RunAsync("Research quantum computing", sessionId: sessionId))
{
    switch (evt)
    {
        // Parent agent's own response (Depth == 0)
        case TextDeltaEvent delta when delta.ExecutionContext?.Depth == 0:
            Console.Write(delta.Text);
            break;

        // Workflow lifecycle events — no ExecutionContext, match directly
        case WorkflowNodeStartedEvent node:
            Console.WriteLine($"\n[{node.NodeId} started]");
            break;

        case WorkflowNodeCompletedEvent node:
            Console.WriteLine($"[{node.NodeId} done — {node.Duration.TotalSeconds:F1}s]");
            break;

        // Text from a specific workflow node
        case TextDeltaEvent delta when delta.ExecutionContext?.AgentName == "writer":
            Console.Write(delta.Text);
            break;
    }
}

Set StreamEvents = false to suppress all workflow events — only the final tool result will be visible to the parent:

csharp
[MultiAgent("Run research pipeline", StreamEvents = false)]
public async Task<AgentWorkflowInstance> ResearchPipeline() { ... }

MultiAgent vs SubAgent

Both delegate work to child agents, but they serve different purposes:

[SubAgent][MultiAgent]
StructureSingle autonomous agentGraph of specialized agents
RoutingAgent decides its own pathDeclarative edges and conditions
Use whenOne expert, unpredictable pathDistinct stages, parallel work, conditional routing

Use [SubAgent] when one agent can handle the whole task autonomously. Use [MultiAgent] when the task benefits from distinct specialized stages or parallel execution.


Typed Metadata

For compile-time validation with conditional registration:

csharp
public class WorkflowMetadata : IToolMetadata
{
    public bool HasResearchCapability { get; set; }
}

public class PipelineToolkit
{
    [MultiAgent<WorkflowMetadata>("Full research pipeline")]
    [ConditionalFunction("HasResearchCapability")]
    public async Task<AgentWorkflowInstance> ResearchPipeline() { ... }
}

var agent = await new AgentBuilder()
    .WithToolkit<PipelineToolkit>(new WorkflowMetadata { HasResearchCapability = true })
    .BuildAsync();

→ See 02.1.4 Tool Dynamic Metadata for conditional registration details.


Next Steps

Released under the MIT License.