diff --git a/dotnet/samples/AzureFunctions/09_Workflow/OrderProcessingExecutors.cs b/dotnet/samples/AzureFunctions/09_Workflow/OrderProcessingExecutors.cs index 193735f192..536136020a 100644 --- a/dotnet/samples/AzureFunctions/09_Workflow/OrderProcessingExecutors.cs +++ b/dotnet/samples/AzureFunctions/09_Workflow/OrderProcessingExecutors.cs @@ -7,7 +7,7 @@ namespace SingleAgent; /// /// Parses an Order ID from a string input and returns an Order object populated. /// -internal sealed class OrderLookupExecutor() : Executor("OrderLookup") +internal sealed class OrderLookup() : Executor("OrderLookup") { public override async ValueTask HandleAsync(string message, IWorkflowContext context, CancellationToken cancellationToken = default) { @@ -19,7 +19,7 @@ internal sealed class OrderLookupExecutor() : Executor("OrderLook /// /// Enriches an Order object with additional information. /// -internal sealed class OrderEnricherExecutor() : Executor("EnrichOrder") +internal sealed class OrderEnrich() : Executor("EnrichOrder") { public override async ValueTask HandleAsync(Order message, IWorkflowContext context, CancellationToken cancellationToken = default) { @@ -33,7 +33,7 @@ internal sealed class OrderEnricherExecutor() : Executor("EnrichOr } } -internal sealed class PaymentProcessorExecutor() : Executor("ProcessPayment") +internal sealed class PaymentProcessor() : Executor("ProcessPayment") { public override async ValueTask HandleAsync(Order message, IWorkflowContext context, CancellationToken cancellationToken = default) { @@ -43,6 +43,14 @@ internal sealed class PaymentProcessorExecutor() : Executor("Proce } } +internal sealed class OrderCancel() : Executor("OrderCancel") +{ + public override async ValueTask HandleAsync(Order message, IWorkflowContext context, CancellationToken cancellationToken = default) + { + return $"Order {message.Id} cancelled at {DateTime.UtcNow:g} UTC."; + } +} + internal sealed class Order { public Order(string id, decimal amount) diff --git a/dotnet/samples/AzureFunctions/09_Workflow/Program.cs b/dotnet/samples/AzureFunctions/09_Workflow/Program.cs index 06a84a05cf..ea805bd2d6 100644 --- a/dotnet/samples/AzureFunctions/09_Workflow/Program.cs +++ b/dotnet/samples/AzureFunctions/09_Workflow/Program.cs @@ -20,12 +20,10 @@ Func orderParserFunc = input => }; var orderParserExecutor = orderParserFunc.BindAsExecutor("OrderParser"); -Func cancelOrderFunc = input => $"Cancelled order:{input}"; -var orderArchiver = orderParserFunc.BindAsExecutor("OrderArchiver"); - -OrderLookupExecutor orderLookupExecutor = new(); -OrderEnricherExecutor orderEnricherExeecutor = new(); -PaymentProcessorExecutor paymentProcessorExecutor = new(); +OrderLookup orderLookupExecutor = new(); +OrderEnrich orderEnricherExeecutor = new(); +PaymentProcessor paymentProcessorExecutor = new(); +OrderCancel orderArchiverExecutor = new(); Workflow processOrder = new WorkflowBuilder(orderParserExecutor) .WithName("FulfillOrder") @@ -39,12 +37,16 @@ Workflow cancelOrder = new WorkflowBuilder(orderParserExecutor) .WithName("CancelOrder") .WithDescription("Cancel an order") .AddEdge(orderParserExecutor, orderLookupExecutor) - .AddEdge(orderLookupExecutor, orderArchiver) + .AddEdge(orderLookupExecutor, orderArchiverExecutor) .Build(); var host = FunctionsApplication.CreateBuilder(args) .ConfigureFunctionsWebApplication() - .ConfigureDurableOptions(options => options.Workflows.AddWorkflow([processOrder, cancelOrder])) + .ConfigureDurableOptions(options => + { + options.Workflows.AddWorkflow(processOrder); + options.Workflows.AddWorkflow(cancelOrder, true); + }) .Build(); host.Run(); diff --git a/dotnet/src/Microsoft.Agents.AI.Hosting.AzureFunctions/BuiltInFunctions.cs b/dotnet/src/Microsoft.Agents.AI.Hosting.AzureFunctions/BuiltInFunctions.cs index 6310e535b5..4776d9fff7 100644 --- a/dotnet/src/Microsoft.Agents.AI.Hosting.AzureFunctions/BuiltInFunctions.cs +++ b/dotnet/src/Microsoft.Agents.AI.Hosting.AzureFunctions/BuiltInFunctions.cs @@ -6,12 +6,10 @@ using Microsoft.Agents.AI.DurableTask; using Microsoft.Azure.Functions.Worker; using Microsoft.Azure.Functions.Worker.Extensions.Mcp; using Microsoft.Azure.Functions.Worker.Http; -using Microsoft.DurableTask; using Microsoft.DurableTask.Client; using Microsoft.DurableTask.Worker.Grpc; using Microsoft.Extensions.AI; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; namespace Microsoft.Agents.AI.Hosting.AzureFunctions; @@ -244,9 +242,7 @@ internal static class BuiltInFunctions string workflowName = context.Name; string orchestrationFunctionName = WorkflowNamingHelper.ToOrchestrationFunctionName(workflowName); - string instanceId = await client.ScheduleNewOrchestrationInstanceAsync( - orchestrationFunctionName, - new DurableWorkflowRunRequest { WorkflowName = workflowName, Input = input }); + string instanceId = await client.ScheduleNewOrchestrationInstanceAsync(orchestrationFunctionName, input); // Wait for the orchestration to complete and return the result OrchestrationMetadata? metadata = await client.WaitForInstanceCompletionAsync( @@ -257,26 +253,6 @@ internal static class BuiltInFunctions return metadata?.ReadOutputAs(); } -#pragma warning disable DURTASK001 // Durable analyzer complained - public static Task WorkflowRunnerOrchestrationAsync(TaskOrchestrationContext context, DurableWorkflowRunRequest input) - { - ArgumentNullException.ThrowIfNull(context); - - ILogger logger = context.CreateReplaySafeLogger("BuiltInFunctions"); - logger.LogInformation("WorkflowRunnerOrchestrationAsync function called."); - - FunctionContext? functionContext = context.GetFunctionContext(); - if (functionContext == null) - { - throw new InvalidOperationException("FunctionContext is not available in the orchestration context."); - } - - var workFlowName = input.WorkflowName; - - return Task.FromResult(new DurableWorkflowRunResult(workFlowName, workFlowName)); - } -#pragma warning restore DURTASK001 - /// /// Creates an error response with the specified status code and error message. ///