// Copyright (c) Microsoft. All rights reserved.
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Shared.Diagnostics;
namespace Microsoft.Agents.AI.Workflows;
///
/// Fluent builder for sequential agent workflows: a pipeline where the output of one
/// agent is the input to the next, terminating in an aggregator that yields the
/// accumulated s as the workflow output.
///
///
/// When no explicit output designations are made, the default is the Python-aligned
/// shape: the terminal aggregator is the workflow output, and every participating agent
/// is designated as an intermediate output source. Calling
///
/// or
/// at all suppresses these defaults.
///
public sealed class SequentialWorkflowBuilder : OrchestrationBuilderBase
{
private readonly List _agents = [];
///
/// Initializes a new with the given pipeline
/// of .
///
public SequentialWorkflowBuilder(params IEnumerable agents)
{
Throw.IfNull(agents);
foreach (AIAgent agent in agents)
{
Throw.IfNull(agent, nameof(agents));
this._agents.Add(agent);
}
}
/// Builds the configured sequential workflow.
public Workflow Build()
{
if (this._agents.Count == 0)
{
throw new ArgumentException("At least one agent must be provided to the SequentialWorkflowBuilder.", "agents");
}
AIAgentHostOptions options = new()
{
ReassignOtherAgentsAsUsers = true,
ForwardIncomingMessages = true,
};
Dictionary agentMap = new(AIAgentIDEqualityComparer.Instance);
List agentExecutors = new(this._agents.Count);
foreach (AIAgent agent in this._agents)
{
ExecutorBinding binding = agent.BindAsExecutor(options);
agentExecutors.Add(binding);
agentMap[agent] = binding;
}
ExecutorBinding previous = agentExecutors[0];
WorkflowBuilder builder = new(previous);
foreach (ExecutorBinding next in agentExecutors.Skip(1))
{
builder.AddEdge(previous, next);
previous = next;
}
OutputMessagesExecutor end = new();
builder.AddEdge(previous, end).BindExecutor(end);
this.ApplyMetadata(builder);
this.ApplyOutputDesignations(builder, agentMap, "sequential", () =>
{
builder.WithOutputFrom(end);
builder.WithIntermediateOutputFrom(agentExecutors);
});
return builder.Build();
}
}