From 12256b59aae3e0d8625ea661d4cd91172f335dc9 Mon Sep 17 00:00:00 2001 From: Shyju Krishnankutty Date: Thu, 22 Jan 2026 22:09:33 -0800 Subject: [PATCH] Working demos --- dotnet/samples/AzureFunctions/.editorconfig | 3 + .../AzureFunctions/09_Workflow/Program.cs | 22 +++---- .../10_WorkflowConcurrent/Program.cs | 14 ++-- .../10_WorkflowConcurrent/demo.http | 2 +- .../11_WorkflowSharedState/MyOrchFunction.cs | 64 ------------------- .../11_WorkflowSharedState/Program.cs | 8 +-- .../12_ConditionalEdges.csproj | 7 +- .../12_ConditionalEdges/Program.cs | 12 ++-- .../DurableWorkflowOptions.cs | 2 +- .../Microsoft.Agents.AI.DurableTask/Logs.cs | 12 ++-- 10 files changed, 39 insertions(+), 107 deletions(-) delete mode 100644 dotnet/samples/AzureFunctions/11_WorkflowSharedState/MyOrchFunction.cs diff --git a/dotnet/samples/AzureFunctions/.editorconfig b/dotnet/samples/AzureFunctions/.editorconfig index b43bf5ebd0..6a74241db4 100644 --- a/dotnet/samples/AzureFunctions/.editorconfig +++ b/dotnet/samples/AzureFunctions/.editorconfig @@ -8,3 +8,6 @@ dotnet_diagnostic.DURABLE0003.severity = none dotnet_diagnostic.DURABLE0004.severity = none dotnet_diagnostic.DURABLE0005.severity = none dotnet_diagnostic.DURABLE0006.severity = none + +# CA1812: Internal classes are instantiated via dependency injection or reflection in samples +dotnet_diagnostic.CA1812.severity = none diff --git a/dotnet/samples/AzureFunctions/09_Workflow/Program.cs b/dotnet/samples/AzureFunctions/09_Workflow/Program.cs index e475426946..fa21e2bcfa 100644 --- a/dotnet/samples/AzureFunctions/09_Workflow/Program.cs +++ b/dotnet/samples/AzureFunctions/09_Workflow/Program.cs @@ -23,9 +23,8 @@ var orderParserExecutor = orderParserFunc.BindAsExecutor("ParseOrderId"); OrderLookup orderLookupExecutor = new(); OrderEnrich orderEnricherExeecutor = new(); PaymentProcessor paymentProcessorExecutor = new(); -OrderCancel orderArchiverExecutor = new(); -Workflow processOrder = new WorkflowBuilder(orderParserExecutor) +Workflow fulfillOrder = new WorkflowBuilder(orderParserExecutor) .WithName("FulfillOrder") .WithDescription("Looks up an order by ID and run payment processing") .AddEdge(orderParserExecutor, orderLookupExecutor) @@ -33,20 +32,17 @@ Workflow processOrder = new WorkflowBuilder(orderParserExecutor) .AddEdge(orderEnricherExeecutor, paymentProcessorExecutor) .Build(); -Workflow cancelOrder = new WorkflowBuilder(orderParserExecutor) - .WithName("CancelOrder") - .WithDescription("Cancel an order") - .AddEdge(orderParserExecutor, orderLookupExecutor) - .AddEdge(orderLookupExecutor, orderArchiverExecutor) - .Build(); +//OrderCancel orderArchiverExecutor = new(); +//Workflow cancelOrder = new WorkflowBuilder(orderParserExecutor) +// .WithName("CancelOrder") +// .WithDescription("Cancel an order") +// .AddEdge(orderParserExecutor, orderLookupExecutor) +// .AddEdge(orderLookupExecutor, orderArchiverExecutor) +// .Build(); var host = FunctionsApplication.CreateBuilder(args) .ConfigureFunctionsWebApplication() - .ConfigureDurableOptions(options => - { - options.Workflows.AddWorkflow(processOrder); - options.Workflows.AddWorkflow(cancelOrder, true); - }) + .ConfigureDurableOptions(options => options.Workflows.AddWorkflow(fulfillOrder)) .Build(); host.Run(); diff --git a/dotnet/samples/AzureFunctions/10_WorkflowConcurrent/Program.cs b/dotnet/samples/AzureFunctions/10_WorkflowConcurrent/Program.cs index 948f750038..a1435fd39d 100644 --- a/dotnet/samples/AzureFunctions/10_WorkflowConcurrent/Program.cs +++ b/dotnet/samples/AzureFunctions/10_WorkflowConcurrent/Program.cs @@ -30,21 +30,19 @@ AIAgent chemist = client.GetChatClient(deploymentName).CreateAIAgent("You are an var startExecutor = new ConcurrentStartExecutor(); var aggregationExecutor = new ResultAggregationExecutor(); -// Build the workflow by adding executors and connecting them var workflow = new WorkflowBuilder(startExecutor) - .WithName("FanOutWorkflow") + .WithName("ExpertReview") .AddFanOutEdge(startExecutor, [physicist, chemist]) .AddFanInEdge([physicist, chemist], aggregationExecutor) .Build(); -// Configure the function app to host AI agents and workflows in a unified way. -// This will automatically generate HTTP API endpoints for agents and workflows. - -FunctionsApplication.CreateBuilder(args) +var host = FunctionsApplication.CreateBuilder(args) .ConfigureFunctionsWebApplication() .ConfigureDurableOptions(options => { // Configure workflows - options.Workflows.AddWorkflow(workflow, enableMcpToolTrigger: true); + options.Workflows.AddWorkflow(workflow); }) - .Build().Run(); + .Build(); + +host.Run(); diff --git a/dotnet/samples/AzureFunctions/10_WorkflowConcurrent/demo.http b/dotnet/samples/AzureFunctions/10_WorkflowConcurrent/demo.http index 92027a13bf..f3a2b6006a 100644 --- a/dotnet/samples/AzureFunctions/10_WorkflowConcurrent/demo.http +++ b/dotnet/samples/AzureFunctions/10_WorkflowConcurrent/demo.http @@ -2,7 +2,7 @@ @authority=http://localhost:7071 ### Start the workflow -POST {{authority}}/api/workflows/FanOutWorkflow/run +POST {{authority}}/api/workflows/ExpertReview/run Content-Type: text/plain What is temperature? diff --git a/dotnet/samples/AzureFunctions/11_WorkflowSharedState/MyOrchFunction.cs b/dotnet/samples/AzureFunctions/11_WorkflowSharedState/MyOrchFunction.cs deleted file mode 100644 index 903a14cabd..0000000000 --- a/dotnet/samples/AzureFunctions/11_WorkflowSharedState/MyOrchFunction.cs +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using Microsoft.Azure.Functions.Worker; -using Microsoft.Azure.Functions.Worker.Http; -using Microsoft.DurableTask; -using Microsoft.DurableTask.Client; -using Microsoft.Extensions.Logging; - -namespace SingleAgent; - -public static class MyOrchFunction -{ - [Function(nameof(MyOrchFunction))] - public static async Task> RunOrchestratorAsync( - [OrchestrationTrigger] TaskOrchestrationContext context) - { - ILogger logger = context.CreateReplaySafeLogger(nameof(MyOrchFunction)); - logger.LogInformation("Saying hello."); - var outputs = new List(); - - // Replace name and input with values relevant for your Durable Functions Activity - outputs.Add(await context.CallActivityAsync(nameof(SayHello), "Tokyo")); - outputs.Add(await context.CallActivityAsync(nameof(SayHello), "Seattle")); - outputs.Add(await context.CallActivityAsync(nameof(SayHello), "London")); - - // returns ["Hello Tokyo!", "Hello Seattle!", "Hello London!"] - return outputs; - } - - [Function(nameof(SayHello))] - public static string SayHello([ActivityTrigger] string name, - TaskActivityContext taskActivityContext, - FunctionContext functionContext) - { - ILogger logger = functionContext.GetLogger("SayHello"); - if (logger.IsEnabled(LogLevel.Information)) - { - var instanceId = (string)functionContext.BindingContext.BindingData["instanceId"]!; - logger.LogInformation("Saying hello to {Name} for instanceId:{InstanceId}", name, instanceId); - } - return $"Hello {name}!"; - } - - [Function("MyOrchFunction_HttpStart")] - public static async Task HttpStartAsync( - [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestData req, - [DurableClient] DurableTaskClient client, - FunctionContext executionContext) - { - ILogger logger = executionContext.GetLogger("MyOrchFunction_HttpStart"); - - // Function input comes from the request content. - string instanceId = await client.ScheduleNewOrchestrationInstanceAsync( - nameof(MyOrchFunction)); - if (logger.IsEnabled(LogLevel.Information)) - { - logger.LogInformation("Started orchestration with ID = '{InstanceId}'.", instanceId); - } - - // Returns an HTTP 202 response with an instance management payload. - // See https://learn.microsoft.com/azure/azure-functions/durable/durable-functions-http-api#start-orchestration - return await client.CreateCheckStatusResponseAsync(req, instanceId); - } -} diff --git a/dotnet/samples/AzureFunctions/11_WorkflowSharedState/Program.cs b/dotnet/samples/AzureFunctions/11_WorkflowSharedState/Program.cs index 167e1fe6cf..34235b7337 100644 --- a/dotnet/samples/AzureFunctions/11_WorkflowSharedState/Program.cs +++ b/dotnet/samples/AzureFunctions/11_WorkflowSharedState/Program.cs @@ -19,11 +19,5 @@ var workflow = builder.WithName("ProcessOrder").Build(); FunctionsApplication.CreateBuilder(args) .ConfigureFunctionsWebApplication() - .ConfigureDurableOptions(options => - { - options.Workflows.AddWorkflow(workflow); - - // Optional - Configure AI agents - // options.Agents.AddAIAgent(agent); - }) + .ConfigureDurableOptions(options => options.Workflows.AddWorkflow(workflow)) .Build().Run(); diff --git a/dotnet/samples/AzureFunctions/12_ConditionalEdges/12_ConditionalEdges.csproj b/dotnet/samples/AzureFunctions/12_ConditionalEdges/12_ConditionalEdges.csproj index 14ce86c2b9..7519c51418 100644 --- a/dotnet/samples/AzureFunctions/12_ConditionalEdges/12_ConditionalEdges.csproj +++ b/dotnet/samples/AzureFunctions/12_ConditionalEdges/12_ConditionalEdges.csproj @@ -1,4 +1,4 @@ - + net10.0 v4 @@ -15,7 +15,10 @@ - + + PreserveNewest + Never + diff --git a/dotnet/samples/AzureFunctions/12_ConditionalEdges/Program.cs b/dotnet/samples/AzureFunctions/12_ConditionalEdges/Program.cs index 8cfa0b8126..b0f075e7cc 100644 --- a/dotnet/samples/AzureFunctions/12_ConditionalEdges/Program.cs +++ b/dotnet/samples/AzureFunctions/12_ConditionalEdges/Program.cs @@ -12,13 +12,15 @@ PaymentProcesserExecutor paymentProcessor = new(); NotifyFraudExecutor notifyFraud = new(); WorkflowBuilder builder = new(orderParser); -builder.AddEdge(orderParser, orderEnrich); -builder.AddEdge(orderEnrich, notifyFraud, condition: OrderRouteConditions.WhenBlocked()); -builder.AddEdge(orderEnrich, paymentProcessor, condition: OrderRouteConditions.WhenNotBlocked()); +builder + .AddEdge(orderParser, orderEnrich) + .AddEdge(orderEnrich, notifyFraud, condition: OrderRouteConditions.WhenBlocked()) + .AddEdge(orderEnrich, paymentProcessor, condition: OrderRouteConditions.WhenNotBlocked()); -var workflow = builder.WithName("ProcessOrder").Build(); +var workflow = builder.WithName("AuditOrder").Build(); FunctionsApplication.CreateBuilder(args) .ConfigureFunctionsWebApplication() .ConfigureDurableOptions(options => options.Workflows.AddWorkflow(workflow)) - .Build().Run(); + .Build() + .Run(); diff --git a/dotnet/src/Microsoft.Agents.AI.DurableTask/DurableWorkflowOptions.cs b/dotnet/src/Microsoft.Agents.AI.DurableTask/DurableWorkflowOptions.cs index c4deeb309c..12fc931314 100644 --- a/dotnet/src/Microsoft.Agents.AI.DurableTask/DurableWorkflowOptions.cs +++ b/dotnet/src/Microsoft.Agents.AI.DurableTask/DurableWorkflowOptions.cs @@ -67,7 +67,7 @@ public sealed class DurableWorkflowOptions /// Adds a collection of workflows to the current instance. /// /// The collection of objects to add. Cannot be . - public void AddWorkflow(IEnumerable workflows) + public void AddWorkflows(IEnumerable workflows) { ArgumentNullException.ThrowIfNull(workflows); diff --git a/dotnet/src/Microsoft.Agents.AI.DurableTask/Logs.cs b/dotnet/src/Microsoft.Agents.AI.DurableTask/Logs.cs index 1667095a96..4540bd28e6 100644 --- a/dotnet/src/Microsoft.Agents.AI.DurableTask/Logs.cs +++ b/dotnet/src/Microsoft.Agents.AI.DurableTask/Logs.cs @@ -103,37 +103,37 @@ internal static partial class Logs [LoggerMessage( EventId = 12, - Level = LogLevel.Information, + Level = LogLevel.Debug, Message = "Attempting to run workflow: {WorkflowName}")] public static partial void LogAttemptingToRunWorkflow(this ILogger logger, string workflowName); [LoggerMessage( EventId = 13, - Level = LogLevel.Information, + Level = LogLevel.Debug, Message = "Running workflow: {WorkflowName}")] public static partial void LogRunningWorkflow(this ILogger logger, string? workflowName); [LoggerMessage( EventId = 14, - Level = LogLevel.Information, + Level = LogLevel.Debug, Message = "Attempting to execute activity in workflow '{WorkflowName}' for executor '{ExecutorName}'")] public static partial void LogAttemptingToExecuteActivity(this ILogger logger, string workflowName, string executorName); [LoggerMessage( EventId = 15, - Level = LogLevel.Information, + Level = LogLevel.Debug, Message = "Executing activity for executor '{ExecutorId}' of type '{ExecutorType}'")] public static partial void LogExecutingActivity(this ILogger logger, string executorId, string executorType); [LoggerMessage( EventId = 16, - Level = LogLevel.Information, + Level = LogLevel.Debug, Message = "Activity executed for executor '{ExecutorId}' with result: {Result}")] public static partial void LogActivityExecuted(this ILogger logger, string executorId, string result); [LoggerMessage( EventId = 17, - Level = LogLevel.Information, + Level = LogLevel.Debug, Message = "Executor '{ExecutorId}' skipped due to edge condition evaluation")] public static partial void LogExecutorSkipped(this ILogger logger, string executorId); }