Files
agent-framework/dotnet/src/Microsoft.Agents.AI.DurableTask/DurableWorkflowOptions.cs
T
2026-01-27 21:00:45 -08:00

102 lines
3.8 KiB
C#

// Copyright (c) Microsoft. All rights reserved.
using System.Diagnostics;
using Microsoft.Agents.AI.Workflows;
namespace Microsoft.Agents.AI.DurableTask;
/// <summary>
/// Provides configuration options for managing durable workflows within an application.
/// </summary>
[DebuggerDisplay("Workflows = {Workflows.Count}")]
public sealed class DurableWorkflowOptions
{
private readonly Dictionary<string, Workflow> _workflows = new(StringComparer.OrdinalIgnoreCase);
private readonly DurableOptions? _parentOptions;
/// <summary>
/// Initializes a new instance of the <see cref="DurableWorkflowOptions"/> class.
/// </summary>
/// <param name="parentOptions">Optional parent options container for accessing related configuration.</param>
internal DurableWorkflowOptions(DurableOptions? parentOptions = null)
{
this._parentOptions = parentOptions;
this.Executors = new ExecutorRegistry();
}
/// <summary>
/// Gets the collection of workflows available in the current context, keyed by their unique names.
/// </summary>
public IReadOnlyDictionary<string, Workflow> Workflows => this._workflows;
/// <summary>
/// Gets the executor registry for direct executor lookup.
/// </summary>
internal ExecutorRegistry Executors { get; }
/// <summary>
/// Adds a workflow to the collection for processing or execution.
/// </summary>
/// <param name="workflow">The workflow instance to add. Cannot be null.</param>
/// <remarks>
/// When a workflow is added, any AI agent executors in the workflow will be automatically
/// registered with the <see cref="DurableAgentsOptions"/> if it was provided during construction.
/// </remarks>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="workflow"/> is null.</exception>
/// <exception cref="ArgumentException">Thrown when the workflow does not have a valid name.</exception>
public void AddWorkflow(Workflow workflow)
{
ArgumentNullException.ThrowIfNull(workflow);
if (string.IsNullOrEmpty(workflow.Name))
{
throw new ArgumentException("Workflow must have a valid Name property.", nameof(workflow));
}
this._workflows[workflow.Name] = workflow;
RegisterExecutors(workflow, this.Executors);
DurableAgentsOptions? agentOptions = this._parentOptions?.Agents;
if (agentOptions is not null)
{
RegisterAgenticExecutors(workflow, agentOptions);
}
}
/// <summary>
/// Adds a collection of workflows to the current instance.
/// </summary>
/// <param name="workflows">The collection of <see cref="Workflow"/> objects to add. Cannot be <see langword="null"/>.</param>
public void AddWorkflows(IEnumerable<Workflow> workflows)
{
ArgumentNullException.ThrowIfNull(workflows);
foreach (var workflow in workflows)
{
this.AddWorkflow(workflow);
}
}
private static void RegisterExecutors(Workflow workflow, ExecutorRegistry registry)
{
foreach (KeyValuePair<string, ExecutorBinding> executor in workflow.ReflectExecutors())
{
int underscoreIndex = executor.Key.IndexOf('_');
string executorName = underscoreIndex > 0 ? executor.Key[..underscoreIndex] : executor.Key;
registry.Register(executorName, executor.Key, workflow);
}
}
private static void RegisterAgenticExecutors(Workflow workflow, DurableAgentsOptions agentOptions)
{
foreach (KeyValuePair<string, ExecutorBinding> executor in workflow.ReflectExecutors())
{
if (executor.Value.RawValue is AIAgent agent && agent.Name is not null && !agentOptions.ContainsAgent(agent.Name))
{
agentOptions.AddAIAgent(agent, workflowOnly: true);
}
}
}
}