From 8add9748ef907aca1243b18d3c3da14784998f91 Mon Sep 17 00:00:00 2001 From: Shyju Krishnankutty Date: Tue, 27 Jan 2026 13:35:21 -0800 Subject: [PATCH] Introduce some interfaces, --- .../ConsoleApps/08_SingleWorkflow/Program.cs | 15 +-- .../09_Workflow_Concurrency/Program.cs | 8 +- .../ConsoleApps/10_Workflow_HITL/Program.cs | 8 +- .../ConsoleApps/11_WorkflowEvents/Program.cs | 13 +- .../ConsoleApps/12_WorkflowLoop/Program.cs | 11 +- dotnet/settings.VisualStudio.json | 4 + .../DurableExecutionEnvironment.cs | 114 ++++++++++++++++++ .../DurableRun.cs | 5 +- .../DurableStreamingRun.cs | 17 ++- .../DurableWorkflow.cs | 24 ++-- ...ableWorkflowServiceCollectionExtensions.cs | 3 + .../Microsoft.Agents.AI.DurableTask/IRun.cs | 53 ++++++++ .../IStreamingRun.cs | 52 ++++++++ 13 files changed, 286 insertions(+), 41 deletions(-) create mode 100644 dotnet/settings.VisualStudio.json create mode 100644 dotnet/src/Microsoft.Agents.AI.DurableTask/DurableExecutionEnvironment.cs create mode 100644 dotnet/src/Microsoft.Agents.AI.DurableTask/IRun.cs create mode 100644 dotnet/src/Microsoft.Agents.AI.DurableTask/IStreamingRun.cs diff --git a/dotnet/samples/DurableAgents/ConsoleApps/08_SingleWorkflow/Program.cs b/dotnet/samples/DurableAgents/ConsoleApps/08_SingleWorkflow/Program.cs index 0ec1b404d5..f871e507fc 100644 --- a/dotnet/samples/DurableAgents/ConsoleApps/08_SingleWorkflow/Program.cs +++ b/dotnet/samples/DurableAgents/ConsoleApps/08_SingleWorkflow/Program.cs @@ -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(); +// Get the DurableExecutionEnvironment from DI - no need to manually resolve DurableTaskClient +DurableExecutionEnvironment durableExecution = host.Services.GetRequiredService(); 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 diff --git a/dotnet/samples/DurableAgents/ConsoleApps/09_Workflow_Concurrency/Program.cs b/dotnet/samples/DurableAgents/ConsoleApps/09_Workflow_Concurrency/Program.cs index 528d709e41..1a24a99330 100644 --- a/dotnet/samples/DurableAgents/ConsoleApps/09_Workflow_Concurrency/Program.cs +++ b/dotnet/samples/DurableAgents/ConsoleApps/09_Workflow_Concurrency/Program.cs @@ -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(); + +// Get the DurableExecutionEnvironment from DI - no need to manually resolve DurableTaskClient +DurableExecutionEnvironment durableExecution = host.Services.GetRequiredService(); // 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(); diff --git a/dotnet/samples/DurableAgents/ConsoleApps/10_Workflow_HITL/Program.cs b/dotnet/samples/DurableAgents/ConsoleApps/10_Workflow_HITL/Program.cs index c6d0a7d5fd..ca87971636 100644 --- a/dotnet/samples/DurableAgents/ConsoleApps/10_Workflow_HITL/Program.cs +++ b/dotnet/samples/DurableAgents/ConsoleApps/10_Workflow_HITL/Program.cs @@ -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(); +// Get the DurableExecutionEnvironment from DI - no need to manually resolve DurableTaskClient +DurableExecutionEnvironment durableExecution = host.Services.GetRequiredService(); // 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"); diff --git a/dotnet/samples/DurableAgents/ConsoleApps/11_WorkflowEvents/Program.cs b/dotnet/samples/DurableAgents/ConsoleApps/11_WorkflowEvents/Program.cs index 22487b4e14..c673800ca3 100644 --- a/dotnet/samples/DurableAgents/ConsoleApps/11_WorkflowEvents/Program.cs +++ b/dotnet/samples/DurableAgents/ConsoleApps/11_WorkflowEvents/Program.cs @@ -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(); +// Get the DurableExecutionEnvironment from DI - no need to manually resolve DurableTaskClient +DurableExecutionEnvironment durableExecution = host.Services.GetRequiredService(); 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 diff --git a/dotnet/samples/DurableAgents/ConsoleApps/12_WorkflowLoop/Program.cs b/dotnet/samples/DurableAgents/ConsoleApps/12_WorkflowLoop/Program.cs index c7199cbfd4..ad6f7677ea 100644 --- a/dotnet/samples/DurableAgents/ConsoleApps/12_WorkflowLoop/Program.cs +++ b/dotnet/samples/DurableAgents/ConsoleApps/12_WorkflowLoop/Program.cs @@ -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(); +// Get the DurableExecutionEnvironment from DI - no need to manually resolve DurableTaskClient +DurableExecutionEnvironment durableExecution = host.Services.GetRequiredService(); 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 diff --git a/dotnet/settings.VisualStudio.json b/dotnet/settings.VisualStudio.json new file mode 100644 index 0000000000..8e92af88e9 --- /dev/null +++ b/dotnet/settings.VisualStudio.json @@ -0,0 +1,4 @@ +/* Visual Studio Settings File */ +{ + "environment.visualExperience.colorTheme": "dark-plus" +} \ No newline at end of file diff --git a/dotnet/src/Microsoft.Agents.AI.DurableTask/DurableExecutionEnvironment.cs b/dotnet/src/Microsoft.Agents.AI.DurableTask/DurableExecutionEnvironment.cs new file mode 100644 index 0000000000..26b68d6b28 --- /dev/null +++ b/dotnet/src/Microsoft.Agents.AI.DurableTask/DurableExecutionEnvironment.cs @@ -0,0 +1,114 @@ +// Copyright (c) Microsoft. All rights reserved. + +using Microsoft.Agents.AI.Workflows; +using Microsoft.DurableTask.Client; + +namespace Microsoft.Agents.AI.DurableTask; + +/// +/// Provides a DI-friendly execution environment for running workflows as durable orchestrations. +/// +/// +/// This class wraps the and provides methods to run workflows +/// without requiring the client to be passed explicitly. Register this class in DI using +/// . +/// +public sealed class DurableExecutionEnvironment +{ + private readonly DurableTaskClient _client; + + /// + /// Initializes a new instance of the class. + /// + /// The durable task client for orchestration operations. + public DurableExecutionEnvironment(DurableTaskClient client) + { + this._client = client ?? throw new ArgumentNullException(nameof(client)); + } + + /// + /// Runs a workflow as a durable orchestration and returns a handle to monitor its execution. + /// + /// The type of the input to the workflow. + /// The workflow to execute. + /// The input to pass to the workflow's starting executor. + /// Optional instance ID for the orchestration. If not provided, a new ID will be generated. + /// A cancellation token to observe. + /// An that can be used to monitor the workflow execution. + /// Thrown when workflow is null. + /// Thrown when the workflow does not have a valid name. + public ValueTask RunAsync( + Workflow workflow, + TInput input, + string? instanceId = null, + CancellationToken cancellationToken = default) + where TInput : notnull + => DurableWorkflow.RunAsync(workflow, input, this._client, instanceId, cancellationToken); + + /// + /// Runs a workflow as a durable orchestration with string input. + /// + /// The workflow to execute. + /// The string input to pass to the workflow. + /// Optional instance ID for the orchestration. + /// A cancellation token to observe. + /// An that can be used to monitor the workflow execution. + public ValueTask RunAsync( + Workflow workflow, + string input, + string? instanceId = null, + CancellationToken cancellationToken = default) + => DurableWorkflow.RunAsync(workflow, input, this._client, instanceId, cancellationToken); + + /// + /// Starts a workflow as a durable orchestration and returns a streaming handle to watch events. + /// + /// The type of the input to the workflow. + /// The workflow to execute. + /// The input to pass to the workflow's starting executor. + /// Optional instance ID for the orchestration. If not provided, a new ID will be generated. + /// A cancellation token to observe. + /// An that can be used to stream workflow events. + /// Thrown when workflow is null. + /// Thrown when the workflow does not have a valid name. + public ValueTask StreamAsync( + Workflow workflow, + TInput input, + string? instanceId = null, + CancellationToken cancellationToken = default) + where TInput : notnull + => DurableWorkflow.StreamAsync(workflow, input, this._client, instanceId, cancellationToken); + + /// + /// Starts a workflow as a durable orchestration with string input and returns a streaming handle. + /// + /// The workflow to execute. + /// The string input to pass to the workflow. + /// Optional instance ID for the orchestration. + /// A cancellation token to observe. + /// An that can be used to stream workflow events. + public ValueTask StreamAsync( + Workflow workflow, + string input, + string? instanceId = null, + CancellationToken cancellationToken = default) + => DurableWorkflow.StreamAsync(workflow, input, this._client, instanceId, cancellationToken); + + /// + /// Attaches to an existing workflow orchestration instance. + /// + /// The instance ID of the orchestration to attach to. + /// The name of the workflow being executed. + /// An that can be used to monitor the workflow execution. + public IRun Attach(string instanceId, string workflowName) + => DurableWorkflow.Attach(instanceId, workflowName, this._client); + + /// + /// Attaches to an existing workflow orchestration instance for streaming. + /// + /// The instance ID of the orchestration to attach to. + /// The workflow being executed. + /// An that can be used to stream workflow events. + public IStreamingRun AttachStream(string instanceId, Workflow workflow) + => DurableWorkflow.AttachStream(instanceId, workflow, this._client); +} diff --git a/dotnet/src/Microsoft.Agents.AI.DurableTask/DurableRun.cs b/dotnet/src/Microsoft.Agents.AI.DurableTask/DurableRun.cs index 5fe120e365..d52df322ee 100644 --- a/dotnet/src/Microsoft.Agents.AI.DurableTask/DurableRun.cs +++ b/dotnet/src/Microsoft.Agents.AI.DurableTask/DurableRun.cs @@ -14,7 +14,7 @@ namespace Microsoft.Agents.AI.DurableTask; /// This class provides a similar API to but for workflows executed as durable orchestrations. /// Events are received by raising external events to the orchestration and can be streamed to the caller. /// -public sealed class DurableRun : IAsyncDisposable +public sealed class DurableRun : IRun { private readonly DurableTaskClient _client; private readonly List _eventSink = []; @@ -32,6 +32,9 @@ public sealed class DurableRun : IAsyncDisposable /// public string InstanceId { get; } + /// + public string RunId => this.InstanceId; + /// /// Gets the name of the workflow being executed. /// diff --git a/dotnet/src/Microsoft.Agents.AI.DurableTask/DurableStreamingRun.cs b/dotnet/src/Microsoft.Agents.AI.DurableTask/DurableStreamingRun.cs index 65830d1e31..18a58d92d3 100644 --- a/dotnet/src/Microsoft.Agents.AI.DurableTask/DurableStreamingRun.cs +++ b/dotnet/src/Microsoft.Agents.AI.DurableTask/DurableStreamingRun.cs @@ -16,7 +16,7 @@ namespace Microsoft.Agents.AI.DurableTask; /// Events are detected by monitoring the orchestration status for executors that are waiting /// for external input (human-in-the-loop scenarios). /// -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 /// public string InstanceId { get; } + /// + public string RunId => this.InstanceId; + /// /// Gets the name of the workflow being executed. /// @@ -76,6 +79,10 @@ public sealed class DurableStreamingRun : IAsyncDisposable }; } + /// + public IAsyncEnumerable WatchStreamAsync(CancellationToken cancellationToken = default) + => this.WatchStreamAsync(pollingInterval: null, cancellationToken); + /// /// Asynchronously streams workflow events as they occur during workflow execution. /// @@ -94,8 +101,8 @@ public sealed class DurableStreamingRun : IAsyncDisposable /// A cancellation token to observe. /// An asynchronous stream of objects. public async IAsyncEnumerable 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); } + /// + public ValueTask SendResponseAsync(ExternalResponse response, CancellationToken cancellationToken = default) + => this.SendExternalEventAsync("ExternalResponse", response, cancellationToken); + /// /// Sends a response to a pending request in the workflow. /// diff --git a/dotnet/src/Microsoft.Agents.AI.DurableTask/DurableWorkflow.cs b/dotnet/src/Microsoft.Agents.AI.DurableTask/DurableWorkflow.cs index cac18319d9..f55d621026 100644 --- a/dotnet/src/Microsoft.Agents.AI.DurableTask/DurableWorkflow.cs +++ b/dotnet/src/Microsoft.Agents.AI.DurableTask/DurableWorkflow.cs @@ -19,10 +19,10 @@ public static class DurableWorkflow /// The durable task client for orchestration operations. /// Optional instance ID for the orchestration. If not provided, a new ID will be generated. /// A cancellation token to observe. - /// A that can be used to monitor the workflow execution. + /// An that can be used to monitor the workflow execution. /// Thrown when workflow or client is null. /// Thrown when the workflow does not have a valid name. - public static async ValueTask RunAsync( + public static async ValueTask RunAsync( Workflow workflow, TInput input, DurableTaskClient client, @@ -55,8 +55,8 @@ public static class DurableWorkflow /// The durable task client for orchestration operations. /// Optional instance ID for the orchestration. /// A cancellation token to observe. - /// A that can be used to monitor the workflow execution. - public static ValueTask RunAsync( + /// An that can be used to monitor the workflow execution. + public static ValueTask RunAsync( Workflow workflow, string input, DurableTaskClient client, @@ -73,10 +73,10 @@ public static class DurableWorkflow /// The durable task client for orchestration operations. /// Optional instance ID for the orchestration. If not provided, a new ID will be generated. /// A cancellation token to observe. - /// A that can be used to stream workflow events. + /// An that can be used to stream workflow events. /// Thrown when workflow or client is null. /// Thrown when the workflow does not have a valid name. - public static async ValueTask StreamAsync( + public static async ValueTask StreamAsync( Workflow workflow, TInput input, DurableTaskClient client, @@ -109,8 +109,8 @@ public static class DurableWorkflow /// The durable task client for orchestration operations. /// Optional instance ID for the orchestration. /// A cancellation token to observe. - /// A that can be used to stream workflow events. - public static ValueTask StreamAsync( + /// An that can be used to stream workflow events. + public static ValueTask StreamAsync( Workflow workflow, string input, DurableTaskClient client, @@ -124,8 +124,8 @@ public static class DurableWorkflow /// The instance ID of the orchestration to attach to. /// The name of the workflow being executed. /// The durable task client for orchestration operations. - /// A that can be used to monitor the workflow execution. - public static DurableRun Attach( + /// An that can be used to monitor the workflow execution. + public static IRun Attach( string instanceId, string workflowName, DurableTaskClient client) @@ -143,8 +143,8 @@ public static class DurableWorkflow /// The instance ID of the orchestration to attach to. /// The workflow being executed. /// The durable task client for orchestration operations. - /// A that can be used to stream workflow events. - public static DurableStreamingRun AttachStream( + /// An that can be used to stream workflow events. + public static IStreamingRun AttachStream( string instanceId, Workflow workflow, DurableTaskClient client) diff --git a/dotnet/src/Microsoft.Agents.AI.DurableTask/DurableWorkflowServiceCollectionExtensions.cs b/dotnet/src/Microsoft.Agents.AI.DurableTask/DurableWorkflowServiceCollectionExtensions.cs index daa796f72d..36da0050f8 100644 --- a/dotnet/src/Microsoft.Agents.AI.DurableTask/DurableWorkflowServiceCollectionExtensions.cs +++ b/dotnet/src/Microsoft.Agents.AI.DurableTask/DurableWorkflowServiceCollectionExtensions.cs @@ -113,6 +113,9 @@ public static class DurableWorkflowServiceCollectionExtensions services.AddDurableTaskClient(clientBuilder); } + // Register the DurableExecutionEnvironment for DI-friendly workflow execution + services.TryAddSingleton(); + return services; } diff --git a/dotnet/src/Microsoft.Agents.AI.DurableTask/IRun.cs b/dotnet/src/Microsoft.Agents.AI.DurableTask/IRun.cs new file mode 100644 index 0000000000..5a383cece9 --- /dev/null +++ b/dotnet/src/Microsoft.Agents.AI.DurableTask/IRun.cs @@ -0,0 +1,53 @@ +// Copyright (c) Microsoft. All rights reserved. + +using Microsoft.Agents.AI.Workflows; + +namespace Microsoft.Agents.AI.DurableTask; + +/// +/// Represents a workflow run that tracks execution status and emitted workflow events, +/// supporting resumption with responses to external requests. +/// +/// +/// 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. +/// +public interface IRun : IAsyncDisposable +{ + /// + /// Gets the unique identifier for the run. + /// + /// + /// This identifier can be provided at the start of the run, or auto-generated. + /// For durable runs, this corresponds to the orchestration instance ID. + /// + string RunId { get; } + + /// + /// Gets all events that have been emitted by the workflow. + /// + IEnumerable OutgoingEvents { get; } + + /// + /// Gets the number of events emitted since the last access to . + /// + int NewEventCount { get; } + + /// + /// Gets all events emitted by the workflow since the last access to this property. + /// + /// + /// Each access to this property advances the bookmark, so subsequent accesses + /// will only return events emitted after the previous access. + /// + IEnumerable NewEvents { get; } + + /// + /// Sends an external response to the workflow. + /// + /// The external response to send. + /// A cancellation token to observe. + /// A representing the asynchronous operation. + ValueTask SendResponseAsync(ExternalResponse response, CancellationToken cancellationToken = default); +} diff --git a/dotnet/src/Microsoft.Agents.AI.DurableTask/IStreamingRun.cs b/dotnet/src/Microsoft.Agents.AI.DurableTask/IStreamingRun.cs new file mode 100644 index 0000000000..27f21382d1 --- /dev/null +++ b/dotnet/src/Microsoft.Agents.AI.DurableTask/IStreamingRun.cs @@ -0,0 +1,52 @@ +// Copyright (c) Microsoft. All rights reserved. + +using Microsoft.Agents.AI.Workflows; + +namespace Microsoft.Agents.AI.DurableTask; + +/// +/// Represents a workflow run that supports streaming workflow events as they occur, +/// providing a mechanism to send responses back to the workflow. +/// +/// +/// 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. +/// +public interface IStreamingRun : IAsyncDisposable +{ + /// + /// Gets the unique identifier for the run. + /// + /// + /// This identifier can be provided at the start of the run, or auto-generated. + /// For durable runs, this corresponds to the orchestration instance ID. + /// + string RunId { get; } + + /// + /// Asynchronously streams workflow events as they occur during workflow execution. + /// + /// + /// This method yields 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. + /// + /// + /// A that can be used to cancel the streaming operation. + /// If cancellation is requested, the stream will end and no further events will be yielded. + /// + /// + /// An asynchronous stream of objects representing significant + /// workflow state changes. + /// + IAsyncEnumerable WatchStreamAsync(CancellationToken cancellationToken = default); + + /// + /// Sends an external response to the workflow. + /// + /// The external response to send. + /// A cancellation token to observe. + /// A representing the asynchronous operation. + ValueTask SendResponseAsync(ExternalResponse response, CancellationToken cancellationToken = default); +}