// 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(); } }