mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
Introduce some interfaces,
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
// This sample demonstrates how to run a workflow as a durable orchestration from a console application.
|
||||
// The workflow consists of three executors: OrderLookup -> OrderCancel -> SendEmail.
|
||||
// It uses the DurableExecution API similar to InProcessExecution for in-process workflows.
|
||||
// It uses the DurableExecutionEnvironment which is injected via DI.
|
||||
//
|
||||
// DURABILITY DEMONSTRATION:
|
||||
// - Each activity has artificial delays to simulate real-world operations
|
||||
@@ -13,7 +13,6 @@
|
||||
|
||||
using Microsoft.Agents.AI.DurableTask;
|
||||
using Microsoft.Agents.AI.Workflows;
|
||||
using Microsoft.DurableTask.Client;
|
||||
using Microsoft.DurableTask.Client.AzureManaged;
|
||||
using Microsoft.DurableTask.Worker.AzureManaged;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
@@ -51,7 +50,8 @@ IHost host = Host.CreateDefaultBuilder(args)
|
||||
|
||||
await host.StartAsync();
|
||||
|
||||
DurableTaskClient durableClient = host.Services.GetRequiredService<DurableTaskClient>();
|
||||
// Get the DurableExecutionEnvironment from DI - no need to manually resolve DurableTaskClient
|
||||
DurableExecutionEnvironment durableExecution = host.Services.GetRequiredService<DurableExecutionEnvironment>();
|
||||
|
||||
Console.WriteLine("Durable Workflow Sample");
|
||||
Console.WriteLine("Workflow: OrderLookup (2s) -> OrderCancel (5s) -> SendEmail (1s)");
|
||||
@@ -75,7 +75,7 @@ while (true)
|
||||
|
||||
try
|
||||
{
|
||||
await StartNewWorkflowAsync(input, cancelOrder, durableClient);
|
||||
await StartNewWorkflowAsync(input, cancelOrder, durableExecution);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -87,12 +87,13 @@ while (true)
|
||||
|
||||
await host.StopAsync();
|
||||
|
||||
// Start a new workflow
|
||||
async Task StartNewWorkflowAsync(string orderId, Workflow workflow, DurableTaskClient client)
|
||||
// Start a new workflow using DurableExecutionEnvironment (no DurableTaskClient needed)
|
||||
async Task StartNewWorkflowAsync(string orderId, Workflow workflow, DurableExecutionEnvironment execution)
|
||||
{
|
||||
Console.WriteLine($"Starting workflow for order '{orderId}'...");
|
||||
|
||||
await using DurableRun run = await DurableWorkflow.RunAsync(workflow, orderId, client);
|
||||
// RunAsync returns IRun, cast to DurableRun for durable-specific features like WaitForCompletionAsync
|
||||
await using DurableRun run = (DurableRun)await execution.RunAsync(workflow, orderId);
|
||||
Console.WriteLine($"Instance ID: {run.InstanceId}");
|
||||
|
||||
try
|
||||
|
||||
@@ -27,7 +27,6 @@ using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Agents.AI.DurableTask;
|
||||
using Microsoft.Agents.AI.Workflows;
|
||||
using Microsoft.DurableTask.Client;
|
||||
using Microsoft.DurableTask.Client.AzureManaged;
|
||||
using Microsoft.DurableTask.Worker.AzureManaged;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
@@ -77,7 +76,9 @@ IHost host = Host.CreateDefaultBuilder(args)
|
||||
.Build();
|
||||
|
||||
await host.StartAsync();
|
||||
DurableTaskClient durableClient = host.Services.GetRequiredService<DurableTaskClient>();
|
||||
|
||||
// Get the DurableExecutionEnvironment from DI - no need to manually resolve DurableTaskClient
|
||||
DurableExecutionEnvironment durableExecution = host.Services.GetRequiredService<DurableExecutionEnvironment>();
|
||||
|
||||
// Console UI
|
||||
Console.ForegroundColor = ConsoleColor.Cyan;
|
||||
@@ -109,7 +110,8 @@ while (true)
|
||||
|
||||
try
|
||||
{
|
||||
await using DurableRun run = await DurableWorkflow.RunAsync(workflow, input, durableClient);
|
||||
// Cast to DurableRun for durable-specific features like InstanceId and WaitForCompletionAsync
|
||||
await using DurableRun run = (DurableRun)await durableExecution.RunAsync(workflow, input);
|
||||
Console.ForegroundColor = ConsoleColor.Gray;
|
||||
Console.WriteLine($"Instance: {run.InstanceId}");
|
||||
Console.ResetColor();
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
|
||||
using Microsoft.Agents.AI.DurableTask;
|
||||
using Microsoft.Agents.AI.Workflows;
|
||||
using Microsoft.DurableTask.Client;
|
||||
using Microsoft.DurableTask.Client.AzureManaged;
|
||||
using Microsoft.DurableTask.Worker.AzureManaged;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
@@ -44,15 +43,16 @@ IHost host = Host.CreateDefaultBuilder(args)
|
||||
|
||||
await host.StartAsync();
|
||||
|
||||
// Get services
|
||||
DurableTaskClient durableClient = host.Services.GetRequiredService<DurableTaskClient>();
|
||||
// Get the DurableExecutionEnvironment from DI - no need to manually resolve DurableTaskClient
|
||||
DurableExecutionEnvironment durableExecution = host.Services.GetRequiredService<DurableExecutionEnvironment>();
|
||||
|
||||
// Start the workflow with an expense ID as input
|
||||
string expenseId = "EXP-2025-001";
|
||||
Console.WriteLine($"Starting expense reimbursement workflow for expense: {expenseId}");
|
||||
|
||||
// Start the workflow and get a streaming handle
|
||||
await using DurableStreamingRun run = await DurableWorkflow.StreamAsync(expenseApproval, expenseId, durableClient);
|
||||
// Cast to DurableStreamingRun for durable-specific features like InstanceId and SendResponseAsync
|
||||
await using DurableStreamingRun run = (DurableStreamingRun)await durableExecution.StreamAsync(expenseApproval, expenseId);
|
||||
|
||||
Console.WriteLine($"Workflow started with instance ID: {run.InstanceId}");
|
||||
Console.WriteLine("Watching for workflow events...\n");
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// 1. AddEventAsync - Emit custom events that callers can observe in real-time
|
||||
// 2. YieldOutputAsync - Stream intermediate outputs during long-running operations
|
||||
//
|
||||
// The sample uses DurableWorkflow.StreamAsync to observe events as they occur,
|
||||
// The sample uses DurableExecutionEnvironment.StreamAsync to observe events as they occur,
|
||||
// showing how callers can receive real-time updates from the workflow.
|
||||
//
|
||||
// Workflow: OrderLookup -> OrderCancel -> SendEmail
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
using Microsoft.Agents.AI.DurableTask;
|
||||
using Microsoft.Agents.AI.Workflows;
|
||||
using Microsoft.DurableTask.Client;
|
||||
using Microsoft.DurableTask.Client.AzureManaged;
|
||||
using Microsoft.DurableTask.Worker.AzureManaged;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
@@ -55,7 +54,8 @@ IHost host = Host.CreateDefaultBuilder(args)
|
||||
|
||||
await host.StartAsync();
|
||||
|
||||
DurableTaskClient durableClient = host.Services.GetRequiredService<DurableTaskClient>();
|
||||
// Get the DurableExecutionEnvironment from DI - no need to manually resolve DurableTaskClient
|
||||
DurableExecutionEnvironment durableExecution = host.Services.GetRequiredService<DurableExecutionEnvironment>();
|
||||
|
||||
Console.WriteLine("Workflow Events Demo - Enter order ID (or 'exit'):");
|
||||
|
||||
@@ -70,7 +70,7 @@ while (true)
|
||||
|
||||
try
|
||||
{
|
||||
await RunWorkflowWithStreamingAsync(input, cancelOrder, durableClient);
|
||||
await RunWorkflowWithStreamingAsync(input, cancelOrder, durableExecution);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -83,10 +83,11 @@ while (true)
|
||||
await host.StopAsync();
|
||||
|
||||
// Runs a workflow and streams events as they occur
|
||||
async Task RunWorkflowWithStreamingAsync(string orderId, Workflow workflow, DurableTaskClient client)
|
||||
async Task RunWorkflowWithStreamingAsync(string orderId, Workflow workflow, DurableExecutionEnvironment execution)
|
||||
{
|
||||
// StreamAsync starts the workflow and returns a handle for observing events
|
||||
await using DurableStreamingRun run = await DurableWorkflow.StreamAsync(workflow, orderId, client);
|
||||
// Cast to DurableStreamingRun for durable-specific features like InstanceId
|
||||
await using DurableStreamingRun run = (DurableStreamingRun)await execution.StreamAsync(workflow, orderId);
|
||||
Console.WriteLine($"Started: {run.InstanceId}");
|
||||
|
||||
// WatchStreamAsync yields events as they're emitted by executors
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI.DurableTask;
|
||||
using Microsoft.Agents.AI.Workflows;
|
||||
using Microsoft.DurableTask.Client;
|
||||
using Microsoft.DurableTask.Client.AzureManaged;
|
||||
using Microsoft.DurableTask.Worker.AzureManaged;
|
||||
using Microsoft.Extensions.AI;
|
||||
@@ -62,7 +61,8 @@ IHost host = Host.CreateDefaultBuilder(args)
|
||||
|
||||
await host.StartAsync();
|
||||
|
||||
DurableTaskClient durableClient = host.Services.GetRequiredService<DurableTaskClient>();
|
||||
// Get the DurableExecutionEnvironment from DI - no need to manually resolve DurableTaskClient
|
||||
DurableExecutionEnvironment durableExecution = host.Services.GetRequiredService<DurableExecutionEnvironment>();
|
||||
|
||||
Console.WriteLine("Workflow Events Demo - Enter input for slogan generation (or 'exit'):");
|
||||
|
||||
@@ -77,7 +77,7 @@ while (true)
|
||||
|
||||
try
|
||||
{
|
||||
await RunWorkflowWithStreamingAsync(input, workflow, durableClient);
|
||||
await RunWorkflowWithStreamingAsync(input, workflow, durableExecution);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -90,10 +90,11 @@ while (true)
|
||||
await host.StopAsync();
|
||||
|
||||
// Runs a workflow and streams events as they occur
|
||||
async Task RunWorkflowWithStreamingAsync(string orderId, Workflow workflow, DurableTaskClient client)
|
||||
async Task RunWorkflowWithStreamingAsync(string orderId, Workflow workflow, DurableExecutionEnvironment execution)
|
||||
{
|
||||
// StreamAsync starts the workflow and returns a handle for observing events
|
||||
await using DurableStreamingRun run = await DurableWorkflow.StreamAsync(workflow, orderId, client);
|
||||
// Cast to DurableStreamingRun for durable-specific features like InstanceId
|
||||
await using DurableStreamingRun run = (DurableStreamingRun)await execution.StreamAsync(workflow, orderId);
|
||||
Console.WriteLine($"Started: {run.InstanceId}");
|
||||
|
||||
// WatchStreamAsync yields events as they're emitted by executors
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
/* Visual Studio Settings File */
|
||||
{
|
||||
"environment.visualExperience.colorTheme": "dark-plus"
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Microsoft.Agents.AI.Workflows;
|
||||
using Microsoft.DurableTask.Client;
|
||||
|
||||
namespace Microsoft.Agents.AI.DurableTask;
|
||||
|
||||
/// <summary>
|
||||
/// Provides a DI-friendly execution environment for running workflows as durable orchestrations.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This class wraps the <see cref="DurableTaskClient"/> and provides methods to run workflows
|
||||
/// without requiring the client to be passed explicitly. Register this class in DI using
|
||||
/// <see cref="DurableWorkflowServiceCollectionExtensions.ConfigureDurableWorkflows"/>.
|
||||
/// </remarks>
|
||||
public sealed class DurableExecutionEnvironment
|
||||
{
|
||||
private readonly DurableTaskClient _client;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DurableExecutionEnvironment"/> class.
|
||||
/// </summary>
|
||||
/// <param name="client">The durable task client for orchestration operations.</param>
|
||||
public DurableExecutionEnvironment(DurableTaskClient client)
|
||||
{
|
||||
this._client = client ?? throw new ArgumentNullException(nameof(client));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Runs a workflow as a durable orchestration and returns a handle to monitor its execution.
|
||||
/// </summary>
|
||||
/// <typeparam name="TInput">The type of the input to the workflow.</typeparam>
|
||||
/// <param name="workflow">The workflow to execute.</param>
|
||||
/// <param name="input">The input to pass to the workflow's starting executor.</param>
|
||||
/// <param name="instanceId">Optional instance ID for the orchestration. If not provided, a new ID will be generated.</param>
|
||||
/// <param name="cancellationToken">A cancellation token to observe.</param>
|
||||
/// <returns>An <see cref="IRun"/> that can be used to monitor the workflow execution.</returns>
|
||||
/// <exception cref="ArgumentNullException">Thrown when workflow is null.</exception>
|
||||
/// <exception cref="ArgumentException">Thrown when the workflow does not have a valid name.</exception>
|
||||
public ValueTask<IRun> RunAsync<TInput>(
|
||||
Workflow workflow,
|
||||
TInput input,
|
||||
string? instanceId = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
where TInput : notnull
|
||||
=> DurableWorkflow.RunAsync(workflow, input, this._client, instanceId, cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Runs a workflow as a durable orchestration with string input.
|
||||
/// </summary>
|
||||
/// <param name="workflow">The workflow to execute.</param>
|
||||
/// <param name="input">The string input to pass to the workflow.</param>
|
||||
/// <param name="instanceId">Optional instance ID for the orchestration.</param>
|
||||
/// <param name="cancellationToken">A cancellation token to observe.</param>
|
||||
/// <returns>An <see cref="IRun"/> that can be used to monitor the workflow execution.</returns>
|
||||
public ValueTask<IRun> RunAsync(
|
||||
Workflow workflow,
|
||||
string input,
|
||||
string? instanceId = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
=> DurableWorkflow.RunAsync(workflow, input, this._client, instanceId, cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Starts a workflow as a durable orchestration and returns a streaming handle to watch events.
|
||||
/// </summary>
|
||||
/// <typeparam name="TInput">The type of the input to the workflow.</typeparam>
|
||||
/// <param name="workflow">The workflow to execute.</param>
|
||||
/// <param name="input">The input to pass to the workflow's starting executor.</param>
|
||||
/// <param name="instanceId">Optional instance ID for the orchestration. If not provided, a new ID will be generated.</param>
|
||||
/// <param name="cancellationToken">A cancellation token to observe.</param>
|
||||
/// <returns>An <see cref="IStreamingRun"/> that can be used to stream workflow events.</returns>
|
||||
/// <exception cref="ArgumentNullException">Thrown when workflow is null.</exception>
|
||||
/// <exception cref="ArgumentException">Thrown when the workflow does not have a valid name.</exception>
|
||||
public ValueTask<IStreamingRun> StreamAsync<TInput>(
|
||||
Workflow workflow,
|
||||
TInput input,
|
||||
string? instanceId = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
where TInput : notnull
|
||||
=> DurableWorkflow.StreamAsync(workflow, input, this._client, instanceId, cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Starts a workflow as a durable orchestration with string input and returns a streaming handle.
|
||||
/// </summary>
|
||||
/// <param name="workflow">The workflow to execute.</param>
|
||||
/// <param name="input">The string input to pass to the workflow.</param>
|
||||
/// <param name="instanceId">Optional instance ID for the orchestration.</param>
|
||||
/// <param name="cancellationToken">A cancellation token to observe.</param>
|
||||
/// <returns>An <see cref="IStreamingRun"/> that can be used to stream workflow events.</returns>
|
||||
public ValueTask<IStreamingRun> StreamAsync(
|
||||
Workflow workflow,
|
||||
string input,
|
||||
string? instanceId = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
=> DurableWorkflow.StreamAsync(workflow, input, this._client, instanceId, cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Attaches to an existing workflow orchestration instance.
|
||||
/// </summary>
|
||||
/// <param name="instanceId">The instance ID of the orchestration to attach to.</param>
|
||||
/// <param name="workflowName">The name of the workflow being executed.</param>
|
||||
/// <returns>An <see cref="IRun"/> that can be used to monitor the workflow execution.</returns>
|
||||
public IRun Attach(string instanceId, string workflowName)
|
||||
=> DurableWorkflow.Attach(instanceId, workflowName, this._client);
|
||||
|
||||
/// <summary>
|
||||
/// Attaches to an existing workflow orchestration instance for streaming.
|
||||
/// </summary>
|
||||
/// <param name="instanceId">The instance ID of the orchestration to attach to.</param>
|
||||
/// <param name="workflow">The workflow being executed.</param>
|
||||
/// <returns>An <see cref="IStreamingRun"/> that can be used to stream workflow events.</returns>
|
||||
public IStreamingRun AttachStream(string instanceId, Workflow workflow)
|
||||
=> DurableWorkflow.AttachStream(instanceId, workflow, this._client);
|
||||
}
|
||||
@@ -14,7 +14,7 @@ namespace Microsoft.Agents.AI.DurableTask;
|
||||
/// This class provides a similar API to <see cref="Run"/> but for workflows executed as durable orchestrations.
|
||||
/// Events are received by raising external events to the orchestration and can be streamed to the caller.
|
||||
/// </remarks>
|
||||
public sealed class DurableRun : IAsyncDisposable
|
||||
public sealed class DurableRun : IRun
|
||||
{
|
||||
private readonly DurableTaskClient _client;
|
||||
private readonly List<WorkflowEvent> _eventSink = [];
|
||||
@@ -32,6 +32,9 @@ public sealed class DurableRun : IAsyncDisposable
|
||||
/// </summary>
|
||||
public string InstanceId { get; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string RunId => this.InstanceId;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the workflow being executed.
|
||||
/// </summary>
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Microsoft.Agents.AI.DurableTask;
|
||||
/// Events are detected by monitoring the orchestration status for <see cref="RequestPort"/> executors that are waiting
|
||||
/// for external input (human-in-the-loop scenarios).
|
||||
/// </remarks>
|
||||
public sealed class DurableStreamingRun : IAsyncDisposable
|
||||
public sealed class DurableStreamingRun : IStreamingRun
|
||||
{
|
||||
private readonly DurableTaskClient _client;
|
||||
private readonly Workflow _workflow;
|
||||
@@ -37,6 +37,9 @@ public sealed class DurableStreamingRun : IAsyncDisposable
|
||||
/// </summary>
|
||||
public string InstanceId { get; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string RunId => this.InstanceId;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the workflow being executed.
|
||||
/// </summary>
|
||||
@@ -76,6 +79,10 @@ public sealed class DurableStreamingRun : IAsyncDisposable
|
||||
};
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IAsyncEnumerable<WorkflowEvent> WatchStreamAsync(CancellationToken cancellationToken = default)
|
||||
=> this.WatchStreamAsync(pollingInterval: null, cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously streams workflow events as they occur during workflow execution.
|
||||
/// </summary>
|
||||
@@ -94,8 +101,8 @@ public sealed class DurableStreamingRun : IAsyncDisposable
|
||||
/// <param name="cancellationToken">A cancellation token to observe.</param>
|
||||
/// <returns>An asynchronous stream of <see cref="WorkflowEvent"/> objects.</returns>
|
||||
public async IAsyncEnumerable<WorkflowEvent> WatchStreamAsync(
|
||||
TimeSpan? pollingInterval = null,
|
||||
[EnumeratorCancellation] CancellationToken cancellationToken = default)
|
||||
TimeSpan? pollingInterval,
|
||||
[EnumeratorCancellation] CancellationToken cancellationToken = default)
|
||||
{
|
||||
TimeSpan interval = pollingInterval ?? TimeSpan.FromMilliseconds(500);
|
||||
|
||||
@@ -350,6 +357,10 @@ public sealed class DurableStreamingRun : IAsyncDisposable
|
||||
cancellation: cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ValueTask SendResponseAsync(ExternalResponse response, CancellationToken cancellationToken = default)
|
||||
=> this.SendExternalEventAsync("ExternalResponse", response, cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Sends a response to a pending request in the workflow.
|
||||
/// </summary>
|
||||
|
||||
@@ -19,10 +19,10 @@ public static class DurableWorkflow
|
||||
/// <param name="client">The durable task client for orchestration operations.</param>
|
||||
/// <param name="instanceId">Optional instance ID for the orchestration. If not provided, a new ID will be generated.</param>
|
||||
/// <param name="cancellationToken">A cancellation token to observe.</param>
|
||||
/// <returns>A <see cref="DurableRun"/> that can be used to monitor the workflow execution.</returns>
|
||||
/// <returns>An <see cref="IRun"/> that can be used to monitor the workflow execution.</returns>
|
||||
/// <exception cref="ArgumentNullException">Thrown when workflow or client is null.</exception>
|
||||
/// <exception cref="ArgumentException">Thrown when the workflow does not have a valid name.</exception>
|
||||
public static async ValueTask<DurableRun> RunAsync<TInput>(
|
||||
public static async ValueTask<IRun> RunAsync<TInput>(
|
||||
Workflow workflow,
|
||||
TInput input,
|
||||
DurableTaskClient client,
|
||||
@@ -55,8 +55,8 @@ public static class DurableWorkflow
|
||||
/// <param name="client">The durable task client for orchestration operations.</param>
|
||||
/// <param name="instanceId">Optional instance ID for the orchestration.</param>
|
||||
/// <param name="cancellationToken">A cancellation token to observe.</param>
|
||||
/// <returns>A <see cref="DurableRun"/> that can be used to monitor the workflow execution.</returns>
|
||||
public static ValueTask<DurableRun> RunAsync(
|
||||
/// <returns>An <see cref="IRun"/> that can be used to monitor the workflow execution.</returns>
|
||||
public static ValueTask<IRun> RunAsync(
|
||||
Workflow workflow,
|
||||
string input,
|
||||
DurableTaskClient client,
|
||||
@@ -73,10 +73,10 @@ public static class DurableWorkflow
|
||||
/// <param name="client">The durable task client for orchestration operations.</param>
|
||||
/// <param name="instanceId">Optional instance ID for the orchestration. If not provided, a new ID will be generated.</param>
|
||||
/// <param name="cancellationToken">A cancellation token to observe.</param>
|
||||
/// <returns>A <see cref="DurableStreamingRun"/> that can be used to stream workflow events.</returns>
|
||||
/// <returns>An <see cref="IStreamingRun"/> that can be used to stream workflow events.</returns>
|
||||
/// <exception cref="ArgumentNullException">Thrown when workflow or client is null.</exception>
|
||||
/// <exception cref="ArgumentException">Thrown when the workflow does not have a valid name.</exception>
|
||||
public static async ValueTask<DurableStreamingRun> StreamAsync<TInput>(
|
||||
public static async ValueTask<IStreamingRun> StreamAsync<TInput>(
|
||||
Workflow workflow,
|
||||
TInput input,
|
||||
DurableTaskClient client,
|
||||
@@ -109,8 +109,8 @@ public static class DurableWorkflow
|
||||
/// <param name="client">The durable task client for orchestration operations.</param>
|
||||
/// <param name="instanceId">Optional instance ID for the orchestration.</param>
|
||||
/// <param name="cancellationToken">A cancellation token to observe.</param>
|
||||
/// <returns>A <see cref="DurableStreamingRun"/> that can be used to stream workflow events.</returns>
|
||||
public static ValueTask<DurableStreamingRun> StreamAsync(
|
||||
/// <returns>An <see cref="IStreamingRun"/> that can be used to stream workflow events.</returns>
|
||||
public static ValueTask<IStreamingRun> StreamAsync(
|
||||
Workflow workflow,
|
||||
string input,
|
||||
DurableTaskClient client,
|
||||
@@ -124,8 +124,8 @@ public static class DurableWorkflow
|
||||
/// <param name="instanceId">The instance ID of the orchestration to attach to.</param>
|
||||
/// <param name="workflowName">The name of the workflow being executed.</param>
|
||||
/// <param name="client">The durable task client for orchestration operations.</param>
|
||||
/// <returns>A <see cref="DurableRun"/> that can be used to monitor the workflow execution.</returns>
|
||||
public static DurableRun Attach(
|
||||
/// <returns>An <see cref="IRun"/> that can be used to monitor the workflow execution.</returns>
|
||||
public static IRun Attach(
|
||||
string instanceId,
|
||||
string workflowName,
|
||||
DurableTaskClient client)
|
||||
@@ -143,8 +143,8 @@ public static class DurableWorkflow
|
||||
/// <param name="instanceId">The instance ID of the orchestration to attach to.</param>
|
||||
/// <param name="workflow">The workflow being executed.</param>
|
||||
/// <param name="client">The durable task client for orchestration operations.</param>
|
||||
/// <returns>A <see cref="DurableStreamingRun"/> that can be used to stream workflow events.</returns>
|
||||
public static DurableStreamingRun AttachStream(
|
||||
/// <returns>An <see cref="IStreamingRun"/> that can be used to stream workflow events.</returns>
|
||||
public static IStreamingRun AttachStream(
|
||||
string instanceId,
|
||||
Workflow workflow,
|
||||
DurableTaskClient client)
|
||||
|
||||
+3
@@ -113,6 +113,9 @@ public static class DurableWorkflowServiceCollectionExtensions
|
||||
services.AddDurableTaskClient(clientBuilder);
|
||||
}
|
||||
|
||||
// Register the DurableExecutionEnvironment for DI-friendly workflow execution
|
||||
services.TryAddSingleton<DurableExecutionEnvironment>();
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Microsoft.Agents.AI.Workflows;
|
||||
|
||||
namespace Microsoft.Agents.AI.DurableTask;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a workflow run that tracks execution status and emitted workflow events,
|
||||
/// supporting resumption with responses to external requests.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This interface defines the common contract for workflow runs across different execution
|
||||
/// environments (in-process, durable, etc.). Implementations provide the mechanism to
|
||||
/// interact with running workflows, send responses, and access emitted events.
|
||||
/// </remarks>
|
||||
public interface IRun : IAsyncDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the unique identifier for the run.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This identifier can be provided at the start of the run, or auto-generated.
|
||||
/// For durable runs, this corresponds to the orchestration instance ID.
|
||||
/// </remarks>
|
||||
string RunId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets all events that have been emitted by the workflow.
|
||||
/// </summary>
|
||||
IEnumerable<WorkflowEvent> OutgoingEvents { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of events emitted since the last access to <see cref="NewEvents"/>.
|
||||
/// </summary>
|
||||
int NewEventCount { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets all events emitted by the workflow since the last access to this property.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Each access to this property advances the bookmark, so subsequent accesses
|
||||
/// will only return events emitted after the previous access.
|
||||
/// </remarks>
|
||||
IEnumerable<WorkflowEvent> NewEvents { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Sends an external response to the workflow.
|
||||
/// </summary>
|
||||
/// <param name="response">The external response to send.</param>
|
||||
/// <param name="cancellationToken">A cancellation token to observe.</param>
|
||||
/// <returns>A <see cref="ValueTask"/> representing the asynchronous operation.</returns>
|
||||
ValueTask SendResponseAsync(ExternalResponse response, CancellationToken cancellationToken = default);
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Microsoft.Agents.AI.Workflows;
|
||||
|
||||
namespace Microsoft.Agents.AI.DurableTask;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a workflow run that supports streaming workflow events as they occur,
|
||||
/// providing a mechanism to send responses back to the workflow.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This interface defines the common contract for streaming workflow runs across different
|
||||
/// execution environments (in-process, durable, etc.). Implementations provide real-time
|
||||
/// access to workflow events and the ability to respond to external requests.
|
||||
/// </remarks>
|
||||
public interface IStreamingRun : IAsyncDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the unique identifier for the run.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This identifier can be provided at the start of the run, or auto-generated.
|
||||
/// For durable runs, this corresponds to the orchestration instance ID.
|
||||
/// </remarks>
|
||||
string RunId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously streams workflow events as they occur during workflow execution.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method yields <see cref="WorkflowEvent"/> instances in real time as the workflow
|
||||
/// progresses. The stream completes when the workflow completes, fails, or is terminated.
|
||||
/// Events are delivered in the order they are raised.
|
||||
/// </remarks>
|
||||
/// <param name="cancellationToken">
|
||||
/// A <see cref="CancellationToken"/> that can be used to cancel the streaming operation.
|
||||
/// If cancellation is requested, the stream will end and no further events will be yielded.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// An asynchronous stream of <see cref="WorkflowEvent"/> objects representing significant
|
||||
/// workflow state changes.
|
||||
/// </returns>
|
||||
IAsyncEnumerable<WorkflowEvent> WatchStreamAsync(CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Sends an external response to the workflow.
|
||||
/// </summary>
|
||||
/// <param name="response">The external response to send.</param>
|
||||
/// <param name="cancellationToken">A cancellation token to observe.</param>
|
||||
/// <returns>A <see cref="ValueTask"/> representing the asynchronous operation.</returns>
|
||||
ValueTask SendResponseAsync(ExternalResponse response, CancellationToken cancellationToken = default);
|
||||
}
|
||||
Reference in New Issue
Block a user