From a4039134de2aad04f51ae353a10d9820e1668526 Mon Sep 17 00:00:00 2001 From: Ben Thomas Date: Tue, 14 Oct 2025 13:34:04 -0700 Subject: [PATCH] .NET: Remove reflection samples (#1460) * Removing usage of ReflectingExecutor from workflow samples. * Removing uneeded changes. * Clean up. * Update dotnet/samples/GettingStarted/Workflows/_Foundational/01_ExecutorsAndEdges/Program.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update dotnet/samples/GettingStarted/Workflows/_Foundational/01_ExecutorsAndEdges/Program.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update dotnet/samples/GettingStarted/Workflows/_Foundational/02_Streaming/Program.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update dotnet/samples/GettingStarted/Workflows/_Foundational/02_Streaming/Program.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Updates per PR feedback. * Undo changes to generated file. --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../Agents/CustomAgentExecutors/Program.cs | 16 +- .../Workflows/Agents/FoundryAgent/Program.cs | 2 +- .../Agents/WorkflowAsAnAgent/Program.cs | 4 +- .../WorkflowAsAnAgent/WorkflowHelper.cs | 11 +- .../CheckpointAndRehydrate/Program.cs | 15 +- .../CheckpointAndRehydrate/WorkflowHelper.cs | 25 +-- .../Checkpoint/CheckpointAndResume/Program.cs | 10 +- .../CheckpointAndResume/WorkflowHelper.cs | 25 +-- .../CheckpointWithHumanInTheLoop/Program.cs | 14 +- .../WorkflowHelper.cs | 14 +- .../Concurrent/Concurrent/Program.cs | 13 +- .../Workflows/Concurrent/MapReduce/Program.cs | 24 +- .../01_EdgeCondition/Program.cs | 19 +- .../ConditionalEdges/02_SwitchCase/Program.cs | 27 ++- .../03_MultiSelection/Program.cs | 31 ++- .../Declarative/ExecuteCode/Generated.cs | 210 +++++++++--------- .../Declarative/ExecuteCode/Program.cs | 2 +- .../Declarative/ExecuteWorkflow/Program.cs | 6 +- .../HumanInTheLoopBasic/Program.cs | 8 +- .../HumanInTheLoopBasic/WorkflowHelper.cs | 12 +- .../GettingStarted/Workflows/Loop/Program.cs | 25 +-- .../ApplicationInsights/Program.cs | 9 +- .../Observability/AspireDashboard/Program.cs | 9 +- .../Workflows/SharedStates/Program.cs | 18 +- .../01_ExecutorsAndEdges/Program.cs | 13 +- .../_Foundational/02_Streaming/Program.cs | 15 +- .../03_AgentsInWorkflows/Program.cs | 2 +- .../04_AgentWorkflowPatterns/Program.cs | 2 +- .../05_MultiModelService/Program.cs | 3 +- 29 files changed, 278 insertions(+), 306 deletions(-) diff --git a/dotnet/samples/GettingStarted/Workflows/Agents/CustomAgentExecutors/Program.cs b/dotnet/samples/GettingStarted/Workflows/Agents/CustomAgentExecutors/Program.cs index 437453a865..be345b4656 100644 --- a/dotnet/samples/GettingStarted/Workflows/Agents/CustomAgentExecutors/Program.cs +++ b/dotnet/samples/GettingStarted/Workflows/Agents/CustomAgentExecutors/Program.cs @@ -6,7 +6,6 @@ using Azure.AI.OpenAI; using Azure.Identity; using Microsoft.Agents.AI; using Microsoft.Agents.AI.Workflows; -using Microsoft.Agents.AI.Workflows.Reflection; using Microsoft.Extensions.AI; namespace WorkflowCustomAgentExecutorsSample; @@ -50,7 +49,7 @@ public static class Program // Execute the workflow await using StreamingRun run = await InProcessExecution.StreamAsync(workflow, "Create a slogan for a new electric SUV that is affordable and fun to drive."); - await foreach (WorkflowEvent evt in run.WatchStreamAsync().ConfigureAwait(false)) + await foreach (WorkflowEvent evt in run.WatchStreamAsync()) { if (evt is SloganGeneratedEvent or FeedbackEvent) { @@ -107,10 +106,7 @@ internal sealed class SloganGeneratedEvent(SloganResult sloganResult) : Workflow /// 1. HandleAsync(string message): Handles the initial task to create a slogan. /// 2. HandleAsync(Feedback message): Handles feedback to improve the slogan. /// -internal sealed class SloganWriterExecutor - : ReflectingExecutor, - IMessageHandler, - IMessageHandler +internal sealed class SloganWriterExecutor : Executor { private readonly AIAgent _agent; private readonly AgentThread _thread; @@ -134,6 +130,10 @@ internal sealed class SloganWriterExecutor this._thread = this._agent.GetNewThread(); } + protected override RouteBuilder ConfigureRoutes(RouteBuilder routeBuilder) => + routeBuilder.AddHandler(this.HandleAsync) + .AddHandler(this.HandleAsync); + public async ValueTask HandleAsync(string message, IWorkflowContext context, CancellationToken cancellationToken = default) { var result = await this._agent.RunAsync(message, this._thread, cancellationToken: cancellationToken); @@ -175,7 +175,7 @@ internal sealed class FeedbackEvent(FeedbackResult feedbackResult) : WorkflowEve /// /// A custom executor that uses an AI agent to provide feedback on a slogan. /// -internal sealed class FeedbackExecutor : ReflectingExecutor, IMessageHandler +internal sealed class FeedbackExecutor : Executor { private readonly AIAgent _agent; private readonly AgentThread _thread; @@ -205,7 +205,7 @@ internal sealed class FeedbackExecutor : ReflectingExecutor, I this._thread = this._agent.GetNewThread(); } - public async ValueTask HandleAsync(SloganResult message, IWorkflowContext context, CancellationToken cancellationToken = default) + public override async ValueTask HandleAsync(SloganResult message, IWorkflowContext context, CancellationToken cancellationToken = default) { var sloganMessage = $""" Here is a slogan for the task '{message.Task}': diff --git a/dotnet/samples/GettingStarted/Workflows/Agents/FoundryAgent/Program.cs b/dotnet/samples/GettingStarted/Workflows/Agents/FoundryAgent/Program.cs index 9a9005e79d..9f1de87438 100644 --- a/dotnet/samples/GettingStarted/Workflows/Agents/FoundryAgent/Program.cs +++ b/dotnet/samples/GettingStarted/Workflows/Agents/FoundryAgent/Program.cs @@ -43,7 +43,7 @@ public static class Program // The agents are wrapped as executors. When they receive messages, // they will cache the messages and only start processing when they receive a TurnToken. await run.TrySendMessageAsync(new TurnToken(emitEvents: true)); - await foreach (WorkflowEvent evt in run.WatchStreamAsync().ConfigureAwait(false)) + await foreach (WorkflowEvent evt in run.WatchStreamAsync()) { if (evt is AgentRunUpdateEvent executorComplete) { diff --git a/dotnet/samples/GettingStarted/Workflows/Agents/WorkflowAsAnAgent/Program.cs b/dotnet/samples/GettingStarted/Workflows/Agents/WorkflowAsAnAgent/Program.cs index 49305d9908..16d4e57e69 100644 --- a/dotnet/samples/GettingStarted/Workflows/Agents/WorkflowAsAnAgent/Program.cs +++ b/dotnet/samples/GettingStarted/Workflows/Agents/WorkflowAsAnAgent/Program.cs @@ -35,7 +35,7 @@ public static class Program var chatClient = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetChatClient(deploymentName).AsIChatClient(); // Create the workflow and turn it into an agent - var workflow = await WorkflowHelper.GetWorkflowAsync(chatClient).ConfigureAwait(false); + var workflow = await WorkflowHelper.GetWorkflowAsync(chatClient); var agent = workflow.AsAgent("workflow-agent", "Workflow Agent"); var thread = agent.GetNewThread(); @@ -59,7 +59,7 @@ public static class Program static async Task ProcessInputAsync(AIAgent agent, AgentThread thread, string input) { Dictionary> buffer = []; - await foreach (AgentRunResponseUpdate update in agent.RunStreamingAsync(input, thread).ConfigureAwait(false)) + await foreach (AgentRunResponseUpdate update in agent.RunStreamingAsync(input, thread)) { if (update.MessageId is null) { diff --git a/dotnet/samples/GettingStarted/Workflows/Agents/WorkflowAsAnAgent/WorkflowHelper.cs b/dotnet/samples/GettingStarted/Workflows/Agents/WorkflowAsAnAgent/WorkflowHelper.cs index 3e2261918b..82ebffa050 100644 --- a/dotnet/samples/GettingStarted/Workflows/Agents/WorkflowAsAnAgent/WorkflowHelper.cs +++ b/dotnet/samples/GettingStarted/Workflows/Agents/WorkflowAsAnAgent/WorkflowHelper.cs @@ -2,7 +2,6 @@ using Microsoft.Agents.AI; using Microsoft.Agents.AI.Workflows; -using Microsoft.Agents.AI.Workflows.Reflection; using Microsoft.Extensions.AI; namespace WorkflowAsAnAgentsSample; @@ -43,8 +42,7 @@ internal static class WorkflowHelper /// Executor that starts the concurrent processing by sending messages to the agents. /// private sealed class ConcurrentStartExecutor() : - ReflectingExecutor("ConcurrentStartExecutor"), - IMessageHandler> + Executor>("ConcurrentStartExecutor") { /// /// Starts the concurrent processing by sending messages to the agents. @@ -53,7 +51,7 @@ internal static class WorkflowHelper /// Workflow context for accessing workflow services and adding events /// The to monitor for cancellation requests. /// The default is . - public async ValueTask HandleAsync(List message, IWorkflowContext context, CancellationToken cancellationToken = default) + public override async ValueTask HandleAsync(List message, IWorkflowContext context, CancellationToken cancellationToken = default) { // Broadcast the message to all connected agents. Receiving agents will queue // the message but will not start processing until they receive a turn token. @@ -67,8 +65,7 @@ internal static class WorkflowHelper /// Executor that aggregates the results from the concurrent agents. /// private sealed class ConcurrentAggregationExecutor() : - ReflectingExecutor("ConcurrentAggregationExecutor"), - IMessageHandler + Executor("ConcurrentAggregationExecutor") { private readonly List _messages = []; @@ -79,7 +76,7 @@ internal static class WorkflowHelper /// Workflow context for accessing workflow services and adding events /// The to monitor for cancellation requests. /// The default is . - public async ValueTask HandleAsync(ChatMessage message, IWorkflowContext context, CancellationToken cancellationToken = default) + public override async ValueTask HandleAsync(ChatMessage message, IWorkflowContext context, CancellationToken cancellationToken = default) { this._messages.Add(message); diff --git a/dotnet/samples/GettingStarted/Workflows/Checkpoint/CheckpointAndRehydrate/Program.cs b/dotnet/samples/GettingStarted/Workflows/Checkpoint/CheckpointAndRehydrate/Program.cs index e36d59f6d6..aedf37700d 100644 --- a/dotnet/samples/GettingStarted/Workflows/Checkpoint/CheckpointAndRehydrate/Program.cs +++ b/dotnet/samples/GettingStarted/Workflows/Checkpoint/CheckpointAndRehydrate/Program.cs @@ -25,7 +25,7 @@ public static class Program private static async Task Main() { // Create the workflow - var workflow = await WorkflowHelper.GetWorkflowAsync().ConfigureAwait(false); + var workflow = await WorkflowHelper.GetWorkflowAsync(); // Create checkpoint manager var checkpointManager = CheckpointManager.Default; @@ -33,9 +33,9 @@ public static class Program // Execute the workflow and save checkpoints await using Checkpointed checkpointedRun = await InProcessExecution - .StreamAsync(workflow, NumberSignal.Init, checkpointManager) - .ConfigureAwait(false); - await foreach (WorkflowEvent evt in checkpointedRun.Run.WatchStreamAsync().ConfigureAwait(false)) + .StreamAsync(workflow, NumberSignal.Init, checkpointManager); + + await foreach (WorkflowEvent evt in checkpointedRun.Run.WatchStreamAsync()) { if (evt is ExecutorCompletedEvent executorCompletedEvt) { @@ -67,16 +67,15 @@ public static class Program Console.WriteLine($"Number of checkpoints created: {checkpoints.Count}"); // Rehydrate a new workflow instance from a saved checkpoint and continue execution - var newWorkflow = await WorkflowHelper.GetWorkflowAsync().ConfigureAwait(false); + var newWorkflow = await WorkflowHelper.GetWorkflowAsync(); const int CheckpointIndex = 5; Console.WriteLine($"\n\nHydrating a new workflow instance from the {CheckpointIndex + 1}th checkpoint."); CheckpointInfo savedCheckpoint = checkpoints[CheckpointIndex]; await using Checkpointed newCheckpointedRun = - await InProcessExecution.ResumeStreamAsync(newWorkflow, savedCheckpoint, checkpointManager, checkpointedRun.Run.RunId) - .ConfigureAwait(false); + await InProcessExecution.ResumeStreamAsync(newWorkflow, savedCheckpoint, checkpointManager, checkpointedRun.Run.RunId); - await foreach (WorkflowEvent evt in newCheckpointedRun.Run.WatchStreamAsync().ConfigureAwait(false)) + await foreach (WorkflowEvent evt in newCheckpointedRun.Run.WatchStreamAsync()) { if (evt is ExecutorCompletedEvent executorCompletedEvt) { diff --git a/dotnet/samples/GettingStarted/Workflows/Checkpoint/CheckpointAndRehydrate/WorkflowHelper.cs b/dotnet/samples/GettingStarted/Workflows/Checkpoint/CheckpointAndRehydrate/WorkflowHelper.cs index cb568fca35..bf38f74ec8 100644 --- a/dotnet/samples/GettingStarted/Workflows/Checkpoint/CheckpointAndRehydrate/WorkflowHelper.cs +++ b/dotnet/samples/GettingStarted/Workflows/Checkpoint/CheckpointAndRehydrate/WorkflowHelper.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft. All rights reserved. using Microsoft.Agents.AI.Workflows; -using Microsoft.Agents.AI.Workflows.Reflection; namespace WorkflowCheckpointAndRehydrateSample; @@ -42,7 +41,7 @@ internal enum NumberSignal /// /// Executor that makes a guess based on the current bounds. /// -internal sealed class GuessNumberExecutor() : ReflectingExecutor("Guess"), IMessageHandler +internal sealed class GuessNumberExecutor() : Executor("Guess") { /// /// The lower bound of the guessing range. @@ -69,20 +68,20 @@ internal sealed class GuessNumberExecutor() : ReflectingExecutor (this.LowerBound + this.UpperBound) / 2; - public async ValueTask HandleAsync(NumberSignal message, IWorkflowContext context, CancellationToken cancellationToken = default) + public override async ValueTask HandleAsync(NumberSignal message, IWorkflowContext context, CancellationToken cancellationToken = default) { switch (message) { case NumberSignal.Init: - await context.SendMessageAsync(this.NextGuess, cancellationToken: cancellationToken).ConfigureAwait(false); + await context.SendMessageAsync(this.NextGuess, cancellationToken: cancellationToken); break; case NumberSignal.Above: this.UpperBound = this.NextGuess - 1; - await context.SendMessageAsync(this.NextGuess, cancellationToken: cancellationToken).ConfigureAwait(false); + await context.SendMessageAsync(this.NextGuess, cancellationToken: cancellationToken); break; case NumberSignal.Below: this.LowerBound = this.NextGuess + 1; - await context.SendMessageAsync(this.NextGuess, cancellationToken: cancellationToken).ConfigureAwait(false); + await context.SendMessageAsync(this.NextGuess, cancellationToken: cancellationToken); break; } } @@ -99,13 +98,13 @@ internal sealed class GuessNumberExecutor() : ReflectingExecutor protected override async ValueTask OnCheckpointRestoredAsync(IWorkflowContext context, CancellationToken cancellationToken = default) => - (this.LowerBound, this.UpperBound) = await context.ReadStateAsync<(int, int)>(StateKey, cancellationToken: cancellationToken).ConfigureAwait(false); + (this.LowerBound, this.UpperBound) = await context.ReadStateAsync<(int, int)>(StateKey, cancellationToken: cancellationToken); } /// /// Executor that judges the guess and provides feedback. /// -internal sealed class JudgeExecutor() : ReflectingExecutor("Judge"), IMessageHandler +internal sealed class JudgeExecutor() : Executor("Judge") { private readonly int _targetNumber; private int _tries; @@ -120,20 +119,20 @@ internal sealed class JudgeExecutor() : ReflectingExecutor("Judge this._targetNumber = targetNumber; } - public async ValueTask HandleAsync(int message, IWorkflowContext context, CancellationToken cancellationToken = default) + public override async ValueTask HandleAsync(int message, IWorkflowContext context, CancellationToken cancellationToken = default) { this._tries++; if (message == this._targetNumber) { - await context.YieldOutputAsync($"{this._targetNumber} found in {this._tries} tries!", cancellationToken: cancellationToken).ConfigureAwait(false); + await context.YieldOutputAsync($"{this._targetNumber} found in {this._tries} tries!", cancellationToken: cancellationToken); } else if (message < this._targetNumber) { - await context.SendMessageAsync(NumberSignal.Below, cancellationToken: cancellationToken).ConfigureAwait(false); + await context.SendMessageAsync(NumberSignal.Below, cancellationToken: cancellationToken); } else { - await context.SendMessageAsync(NumberSignal.Above, cancellationToken: cancellationToken).ConfigureAwait(false); + await context.SendMessageAsync(NumberSignal.Above, cancellationToken: cancellationToken); } } @@ -149,5 +148,5 @@ internal sealed class JudgeExecutor() : ReflectingExecutor("Judge /// This must be overridden to restore any state that was saved during checkpointing. /// protected override async ValueTask OnCheckpointRestoredAsync(IWorkflowContext context, CancellationToken cancellationToken = default) => - this._tries = await context.ReadStateAsync(StateKey, cancellationToken: cancellationToken).ConfigureAwait(false); + this._tries = await context.ReadStateAsync(StateKey, cancellationToken: cancellationToken); } diff --git a/dotnet/samples/GettingStarted/Workflows/Checkpoint/CheckpointAndResume/Program.cs b/dotnet/samples/GettingStarted/Workflows/Checkpoint/CheckpointAndResume/Program.cs index f7fb178c8b..b4191b397f 100644 --- a/dotnet/samples/GettingStarted/Workflows/Checkpoint/CheckpointAndResume/Program.cs +++ b/dotnet/samples/GettingStarted/Workflows/Checkpoint/CheckpointAndResume/Program.cs @@ -24,7 +24,7 @@ public static class Program private static async Task Main() { // Create the workflow - var workflow = await WorkflowHelper.GetWorkflowAsync().ConfigureAwait(false); + var workflow = await WorkflowHelper.GetWorkflowAsync(); // Create checkpoint manager var checkpointManager = CheckpointManager.Default; @@ -33,8 +33,8 @@ public static class Program // Execute the workflow and save checkpoints await using Checkpointed checkpointedRun = await InProcessExecution .StreamAsync(workflow, NumberSignal.Init, checkpointManager) - .ConfigureAwait(false); - await foreach (WorkflowEvent evt in checkpointedRun.Run.WatchStreamAsync().ConfigureAwait(false)) + ; + await foreach (WorkflowEvent evt in checkpointedRun.Run.WatchStreamAsync()) { if (evt is ExecutorCompletedEvent executorCompletedEvt) { @@ -70,8 +70,8 @@ public static class Program Console.WriteLine($"\n\nRestoring from the {CheckpointIndex + 1}th checkpoint."); CheckpointInfo savedCheckpoint = checkpoints[CheckpointIndex]; // Note that we are restoring the state directly to the same run instance. - await checkpointedRun.RestoreCheckpointAsync(savedCheckpoint, CancellationToken.None).ConfigureAwait(false); - await foreach (WorkflowEvent evt in checkpointedRun.Run.WatchStreamAsync().ConfigureAwait(false)) + await checkpointedRun.RestoreCheckpointAsync(savedCheckpoint, CancellationToken.None); + await foreach (WorkflowEvent evt in checkpointedRun.Run.WatchStreamAsync()) { if (evt is ExecutorCompletedEvent executorCompletedEvt) { diff --git a/dotnet/samples/GettingStarted/Workflows/Checkpoint/CheckpointAndResume/WorkflowHelper.cs b/dotnet/samples/GettingStarted/Workflows/Checkpoint/CheckpointAndResume/WorkflowHelper.cs index ba6268c924..5f60b355d1 100644 --- a/dotnet/samples/GettingStarted/Workflows/Checkpoint/CheckpointAndResume/WorkflowHelper.cs +++ b/dotnet/samples/GettingStarted/Workflows/Checkpoint/CheckpointAndResume/WorkflowHelper.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft. All rights reserved. using Microsoft.Agents.AI.Workflows; -using Microsoft.Agents.AI.Workflows.Reflection; namespace WorkflowCheckpointAndResumeSample; @@ -42,7 +41,7 @@ internal enum NumberSignal /// /// Executor that makes a guess based on the current bounds. /// -internal sealed class GuessNumberExecutor() : ReflectingExecutor("Guess"), IMessageHandler +internal sealed class GuessNumberExecutor() : Executor("Guess") { /// /// The lower bound of the guessing range. @@ -69,20 +68,20 @@ internal sealed class GuessNumberExecutor() : ReflectingExecutor (this.LowerBound + this.UpperBound) / 2; - public async ValueTask HandleAsync(NumberSignal message, IWorkflowContext context, CancellationToken cancellationToken = default) + public override async ValueTask HandleAsync(NumberSignal message, IWorkflowContext context, CancellationToken cancellationToken = default) { switch (message) { case NumberSignal.Init: - await context.SendMessageAsync(this.NextGuess, cancellationToken: cancellationToken).ConfigureAwait(false); + await context.SendMessageAsync(this.NextGuess, cancellationToken: cancellationToken); break; case NumberSignal.Above: this.UpperBound = this.NextGuess - 1; - await context.SendMessageAsync(this.NextGuess, cancellationToken: cancellationToken).ConfigureAwait(false); + await context.SendMessageAsync(this.NextGuess, cancellationToken: cancellationToken); break; case NumberSignal.Below: this.LowerBound = this.NextGuess + 1; - await context.SendMessageAsync(this.NextGuess, cancellationToken: cancellationToken).ConfigureAwait(false); + await context.SendMessageAsync(this.NextGuess, cancellationToken: cancellationToken); break; } } @@ -99,13 +98,13 @@ internal sealed class GuessNumberExecutor() : ReflectingExecutor protected override async ValueTask OnCheckpointRestoredAsync(IWorkflowContext context, CancellationToken cancellationToken = default) => - (this.LowerBound, this.UpperBound) = await context.ReadStateAsync<(int, int)>(StateKey, cancellationToken: cancellationToken).ConfigureAwait(false); + (this.LowerBound, this.UpperBound) = await context.ReadStateAsync<(int, int)>(StateKey, cancellationToken: cancellationToken); } /// /// Executor that judges the guess and provides feedback. /// -internal sealed class JudgeExecutor() : ReflectingExecutor("Judge"), IMessageHandler +internal sealed class JudgeExecutor() : Executor("Judge") { private readonly int _targetNumber; private int _tries; @@ -120,20 +119,20 @@ internal sealed class JudgeExecutor() : ReflectingExecutor("Judge this._targetNumber = targetNumber; } - public async ValueTask HandleAsync(int message, IWorkflowContext context, CancellationToken cancellationToken = default) + public override async ValueTask HandleAsync(int message, IWorkflowContext context, CancellationToken cancellationToken = default) { this._tries++; if (message == this._targetNumber) { - await context.YieldOutputAsync($"{this._targetNumber} found in {this._tries} tries!", cancellationToken).ConfigureAwait(false); + await context.YieldOutputAsync($"{this._targetNumber} found in {this._tries} tries!", cancellationToken); } else if (message < this._targetNumber) { - await context.SendMessageAsync(NumberSignal.Below, cancellationToken: cancellationToken).ConfigureAwait(false); + await context.SendMessageAsync(NumberSignal.Below, cancellationToken: cancellationToken); } else { - await context.SendMessageAsync(NumberSignal.Above, cancellationToken: cancellationToken).ConfigureAwait(false); + await context.SendMessageAsync(NumberSignal.Above, cancellationToken: cancellationToken); } } @@ -149,5 +148,5 @@ internal sealed class JudgeExecutor() : ReflectingExecutor("Judge /// This must be overridden to restore any state that was saved during checkpointing. /// protected override async ValueTask OnCheckpointRestoredAsync(IWorkflowContext context, CancellationToken cancellationToken = default) => - this._tries = await context.ReadStateAsync(StateKey, cancellationToken: cancellationToken).ConfigureAwait(false); + this._tries = await context.ReadStateAsync(StateKey, cancellationToken: cancellationToken); } diff --git a/dotnet/samples/GettingStarted/Workflows/Checkpoint/CheckpointWithHumanInTheLoop/Program.cs b/dotnet/samples/GettingStarted/Workflows/Checkpoint/CheckpointWithHumanInTheLoop/Program.cs index 48903425a9..0a968ed8b3 100644 --- a/dotnet/samples/GettingStarted/Workflows/Checkpoint/CheckpointWithHumanInTheLoop/Program.cs +++ b/dotnet/samples/GettingStarted/Workflows/Checkpoint/CheckpointWithHumanInTheLoop/Program.cs @@ -27,7 +27,7 @@ public static class Program private static async Task Main() { // Create the workflow - var workflow = await WorkflowHelper.GetWorkflowAsync().ConfigureAwait(false); + var workflow = await WorkflowHelper.GetWorkflowAsync(); // Create checkpoint manager var checkpointManager = CheckpointManager.Default; @@ -36,15 +36,15 @@ public static class Program // Execute the workflow and save checkpoints await using Checkpointed checkpointedRun = await InProcessExecution .StreamAsync(workflow, new SignalWithNumber(NumberSignal.Init), checkpointManager) - .ConfigureAwait(false); - await foreach (WorkflowEvent evt in checkpointedRun.Run.WatchStreamAsync().ConfigureAwait(false)) + ; + await foreach (WorkflowEvent evt in checkpointedRun.Run.WatchStreamAsync()) { switch (evt) { case RequestInfoEvent requestInputEvt: // Handle `RequestInfoEvent` from the workflow ExternalResponse response = HandleExternalRequest(requestInputEvt.Request); - await checkpointedRun.Run.SendResponseAsync(response).ConfigureAwait(false); + await checkpointedRun.Run.SendResponseAsync(response); break; case ExecutorCompletedEvent executorCompletedEvt: Console.WriteLine($"* Executor {executorCompletedEvt.ExecutorId} completed."); @@ -76,15 +76,15 @@ public static class Program Console.WriteLine($"\n\nRestoring from the {CheckpointIndex + 1}th checkpoint."); CheckpointInfo savedCheckpoint = checkpoints[CheckpointIndex]; // Note that we are restoring the state directly to the same run instance. - await checkpointedRun.RestoreCheckpointAsync(savedCheckpoint, CancellationToken.None).ConfigureAwait(false); - await foreach (WorkflowEvent evt in checkpointedRun.Run.WatchStreamAsync().ConfigureAwait(false)) + await checkpointedRun.RestoreCheckpointAsync(savedCheckpoint, CancellationToken.None); + await foreach (WorkflowEvent evt in checkpointedRun.Run.WatchStreamAsync()) { switch (evt) { case RequestInfoEvent requestInputEvt: // Handle `RequestInfoEvent` from the workflow ExternalResponse response = HandleExternalRequest(requestInputEvt.Request); - await checkpointedRun.Run.SendResponseAsync(response).ConfigureAwait(false); + await checkpointedRun.Run.SendResponseAsync(response); break; case ExecutorCompletedEvent executorCompletedEvt: Console.WriteLine($"* Executor {executorCompletedEvt.ExecutorId} completed."); diff --git a/dotnet/samples/GettingStarted/Workflows/Checkpoint/CheckpointWithHumanInTheLoop/WorkflowHelper.cs b/dotnet/samples/GettingStarted/Workflows/Checkpoint/CheckpointWithHumanInTheLoop/WorkflowHelper.cs index 9fabfee873..a4dcfcf376 100644 --- a/dotnet/samples/GettingStarted/Workflows/Checkpoint/CheckpointWithHumanInTheLoop/WorkflowHelper.cs +++ b/dotnet/samples/GettingStarted/Workflows/Checkpoint/CheckpointWithHumanInTheLoop/WorkflowHelper.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft. All rights reserved. using Microsoft.Agents.AI.Workflows; -using Microsoft.Agents.AI.Workflows.Reflection; namespace WorkflowCheckpointWithHumanInTheLoopSample; @@ -54,7 +53,7 @@ internal sealed class SignalWithNumber /// /// Executor that judges the guess and provides feedback. /// -internal sealed class JudgeExecutor() : ReflectingExecutor("Judge"), IMessageHandler +internal sealed class JudgeExecutor() : Executor("Judge") { private readonly int _targetNumber; private int _tries; @@ -69,21 +68,20 @@ internal sealed class JudgeExecutor() : ReflectingExecutor("Judge this._targetNumber = targetNumber; } - public async ValueTask HandleAsync(int message, IWorkflowContext context, CancellationToken cancellationToken = default) + public override async ValueTask HandleAsync(int message, IWorkflowContext context, CancellationToken cancellationToken = default) { this._tries++; if (message == this._targetNumber) { - await context.YieldOutputAsync($"{this._targetNumber} found in {this._tries} tries!", cancellationToken) - .ConfigureAwait(false); + await context.YieldOutputAsync($"{this._targetNumber} found in {this._tries} tries!", cancellationToken); } else if (message < this._targetNumber) { - await context.SendMessageAsync(new SignalWithNumber(NumberSignal.Below, message), cancellationToken: cancellationToken).ConfigureAwait(false); + await context.SendMessageAsync(new SignalWithNumber(NumberSignal.Below, message), cancellationToken: cancellationToken); } else { - await context.SendMessageAsync(new SignalWithNumber(NumberSignal.Above, message), cancellationToken: cancellationToken).ConfigureAwait(false); + await context.SendMessageAsync(new SignalWithNumber(NumberSignal.Above, message), cancellationToken: cancellationToken); } } @@ -99,5 +97,5 @@ internal sealed class JudgeExecutor() : ReflectingExecutor("Judge /// This must be overridden to restore any state that was saved during checkpointing. /// protected override async ValueTask OnCheckpointRestoredAsync(IWorkflowContext context, CancellationToken cancellationToken = default) => - this._tries = await context.ReadStateAsync(StateKey, cancellationToken: cancellationToken).ConfigureAwait(false); + this._tries = await context.ReadStateAsync(StateKey, cancellationToken: cancellationToken); } diff --git a/dotnet/samples/GettingStarted/Workflows/Concurrent/Concurrent/Program.cs b/dotnet/samples/GettingStarted/Workflows/Concurrent/Concurrent/Program.cs index 44d0f0fe77..30b2372006 100644 --- a/dotnet/samples/GettingStarted/Workflows/Concurrent/Concurrent/Program.cs +++ b/dotnet/samples/GettingStarted/Workflows/Concurrent/Concurrent/Program.cs @@ -4,7 +4,6 @@ using Azure.AI.OpenAI; using Azure.Identity; using Microsoft.Agents.AI; using Microsoft.Agents.AI.Workflows; -using Microsoft.Agents.AI.Workflows.Reflection; using Microsoft.Extensions.AI; namespace WorkflowConcurrentSample; @@ -60,7 +59,7 @@ public static class Program // Execute the workflow in streaming mode await using StreamingRun run = await InProcessExecution.StreamAsync(workflow, "What is temperature?"); - await foreach (WorkflowEvent evt in run.WatchStreamAsync().ConfigureAwait(false)) + await foreach (WorkflowEvent evt in run.WatchStreamAsync()) { if (evt is WorkflowOutputEvent output) { @@ -74,8 +73,7 @@ public static class Program /// Executor that starts the concurrent processing by sending messages to the agents. /// internal sealed class ConcurrentStartExecutor() : - ReflectingExecutor("ConcurrentStartExecutor"), - IMessageHandler + Executor("ConcurrentStartExecutor") { /// /// Starts the concurrent processing by sending messages to the agents. @@ -85,7 +83,7 @@ internal sealed class ConcurrentStartExecutor() : /// The to monitor for cancellation requests. /// The default is . /// A task representing the asynchronous operation - public async ValueTask HandleAsync(string message, IWorkflowContext context, CancellationToken cancellationToken = default) + public override async ValueTask HandleAsync(string message, IWorkflowContext context, CancellationToken cancellationToken = default) { // Broadcast the message to all connected agents. Receiving agents will queue // the message but will not start processing until they receive a turn token. @@ -99,8 +97,7 @@ internal sealed class ConcurrentStartExecutor() : /// Executor that aggregates the results from the concurrent agents. /// internal sealed class ConcurrentAggregationExecutor() : - ReflectingExecutor("ConcurrentAggregationExecutor"), - IMessageHandler + Executor("ConcurrentAggregationExecutor") { private readonly List _messages = []; @@ -112,7 +109,7 @@ internal sealed class ConcurrentAggregationExecutor() : /// The to monitor for cancellation requests. /// The default is . /// A task representing the asynchronous operation - public async ValueTask HandleAsync(ChatMessage message, IWorkflowContext context, CancellationToken cancellationToken = default) + public override async ValueTask HandleAsync(ChatMessage message, IWorkflowContext context, CancellationToken cancellationToken = default) { this._messages.Add(message); diff --git a/dotnet/samples/GettingStarted/Workflows/Concurrent/MapReduce/Program.cs b/dotnet/samples/GettingStarted/Workflows/Concurrent/MapReduce/Program.cs index 759f602563..db10f0e8af 100644 --- a/dotnet/samples/GettingStarted/Workflows/Concurrent/MapReduce/Program.cs +++ b/dotnet/samples/GettingStarted/Workflows/Concurrent/MapReduce/Program.cs @@ -8,7 +8,6 @@ using System.Text.Json; using System.Threading; using System.Threading.Tasks; using Microsoft.Agents.AI.Workflows; -using Microsoft.Agents.AI.Workflows.Reflection; namespace WorkflowMapReduceSample; @@ -130,8 +129,7 @@ public static class Program /// Splits data into roughly equal chunks based on the number of mapper nodes. /// internal sealed class Split(string[] mapperIds, string id) : - ReflectingExecutor(id), - IMessageHandler + Executor(id) { private readonly string[] _mapperIds = mapperIds; private static readonly string[] s_lineSeparators = ["\r\n", "\r", "\n"]; @@ -139,7 +137,7 @@ internal sealed class Split(string[] mapperIds, string id) : /// /// Tokenize input and assign contiguous index ranges to each mapper via shared state. /// - public async ValueTask HandleAsync(string message, IWorkflowContext context, CancellationToken cancellationToken = default) + public override async ValueTask HandleAsync(string message, IWorkflowContext context, CancellationToken cancellationToken = default) { // Ensure temp directory exists Directory.CreateDirectory(MapReduceConstants.TempDir); @@ -188,12 +186,12 @@ internal sealed class Split(string[] mapperIds, string id) : /// /// Maps each token to a count of 1 and writes pairs to a per-mapper file. /// -internal sealed class Mapper(string id) : ReflectingExecutor(id), IMessageHandler +internal sealed class Mapper(string id) : Executor(id) { /// /// Read the assigned slice, emit (word, 1) pairs, and persist to disk. /// - public async ValueTask HandleAsync(SplitComplete message, IWorkflowContext context, CancellationToken cancellationToken = default) + public override async ValueTask HandleAsync(SplitComplete message, IWorkflowContext context, CancellationToken cancellationToken = default) { var dataToProcess = await context.ReadStateAsync(MapReduceConstants.DataToProcessKey, scopeName: MapReduceConstants.StateScope, cancellationToken); var chunk = await context.ReadStateAsync<(int start, int end)>(this.Id, scopeName: MapReduceConstants.StateScope, cancellationToken); @@ -215,8 +213,7 @@ internal sealed class Mapper(string id) : ReflectingExecutor(id), IMessa /// Groups intermediate pairs by key and partitions them across reducers. /// internal sealed class Shuffler(string[] reducerIds, string[] mapperIds, string id) : - ReflectingExecutor(id), - IMessageHandler + Executor(id) { private readonly string[] _reducerIds = reducerIds; private readonly string[] _mapperIds = mapperIds; @@ -225,7 +222,7 @@ internal sealed class Shuffler(string[] reducerIds, string[] mapperIds, string i /// /// Aggregate mapper outputs and write one partition file per reducer. /// - public async ValueTask HandleAsync(MapComplete message, IWorkflowContext context, CancellationToken cancellationToken = default) + public override async ValueTask HandleAsync(MapComplete message, IWorkflowContext context, CancellationToken cancellationToken = default) { this._mapResults.Add(message); @@ -314,12 +311,12 @@ internal sealed class Shuffler(string[] reducerIds, string[] mapperIds, string i /// /// Sums grouped counts per key for its assigned partition. /// -internal sealed class Reducer(string id) : ReflectingExecutor(id), IMessageHandler +internal sealed class Reducer(string id) : Executor(id) { /// /// Read one shuffle partition and reduce it to totals. /// - public async ValueTask HandleAsync(ShuffleComplete message, IWorkflowContext context, CancellationToken cancellationToken = default) + public override async ValueTask HandleAsync(ShuffleComplete message, IWorkflowContext context, CancellationToken cancellationToken = default) { if (message.ReducerId != this.Id) { @@ -356,13 +353,12 @@ internal sealed class Reducer(string id) : ReflectingExecutor(id), IMes /// Joins all reducer outputs and yields the final output. /// internal sealed class CompletionExecutor(string id) : - ReflectingExecutor(id), - IMessageHandler> + Executor>(id) { /// /// Collect reducer output file paths and yield final output. /// - public async ValueTask HandleAsync(List message, IWorkflowContext context, CancellationToken cancellationToken = default) + public override async ValueTask HandleAsync(List message, IWorkflowContext context, CancellationToken cancellationToken = default) { var filePaths = message.ConvertAll(r => r.FilePath); await context.YieldOutputAsync(filePaths, cancellationToken); diff --git a/dotnet/samples/GettingStarted/Workflows/ConditionalEdges/01_EdgeCondition/Program.cs b/dotnet/samples/GettingStarted/Workflows/ConditionalEdges/01_EdgeCondition/Program.cs index 6298337d79..b6e3d4d513 100644 --- a/dotnet/samples/GettingStarted/Workflows/ConditionalEdges/01_EdgeCondition/Program.cs +++ b/dotnet/samples/GettingStarted/Workflows/ConditionalEdges/01_EdgeCondition/Program.cs @@ -6,7 +6,6 @@ using Azure.AI.OpenAI; using Azure.Identity; using Microsoft.Agents.AI; using Microsoft.Agents.AI.Workflows; -using Microsoft.Agents.AI.Workflows.Reflection; using Microsoft.Extensions.AI; namespace WorkflowEdgeConditionSample; @@ -64,7 +63,7 @@ public static class Program // Execute the workflow await using StreamingRun run = await InProcessExecution.StreamAsync(workflow, new ChatMessage(ChatRole.User, email)); await run.TrySendMessageAsync(new TurnToken(emitEvents: true)); - await foreach (WorkflowEvent evt in run.WatchStreamAsync().ConfigureAwait(false)) + await foreach (WorkflowEvent evt in run.WatchStreamAsync()) { if (evt is WorkflowOutputEvent outputEvent) { @@ -147,7 +146,7 @@ internal sealed class Email /// /// Executor that detects spam using an AI agent. /// -internal sealed class SpamDetectionExecutor : ReflectingExecutor, IMessageHandler +internal sealed class SpamDetectionExecutor : Executor { private readonly AIAgent _spamDetectionAgent; @@ -160,7 +159,7 @@ internal sealed class SpamDetectionExecutor : ReflectingExecutor HandleAsync(ChatMessage message, IWorkflowContext context, CancellationToken cancellationToken = default) + public override async ValueTask HandleAsync(ChatMessage message, IWorkflowContext context, CancellationToken cancellationToken = default) { // Generate a random email ID and store the email content to the shared state var newEmail = new Email @@ -192,7 +191,7 @@ public sealed class EmailResponse /// /// Executor that assists with email responses using an AI agent. /// -internal sealed class EmailAssistantExecutor : ReflectingExecutor, IMessageHandler +internal sealed class EmailAssistantExecutor : Executor { private readonly AIAgent _emailAssistantAgent; @@ -205,7 +204,7 @@ internal sealed class EmailAssistantExecutor : ReflectingExecutor HandleAsync(DetectionResult message, IWorkflowContext context, CancellationToken cancellationToken = default) + public override async ValueTask HandleAsync(DetectionResult message, IWorkflowContext context, CancellationToken cancellationToken = default) { if (message.IsSpam) { @@ -227,24 +226,24 @@ internal sealed class EmailAssistantExecutor : ReflectingExecutor /// Executor that sends emails. /// -internal sealed class SendEmailExecutor() : ReflectingExecutor("SendEmailExecutor"), IMessageHandler +internal sealed class SendEmailExecutor() : Executor("SendEmailExecutor") { /// /// Simulate the sending of an email. /// - public async ValueTask HandleAsync(EmailResponse message, IWorkflowContext context, CancellationToken cancellationToken = default) => + public override async ValueTask HandleAsync(EmailResponse message, IWorkflowContext context, CancellationToken cancellationToken = default) => await context.YieldOutputAsync($"Email sent: {message.Response}", cancellationToken); } /// /// Executor that handles spam messages. /// -internal sealed class HandleSpamExecutor() : ReflectingExecutor("HandleSpamExecutor"), IMessageHandler +internal sealed class HandleSpamExecutor() : Executor("HandleSpamExecutor") { /// /// Simulate the handling of a spam message. /// - public async ValueTask HandleAsync(DetectionResult message, IWorkflowContext context, CancellationToken cancellationToken = default) + public override async ValueTask HandleAsync(DetectionResult message, IWorkflowContext context, CancellationToken cancellationToken = default) { if (message.IsSpam) { diff --git a/dotnet/samples/GettingStarted/Workflows/ConditionalEdges/02_SwitchCase/Program.cs b/dotnet/samples/GettingStarted/Workflows/ConditionalEdges/02_SwitchCase/Program.cs index 17de5311c5..13f0a75bc2 100644 --- a/dotnet/samples/GettingStarted/Workflows/ConditionalEdges/02_SwitchCase/Program.cs +++ b/dotnet/samples/GettingStarted/Workflows/ConditionalEdges/02_SwitchCase/Program.cs @@ -6,7 +6,6 @@ using Azure.AI.OpenAI; using Azure.Identity; using Microsoft.Agents.AI; using Microsoft.Agents.AI.Workflows; -using Microsoft.Agents.AI.Workflows.Reflection; using Microsoft.Extensions.AI; namespace WorkflowSwitchCaseSample; @@ -80,7 +79,7 @@ public static class Program // Execute the workflow await using StreamingRun run = await InProcessExecution.StreamAsync(workflow, new ChatMessage(ChatRole.User, email)); await run.TrySendMessageAsync(new TurnToken(emitEvents: true)); - await foreach (WorkflowEvent evt in run.WatchStreamAsync().ConfigureAwait(false)) + await foreach (WorkflowEvent evt in run.WatchStreamAsync()) { if (evt is WorkflowOutputEvent outputEvent) { @@ -172,7 +171,7 @@ internal sealed class Email /// /// Executor that detects spam using an AI agent. /// -internal sealed class SpamDetectionExecutor : ReflectingExecutor, IMessageHandler +internal sealed class SpamDetectionExecutor : Executor { private readonly AIAgent _spamDetectionAgent; @@ -185,7 +184,7 @@ internal sealed class SpamDetectionExecutor : ReflectingExecutor HandleAsync(ChatMessage message, IWorkflowContext context, CancellationToken cancellationToken = default) + public override async ValueTask HandleAsync(ChatMessage message, IWorkflowContext context, CancellationToken cancellationToken = default) { // Generate a random email ID and store the email content var newEmail = new Email @@ -217,7 +216,7 @@ public sealed class EmailResponse /// /// Executor that assists with email responses using an AI agent. /// -internal sealed class EmailAssistantExecutor : ReflectingExecutor, IMessageHandler +internal sealed class EmailAssistantExecutor : Executor { private readonly AIAgent _emailAssistantAgent; @@ -230,7 +229,7 @@ internal sealed class EmailAssistantExecutor : ReflectingExecutor HandleAsync(DetectionResult message, IWorkflowContext context, CancellationToken cancellationToken = default) + public override async ValueTask HandleAsync(DetectionResult message, IWorkflowContext context, CancellationToken cancellationToken = default) { if (message.spamDecision == SpamDecision.Spam) { @@ -251,28 +250,28 @@ internal sealed class EmailAssistantExecutor : ReflectingExecutor /// Executor that sends emails. /// -internal sealed class SendEmailExecutor() : ReflectingExecutor("SendEmailExecutor"), IMessageHandler +internal sealed class SendEmailExecutor() : Executor("SendEmailExecutor") { /// /// Simulate the sending of an email. /// - public async ValueTask HandleAsync(EmailResponse message, IWorkflowContext context, CancellationToken cancellationToken = default) => - await context.YieldOutputAsync($"Email sent: {message.Response}", cancellationToken).ConfigureAwait(false); + public override async ValueTask HandleAsync(EmailResponse message, IWorkflowContext context, CancellationToken cancellationToken = default) => + await context.YieldOutputAsync($"Email sent: {message.Response}", cancellationToken); } /// /// Executor that handles spam messages. /// -internal sealed class HandleSpamExecutor() : ReflectingExecutor("HandleSpamExecutor"), IMessageHandler +internal sealed class HandleSpamExecutor() : Executor("HandleSpamExecutor") { /// /// Simulate the handling of a spam message. /// - public async ValueTask HandleAsync(DetectionResult message, IWorkflowContext context, CancellationToken cancellationToken = default) + public override async ValueTask HandleAsync(DetectionResult message, IWorkflowContext context, CancellationToken cancellationToken = default) { if (message.spamDecision == SpamDecision.Spam) { - await context.YieldOutputAsync($"Email marked as spam: {message.Reason}", cancellationToken).ConfigureAwait(false); + await context.YieldOutputAsync($"Email marked as spam: {message.Reason}", cancellationToken); } else { @@ -284,12 +283,12 @@ internal sealed class HandleSpamExecutor() : ReflectingExecutor /// Executor that handles uncertain emails. /// -internal sealed class HandleUncertainExecutor() : ReflectingExecutor("HandleUncertainExecutor"), IMessageHandler +internal sealed class HandleUncertainExecutor() : Executor("HandleUncertainExecutor") { /// /// Simulate the handling of an uncertain spam decision. /// - public async ValueTask HandleAsync(DetectionResult message, IWorkflowContext context, CancellationToken cancellationToken = default) + public override async ValueTask HandleAsync(DetectionResult message, IWorkflowContext context, CancellationToken cancellationToken = default) { if (message.spamDecision == SpamDecision.Uncertain) { diff --git a/dotnet/samples/GettingStarted/Workflows/ConditionalEdges/03_MultiSelection/Program.cs b/dotnet/samples/GettingStarted/Workflows/ConditionalEdges/03_MultiSelection/Program.cs index cb3914fa64..15746f727e 100644 --- a/dotnet/samples/GettingStarted/Workflows/ConditionalEdges/03_MultiSelection/Program.cs +++ b/dotnet/samples/GettingStarted/Workflows/ConditionalEdges/03_MultiSelection/Program.cs @@ -6,7 +6,6 @@ using Azure.AI.OpenAI; using Azure.Identity; using Microsoft.Agents.AI; using Microsoft.Agents.AI.Workflows; -using Microsoft.Agents.AI.Workflows.Reflection; using Microsoft.Extensions.AI; namespace WorkflowMultiSelectionSample; @@ -88,7 +87,7 @@ public static class Program // Execute the workflow await using StreamingRun run = await InProcessExecution.StreamAsync(workflow, new ChatMessage(ChatRole.User, email)); await run.TrySendMessageAsync(new TurnToken(emitEvents: true)); - await foreach (WorkflowEvent evt in run.WatchStreamAsync().ConfigureAwait(false)) + await foreach (WorkflowEvent evt in run.WatchStreamAsync()) { if (evt is WorkflowOutputEvent outputEvent) { @@ -228,7 +227,7 @@ internal sealed class Email /// /// Executor that analyzes emails using an AI agent. /// -internal sealed class EmailAnalysisExecutor : ReflectingExecutor, IMessageHandler +internal sealed class EmailAnalysisExecutor : Executor { private readonly AIAgent _emailAnalysisAgent; @@ -241,7 +240,7 @@ internal sealed class EmailAnalysisExecutor : ReflectingExecutor HandleAsync(ChatMessage message, IWorkflowContext context, CancellationToken cancellationToken = default) + public override async ValueTask HandleAsync(ChatMessage message, IWorkflowContext context, CancellationToken cancellationToken = default) { // Generate a random email ID and store the email content var newEmail = new Email @@ -274,7 +273,7 @@ public sealed class EmailResponse /// /// Executor that assists with email responses using an AI agent. /// -internal sealed class EmailAssistantExecutor : ReflectingExecutor, IMessageHandler +internal sealed class EmailAssistantExecutor : Executor { private readonly AIAgent _emailAssistantAgent; @@ -287,7 +286,7 @@ internal sealed class EmailAssistantExecutor : ReflectingExecutor HandleAsync(AnalysisResult message, IWorkflowContext context, CancellationToken cancellationToken = default) + public override async ValueTask HandleAsync(AnalysisResult message, IWorkflowContext context, CancellationToken cancellationToken = default) { if (message.spamDecision == SpamDecision.Spam) { @@ -308,24 +307,24 @@ internal sealed class EmailAssistantExecutor : ReflectingExecutor /// Executor that sends emails. /// -internal sealed class SendEmailExecutor() : ReflectingExecutor("SendEmailExecutor"), IMessageHandler +internal sealed class SendEmailExecutor() : Executor("SendEmailExecutor") { /// /// Simulate the sending of an email. /// - public async ValueTask HandleAsync(EmailResponse message, IWorkflowContext context, CancellationToken cancellationToken = default) => + public override async ValueTask HandleAsync(EmailResponse message, IWorkflowContext context, CancellationToken cancellationToken = default) => await context.YieldOutputAsync($"Email sent: {message.Response}", cancellationToken); } /// /// Executor that handles spam messages. /// -internal sealed class HandleSpamExecutor() : ReflectingExecutor("HandleSpamExecutor"), IMessageHandler +internal sealed class HandleSpamExecutor() : Executor("HandleSpamExecutor") { /// /// Simulate the handling of a spam message. /// - public async ValueTask HandleAsync(AnalysisResult message, IWorkflowContext context, CancellationToken cancellationToken = default) + public override async ValueTask HandleAsync(AnalysisResult message, IWorkflowContext context, CancellationToken cancellationToken = default) { if (message.spamDecision == SpamDecision.Spam) { @@ -341,12 +340,12 @@ internal sealed class HandleSpamExecutor() : ReflectingExecutor /// Executor that handles uncertain messages. /// -internal sealed class HandleUncertainExecutor() : ReflectingExecutor("HandleUncertainExecutor"), IMessageHandler +internal sealed class HandleUncertainExecutor() : Executor("HandleUncertainExecutor") { /// /// Simulate the handling of an uncertain spam decision. /// - public async ValueTask HandleAsync(AnalysisResult message, IWorkflowContext context, CancellationToken cancellationToken = default) + public override async ValueTask HandleAsync(AnalysisResult message, IWorkflowContext context, CancellationToken cancellationToken = default) { if (message.spamDecision == SpamDecision.Uncertain) { @@ -372,7 +371,7 @@ public sealed class EmailSummary /// /// Executor that summarizes emails using an AI agent. /// -internal sealed class EmailSummaryExecutor : ReflectingExecutor, IMessageHandler +internal sealed class EmailSummaryExecutor : Executor { private readonly AIAgent _emailSummaryAgent; @@ -385,7 +384,7 @@ internal sealed class EmailSummaryExecutor : ReflectingExecutor HandleAsync(AnalysisResult message, IWorkflowContext context, CancellationToken cancellationToken = default) + public override async ValueTask HandleAsync(AnalysisResult message, IWorkflowContext context, CancellationToken cancellationToken = default) { // Read the email content from the shared states var email = await context.ReadStateAsync(message.EmailId, scopeName: EmailStateConstants.EmailStateScope, cancellationToken); @@ -408,9 +407,9 @@ internal sealed class DatabaseEvent(string message) : WorkflowEvent(message) { } /// /// Executor that handles database access. /// -internal sealed class DatabaseAccessExecutor() : ReflectingExecutor("DatabaseAccessExecutor"), IMessageHandler +internal sealed class DatabaseAccessExecutor() : Executor("DatabaseAccessExecutor") { - public async ValueTask HandleAsync(AnalysisResult message, IWorkflowContext context, CancellationToken cancellationToken = default) + public override async ValueTask HandleAsync(AnalysisResult message, IWorkflowContext context, CancellationToken cancellationToken = default) { // 1. Save the email content await context.ReadStateAsync(message.EmailId, scopeName: EmailStateConstants.EmailStateScope, cancellationToken); diff --git a/dotnet/samples/GettingStarted/Workflows/Declarative/ExecuteCode/Generated.cs b/dotnet/samples/GettingStarted/Workflows/Declarative/ExecuteCode/Generated.cs index e067140912..d1c8d45082 100644 --- a/dotnet/samples/GettingStarted/Workflows/Declarative/ExecuteCode/Generated.cs +++ b/dotnet/samples/GettingStarted/Workflows/Declarative/ExecuteCode/Generated.cs @@ -52,22 +52,22 @@ public static class TestWorkflowProvider "FOUNDRY_AGENT_RESEARCHWEATHER").ConfigureAwait(false); // Initialize variables - await context.QueueStateUpdateAsync("AgentResponse", UnassignedValue.Instance, "Local").ConfigureAwait(false); - await context.QueueStateUpdateAsync("AgentResponseText", UnassignedValue.Instance, "Local").ConfigureAwait(false); - await context.QueueStateUpdateAsync("AvailableAgents", UnassignedValue.Instance, "Local").ConfigureAwait(false); - await context.QueueStateUpdateAsync("FinalResponse", UnassignedValue.Instance, "Local").ConfigureAwait(false); - await context.QueueStateUpdateAsync("InputTask", UnassignedValue.Instance, "Local").ConfigureAwait(false); - await context.QueueStateUpdateAsync("InternalConversationId", UnassignedValue.Instance, "Local").ConfigureAwait(false); - await context.QueueStateUpdateAsync("NextSpeaker", UnassignedValue.Instance, "Local").ConfigureAwait(false); - await context.QueueStateUpdateAsync("Plan", UnassignedValue.Instance, "Local").ConfigureAwait(false); - await context.QueueStateUpdateAsync("ProgressLedgerUpdate", UnassignedValue.Instance, "Local").ConfigureAwait(false); - await context.QueueStateUpdateAsync("RestartCount", UnassignedValue.Instance, "Local").ConfigureAwait(false); - await context.QueueStateUpdateAsync("SeedTask", UnassignedValue.Instance, "Local").ConfigureAwait(false); - await context.QueueStateUpdateAsync("StallCount", UnassignedValue.Instance, "Local").ConfigureAwait(false); - await context.QueueStateUpdateAsync("TaskFacts", UnassignedValue.Instance, "Local").ConfigureAwait(false); - await context.QueueStateUpdateAsync("TaskInstructions", UnassignedValue.Instance, "Local").ConfigureAwait(false); - await context.QueueStateUpdateAsync("TeamDescription", UnassignedValue.Instance, "Local").ConfigureAwait(false); - await context.QueueStateUpdateAsync("TypedProgressLedger", UnassignedValue.Instance, "Local").ConfigureAwait(false); + await context.QueueStateUpdateAsync("AgentResponse", UnassignedValue.Instance, "Local"); + await context.QueueStateUpdateAsync("AgentResponseText", UnassignedValue.Instance, "Local"); + await context.QueueStateUpdateAsync("AvailableAgents", UnassignedValue.Instance, "Local"); + await context.QueueStateUpdateAsync("FinalResponse", UnassignedValue.Instance, "Local"); + await context.QueueStateUpdateAsync("InputTask", UnassignedValue.Instance, "Local"); + await context.QueueStateUpdateAsync("InternalConversationId", UnassignedValue.Instance, "Local"); + await context.QueueStateUpdateAsync("NextSpeaker", UnassignedValue.Instance, "Local"); + await context.QueueStateUpdateAsync("Plan", UnassignedValue.Instance, "Local"); + await context.QueueStateUpdateAsync("ProgressLedgerUpdate", UnassignedValue.Instance, "Local"); + await context.QueueStateUpdateAsync("RestartCount", UnassignedValue.Instance, "Local"); + await context.QueueStateUpdateAsync("SeedTask", UnassignedValue.Instance, "Local"); + await context.QueueStateUpdateAsync("StallCount", UnassignedValue.Instance, "Local"); + await context.QueueStateUpdateAsync("TaskFacts", UnassignedValue.Instance, "Local"); + await context.QueueStateUpdateAsync("TaskInstructions", UnassignedValue.Instance, "Local"); + await context.QueueStateUpdateAsync("TeamDescription", UnassignedValue.Instance, "Local"); + await context.QueueStateUpdateAsync("TypedProgressLedger", UnassignedValue.Instance, "Local"); } } @@ -97,8 +97,8 @@ public static class TestWorkflowProvider agentid: Env.FOUNDRY_AGENT_RESEARCHWEB } ] - """).ConfigureAwait(false); - await context.QueueStateUpdateAsync(key: "AvailableAgents", value: evaluatedValue, scopeName: "Local").ConfigureAwait(false); + """); + await context.QueueStateUpdateAsync(key: "AvailableAgents", value: evaluatedValue, scopeName: "Local"); return default; } @@ -115,8 +115,8 @@ public static class TestWorkflowProvider object? evaluatedValue = await context.EvaluateValueAsync(""" Concat(ForAll(Local.AvailableAgents, $"- " & name & $": " & description), Value, " ") - """).ConfigureAwait(false); - await context.QueueStateUpdateAsync(key: "TeamDescription", value: evaluatedValue, scopeName: "Local").ConfigureAwait(false); + """); + await context.QueueStateUpdateAsync(key: "TeamDescription", value: evaluatedValue, scopeName: "Local"); return default; } @@ -130,8 +130,8 @@ public static class TestWorkflowProvider // protected override async ValueTask ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken) { - object? evaluatedValue = await context.EvaluateValueAsync("System.LastMessage.Text").ConfigureAwait(false); - await context.QueueStateUpdateAsync(key: "InputTask", value: evaluatedValue, scopeName: "Local").ConfigureAwait(false); + object? evaluatedValue = await context.EvaluateValueAsync("System.LastMessage.Text"); + await context.QueueStateUpdateAsync(key: "InputTask", value: evaluatedValue, scopeName: "Local"); return default; } @@ -145,8 +145,8 @@ public static class TestWorkflowProvider // protected override async ValueTask ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken) { - object? evaluatedValue = await context.EvaluateValueAsync("UserMessage(Local.InputTask)").ConfigureAwait(false); - await context.QueueStateUpdateAsync(key: "SeedTask", value: evaluatedValue, scopeName: "Local").ConfigureAwait(false); + object? evaluatedValue = await context.EvaluateValueAsync("UserMessage(Local.InputTask)"); + await context.QueueStateUpdateAsync(key: "SeedTask", value: evaluatedValue, scopeName: "Local"); return default; } @@ -167,7 +167,7 @@ public static class TestWorkflowProvider """ ); AgentRunResponse response = new([new ChatMessage(ChatRole.Assistant, activityText)]); - await context.AddEventAsync(new AgentRunResponseEvent(this.Id, response)).ConfigureAwait(false); + await context.AddEventAsync(new AgentRunResponseEvent(this.Id, response)); return default; } @@ -180,8 +180,8 @@ public static class TestWorkflowProvider { protected override async ValueTask ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken) { - string conversationId = await agentProvider.CreateConversationAsync(cancellationToken).ConfigureAwait(false); - await context.QueueStateUpdateAsync(key: "InternalConversationId", value: conversationId, scopeName: "Local").ConfigureAwait(false); + string conversationId = await agentProvider.CreateConversationAsync(cancellationToken); + await context.QueueStateUpdateAsync(key: "InternalConversationId", value: conversationId, scopeName: "Local"); return default; } @@ -195,14 +195,14 @@ public static class TestWorkflowProvider // protected override async ValueTask ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken) { - string? agentName = await context.ReadStateAsync(key: "FOUNDRY_AGENT_RESEARCHANALYST", scopeName: "Env").ConfigureAwait(false); + string? agentName = await context.ReadStateAsync(key: "FOUNDRY_AGENT_RESEARCHANALYST", scopeName: "Env"); if (string.IsNullOrWhiteSpace(agentName)) { throw new InvalidOperationException($"Agent name must be defined: {this.Id}"); } - string? conversationId = await context.ReadStateAsync(key: "InternalConversationId", scopeName: "Local").ConfigureAwait(false); + string? conversationId = await context.ReadStateAsync(key: "InternalConversationId", scopeName: "Local"); bool autoSend = true; string additionalInstructions = await context.FormatTemplateAsync( @@ -226,7 +226,7 @@ public static class TestWorkflowProvider DO NOT include any other headings or sections in your response. DO NOT list next steps or plans until asked to do so. """); - IList? inputMessages = await context.EvaluateListAsync("UserMessage(Local.InputTask)").ConfigureAwait(false); + IList? inputMessages = await context.EvaluateListAsync("UserMessage(Local.InputTask)"); AgentRunResponse agentResponse = await InvokeAgentAsync( @@ -236,14 +236,14 @@ public static class TestWorkflowProvider autoSend, additionalInstructions, inputMessages, - cancellationToken).ConfigureAwait(false); + cancellationToken); if (autoSend) { - await context.AddEventAsync(new AgentRunResponseEvent(this.Id, agentResponse)).ConfigureAwait(false); + await context.AddEventAsync(new AgentRunResponseEvent(this.Id, agentResponse)); } - await context.QueueStateUpdateAsync(key: "TaskFacts", value: agentResponse.Messages, scopeName: "Local").ConfigureAwait(false); + await context.QueueStateUpdateAsync(key: "TaskFacts", value: agentResponse.Messages, scopeName: "Local"); return default; } @@ -264,7 +264,7 @@ public static class TestWorkflowProvider """ ); AgentRunResponse response = new([new ChatMessage(ChatRole.Assistant, activityText)]); - await context.AddEventAsync(new AgentRunResponseEvent(this.Id, response)).ConfigureAwait(false); + await context.AddEventAsync(new AgentRunResponseEvent(this.Id, response)); return default; } @@ -278,14 +278,14 @@ public static class TestWorkflowProvider // protected override async ValueTask ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken) { - string? agentName = await context.ReadStateAsync(key: "FOUNDRY_AGENT_RESEARCHMANAGER", scopeName: "Env").ConfigureAwait(false); + string? agentName = await context.ReadStateAsync(key: "FOUNDRY_AGENT_RESEARCHMANAGER", scopeName: "Env"); if (string.IsNullOrWhiteSpace(agentName)) { throw new InvalidOperationException($"Agent name must be defined: {this.Id}"); } - string? conversationId = await context.ReadStateAsync(key: "InternalConversationId", scopeName: "Local").ConfigureAwait(false); + string? conversationId = await context.ReadStateAsync(key: "InternalConversationId", scopeName: "Local"); bool autoSend = true; string additionalInstructions = await context.FormatTemplateAsync( @@ -300,7 +300,7 @@ public static class TestWorkflowProvider Remember, there is no requirement to involve the entire team -- only select team member's whose particular expertise is required for this task. """); - IList? inputMessages = await context.EvaluateListAsync("UserMessage(Local.InputTask)").ConfigureAwait(false); + IList? inputMessages = await context.EvaluateListAsync("UserMessage(Local.InputTask)"); AgentRunResponse agentResponse = await InvokeAgentAsync( @@ -310,14 +310,14 @@ public static class TestWorkflowProvider autoSend, additionalInstructions, inputMessages, - cancellationToken).ConfigureAwait(false); + cancellationToken); if (autoSend) { - await context.AddEventAsync(new AgentRunResponseEvent(this.Id, agentResponse)).ConfigureAwait(false); + await context.AddEventAsync(new AgentRunResponseEvent(this.Id, agentResponse)); } - await context.QueueStateUpdateAsync(key: "Plan", value: agentResponse.Messages, scopeName: "Local").ConfigureAwait(false); + await context.QueueStateUpdateAsync(key: "Plan", value: agentResponse.Messages, scopeName: "Local"); return default; } @@ -354,8 +354,8 @@ public static class TestWorkflowProvider Here is the plan to follow as best as possible: " & Last(Local.Plan).Text - """).ConfigureAwait(false); - await context.QueueStateUpdateAsync(key: "TaskInstructions", value: evaluatedValue, scopeName: "Local").ConfigureAwait(false); + """); + await context.QueueStateUpdateAsync(key: "TaskInstructions", value: evaluatedValue, scopeName: "Local"); return default; } @@ -376,7 +376,7 @@ public static class TestWorkflowProvider """ ); AgentRunResponse response = new([new ChatMessage(ChatRole.Assistant, activityText)]); - await context.AddEventAsync(new AgentRunResponseEvent(this.Id, response)).ConfigureAwait(false); + await context.AddEventAsync(new AgentRunResponseEvent(this.Id, response)); return default; } @@ -390,14 +390,14 @@ public static class TestWorkflowProvider // protected override async ValueTask ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken) { - string? agentName = await context.ReadStateAsync(key: "FOUNDRY_AGENT_RESEARCHMANAGER", scopeName: "Env").ConfigureAwait(false); + string? agentName = await context.ReadStateAsync(key: "FOUNDRY_AGENT_RESEARCHMANAGER", scopeName: "Env"); if (string.IsNullOrWhiteSpace(agentName)) { throw new InvalidOperationException($"Agent name must be defined: {this.Id}"); } - string? conversationId = await context.ReadStateAsync(key: "InternalConversationId", scopeName: "Local").ConfigureAwait(false); + string? conversationId = await context.ReadStateAsync(key: "InternalConversationId", scopeName: "Local"); bool autoSend = true; string additionalInstructions = await context.FormatTemplateAsync( @@ -443,7 +443,7 @@ public static class TestWorkflowProvider }} }} """); - IList? inputMessages = await context.EvaluateListAsync("UserMessage(Local.AgentResponseText)").ConfigureAwait(false); + IList? inputMessages = await context.EvaluateListAsync("UserMessage(Local.AgentResponseText)"); AgentRunResponse agentResponse = await InvokeAgentAsync( @@ -453,14 +453,14 @@ public static class TestWorkflowProvider autoSend, additionalInstructions, inputMessages, - cancellationToken).ConfigureAwait(false); + cancellationToken); if (autoSend) { - await context.AddEventAsync(new AgentRunResponseEvent(this.Id, agentResponse)).ConfigureAwait(false); + await context.AddEventAsync(new AgentRunResponseEvent(this.Id, agentResponse)); } - await context.QueueStateUpdateAsync(key: "ProgressLedgerUpdate", value: agentResponse.Messages, scopeName: "Local").ConfigureAwait(false); + await context.QueueStateUpdateAsync(key: "ProgressLedgerUpdate", value: agentResponse.Messages, scopeName: "Local"); return default; } @@ -496,8 +496,8 @@ public static class TestWorkflowProvider VariableType.Record( ("reason", typeof(string)), ("answer", typeof(string))))); - object? parsedValue = await context.ConvertValueAsync(targetType, "Last(Local.ProgressLedgerUpdate).Text", cancellationToken).ConfigureAwait(false); - await context.QueueStateUpdateAsync(key: "TypedProgressLedger", value: parsedValue, scopeName: "Local").ConfigureAwait(false); + object? parsedValue = await context.ConvertValueAsync(targetType, "Last(Local.ProgressLedgerUpdate).Text", cancellationToken); + await context.QueueStateUpdateAsync(key: "TypedProgressLedger", value: parsedValue, scopeName: "Local"); return default; } @@ -511,13 +511,13 @@ public static class TestWorkflowProvider // protected override async ValueTask ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken) { - bool condition0 = await context.EvaluateValueAsync("Local.TypedProgressLedger.is_request_satisfied.answer").ConfigureAwait(false); + bool condition0 = await context.EvaluateValueAsync("Local.TypedProgressLedger.is_request_satisfied.answer"); if (condition0) { return "conditionItem_fj432c"; } - bool condition1 = await context.EvaluateValueAsync("Local.TypedProgressLedger.is_in_loop.answer || Not(Local.TypedProgressLedger.is_progress_being_made.answer)").ConfigureAwait(false); + bool condition1 = await context.EvaluateValueAsync("Local.TypedProgressLedger.is_in_loop.answer || Not(Local.TypedProgressLedger.is_progress_being_made.answer)"); if (condition1) { return "conditionItem_yiqund"; @@ -542,7 +542,7 @@ public static class TestWorkflowProvider """ ); AgentRunResponse response = new([new ChatMessage(ChatRole.Assistant, activityText)]); - await context.AddEventAsync(new AgentRunResponseEvent(this.Id, response)).ConfigureAwait(false); + await context.AddEventAsync(new AgentRunResponseEvent(this.Id, response)); return default; } @@ -556,14 +556,14 @@ public static class TestWorkflowProvider // protected override async ValueTask ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken) { - string? agentName = await context.ReadStateAsync(key: "FOUNDRY_AGENT_RESEARCHMANAGER", scopeName: "Env").ConfigureAwait(false); + string? agentName = await context.ReadStateAsync(key: "FOUNDRY_AGENT_RESEARCHMANAGER", scopeName: "Env"); if (string.IsNullOrWhiteSpace(agentName)) { throw new InvalidOperationException($"Agent name must be defined: {this.Id}"); } - string? conversationId = await context.ReadStateAsync(key: "ConversationId", scopeName: "System").ConfigureAwait(false); + string? conversationId = await context.ReadStateAsync(key: "ConversationId", scopeName: "System"); bool autoSend = true; string additionalInstructions = await context.FormatTemplateAsync( @@ -572,7 +572,7 @@ public static class TestWorkflowProvider Based only on the conversation and without adding any new information, synthesize the result of the conversation as a complete response to the user task. The user will only every see this last response and not the entire conversation, so please ensure it is complete and self-contained. """); - IList? inputMessages = await context.ReadListAsync(key: "SeedTask", scopeName: "Local").ConfigureAwait(false); + IList? inputMessages = await context.ReadListAsync(key: "SeedTask", scopeName: "Local"); AgentRunResponse agentResponse = await InvokeAgentAsync( @@ -582,14 +582,14 @@ public static class TestWorkflowProvider autoSend, additionalInstructions, inputMessages, - cancellationToken).ConfigureAwait(false); + cancellationToken); if (autoSend) { - await context.AddEventAsync(new AgentRunResponseEvent(this.Id, agentResponse)).ConfigureAwait(false); + await context.AddEventAsync(new AgentRunResponseEvent(this.Id, agentResponse)); } - await context.QueueStateUpdateAsync(key: "FinalResponse", value: agentResponse.Messages, scopeName: "Local").ConfigureAwait(false); + await context.QueueStateUpdateAsync(key: "FinalResponse", value: agentResponse.Messages, scopeName: "Local"); return default; } @@ -603,8 +603,8 @@ public static class TestWorkflowProvider // protected override async ValueTask ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken) { - object? evaluatedValue = await context.EvaluateValueAsync("Local.StallCount + 1").ConfigureAwait(false); - await context.QueueStateUpdateAsync(key: "StallCount", value: evaluatedValue, scopeName: "Local").ConfigureAwait(false); + object? evaluatedValue = await context.EvaluateValueAsync("Local.StallCount + 1"); + await context.QueueStateUpdateAsync(key: "StallCount", value: evaluatedValue, scopeName: "Local"); return default; } @@ -618,13 +618,13 @@ public static class TestWorkflowProvider // protected override async ValueTask ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken) { - bool condition0 = await context.EvaluateValueAsync(".TypedProgressLedger.is_in_loop.answer").ConfigureAwait(false); + bool condition0 = await context.EvaluateValueAsync(".TypedProgressLedger.is_in_loop.answer"); if (condition0) { return "conditionItem_fpaNL9"; } - bool condition1 = await context.EvaluateValueAsync("Not(Local.TypedProgressLedger.is_progress_being_made.answer)").ConfigureAwait(false); + bool condition1 = await context.EvaluateValueAsync("Not(Local.TypedProgressLedger.is_progress_being_made.answer)"); if (condition1) { return "conditionItem_NnqvXh"; @@ -649,7 +649,7 @@ public static class TestWorkflowProvider """ ); AgentRunResponse response = new([new ChatMessage(ChatRole.Assistant, activityText)]); - await context.AddEventAsync(new AgentRunResponseEvent(this.Id, response)).ConfigureAwait(false); + await context.AddEventAsync(new AgentRunResponseEvent(this.Id, response)); return default; } @@ -670,7 +670,7 @@ public static class TestWorkflowProvider """ ); AgentRunResponse response = new([new ChatMessage(ChatRole.Assistant, activityText)]); - await context.AddEventAsync(new AgentRunResponseEvent(this.Id, response)).ConfigureAwait(false); + await context.AddEventAsync(new AgentRunResponseEvent(this.Id, response)); return default; } @@ -684,7 +684,7 @@ public static class TestWorkflowProvider // protected override async ValueTask ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken) { - bool condition0 = await context.EvaluateValueAsync("Local.StallCount > 2").ConfigureAwait(false); + bool condition0 = await context.EvaluateValueAsync("Local.StallCount > 2"); if (condition0) { return "conditionItem_NlQTBv"; @@ -709,7 +709,7 @@ public static class TestWorkflowProvider """ ); AgentRunResponse response = new([new ChatMessage(ChatRole.Assistant, activityText)]); - await context.AddEventAsync(new AgentRunResponseEvent(this.Id, response)).ConfigureAwait(false); + await context.AddEventAsync(new AgentRunResponseEvent(this.Id, response)); return default; } @@ -723,7 +723,7 @@ public static class TestWorkflowProvider // protected override async ValueTask ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken) { - bool condition0 = await context.EvaluateValueAsync("Local.RestartCount > 2").ConfigureAwait(false); + bool condition0 = await context.EvaluateValueAsync("Local.RestartCount > 2"); if (condition0) { return "conditionItem_EXAlhZ"; @@ -748,7 +748,7 @@ public static class TestWorkflowProvider """ ); AgentRunResponse response = new([new ChatMessage(ChatRole.Assistant, activityText)]); - await context.AddEventAsync(new AgentRunResponseEvent(this.Id, response)).ConfigureAwait(false); + await context.AddEventAsync(new AgentRunResponseEvent(this.Id, response)); return default; } @@ -769,7 +769,7 @@ public static class TestWorkflowProvider """ ); AgentRunResponse response = new([new ChatMessage(ChatRole.Assistant, activityText)]); - await context.AddEventAsync(new AgentRunResponseEvent(this.Id, response)).ConfigureAwait(false); + await context.AddEventAsync(new AgentRunResponseEvent(this.Id, response)); return default; } @@ -783,14 +783,14 @@ public static class TestWorkflowProvider // protected override async ValueTask ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken) { - string? agentName = await context.ReadStateAsync(key: "FOUNDRY_AGENT_RESEARCHANALYST", scopeName: "Env").ConfigureAwait(false); + string? agentName = await context.ReadStateAsync(key: "FOUNDRY_AGENT_RESEARCHANALYST", scopeName: "Env"); if (string.IsNullOrWhiteSpace(agentName)) { throw new InvalidOperationException($"Agent name must be defined: {this.Id}"); } - string? conversationId = await context.ReadStateAsync(key: "InternalConversationId", scopeName: "Local").ConfigureAwait(false); + string? conversationId = await context.ReadStateAsync(key: "InternalConversationId", scopeName: "Local"); bool autoSend = true; string additionalInstructions = await context.FormatTemplateAsync( @@ -810,7 +810,7 @@ public static class TestWorkflowProvider "As a reminder, we are working to solve the following task: " & Local.InputTask) - """).ConfigureAwait(false); + """); AgentRunResponse agentResponse = await InvokeAgentAsync( @@ -820,14 +820,14 @@ public static class TestWorkflowProvider autoSend, additionalInstructions, inputMessages, - cancellationToken).ConfigureAwait(false); + cancellationToken); if (autoSend) { - await context.AddEventAsync(new AgentRunResponseEvent(this.Id, agentResponse)).ConfigureAwait(false); + await context.AddEventAsync(new AgentRunResponseEvent(this.Id, agentResponse)); } - await context.QueueStateUpdateAsync(key: "TaskFacts", value: agentResponse.Messages, scopeName: "Local").ConfigureAwait(false); + await context.QueueStateUpdateAsync(key: "TaskFacts", value: agentResponse.Messages, scopeName: "Local"); return default; } @@ -848,7 +848,7 @@ public static class TestWorkflowProvider """ ); AgentRunResponse response = new([new ChatMessage(ChatRole.Assistant, activityText)]); - await context.AddEventAsync(new AgentRunResponseEvent(this.Id, response)).ConfigureAwait(false); + await context.AddEventAsync(new AgentRunResponseEvent(this.Id, response)); return default; } @@ -862,14 +862,14 @@ public static class TestWorkflowProvider // protected override async ValueTask ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken) { - string? agentName = await context.ReadStateAsync(key: "FOUNDRY_AGENT_RESEARCHMANAGER", scopeName: "Env").ConfigureAwait(false); + string? agentName = await context.ReadStateAsync(key: "FOUNDRY_AGENT_RESEARCHMANAGER", scopeName: "Env"); if (string.IsNullOrWhiteSpace(agentName)) { throw new InvalidOperationException($"Agent name must be defined: {this.Id}"); } - string? conversationId = await context.ReadStateAsync(key: "InternalConversationId", scopeName: "Local").ConfigureAwait(false); + string? conversationId = await context.ReadStateAsync(key: "InternalConversationId", scopeName: "Local"); bool autoSend = true; string additionalInstructions = await context.FormatTemplateAsync( @@ -891,14 +891,14 @@ public static class TestWorkflowProvider autoSend, additionalInstructions, inputMessages, - cancellationToken).ConfigureAwait(false); + cancellationToken); if (autoSend) { - await context.AddEventAsync(new AgentRunResponseEvent(this.Id, agentResponse)).ConfigureAwait(false); + await context.AddEventAsync(new AgentRunResponseEvent(this.Id, agentResponse)); } - await context.QueueStateUpdateAsync(key: "Plan", value: agentResponse.Messages, scopeName: "Local").ConfigureAwait(false); + await context.QueueStateUpdateAsync(key: "Plan", value: agentResponse.Messages, scopeName: "Local"); return default; } @@ -935,8 +935,8 @@ public static class TestWorkflowProvider Here is the plan to follow as best as possible: " & Local.Plan.Text - """).ConfigureAwait(false); - await context.QueueStateUpdateAsync(key: "TaskInstructions", value: evaluatedValue, scopeName: "Local").ConfigureAwait(false); + """); + await context.QueueStateUpdateAsync(key: "TaskInstructions", value: evaluatedValue, scopeName: "Local"); return default; } @@ -951,7 +951,7 @@ public static class TestWorkflowProvider protected override async ValueTask ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken) { object? evaluatedValue = 0; - await context.QueueStateUpdateAsync(key: "StallCount", value: evaluatedValue, scopeName: "Local").ConfigureAwait(false); + await context.QueueStateUpdateAsync(key: "StallCount", value: evaluatedValue, scopeName: "Local"); return default; } @@ -965,8 +965,8 @@ public static class TestWorkflowProvider // protected override async ValueTask ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken) { - object? evaluatedValue = await context.EvaluateValueAsync("Local.RestartCount + 1").ConfigureAwait(false); - await context.QueueStateUpdateAsync(key: "RestartCount", value: evaluatedValue, scopeName: "Local").ConfigureAwait(false); + object? evaluatedValue = await context.EvaluateValueAsync("Local.RestartCount + 1"); + await context.QueueStateUpdateAsync(key: "RestartCount", value: evaluatedValue, scopeName: "Local"); return default; } @@ -989,7 +989,7 @@ public static class TestWorkflowProvider """ ); AgentRunResponse response = new([new ChatMessage(ChatRole.Assistant, activityText)]); - await context.AddEventAsync(new AgentRunResponseEvent(this.Id, response)).ConfigureAwait(false); + await context.AddEventAsync(new AgentRunResponseEvent(this.Id, response)); return default; } @@ -1004,7 +1004,7 @@ public static class TestWorkflowProvider protected override async ValueTask ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken) { object? evaluatedValue = 0; - await context.QueueStateUpdateAsync(key: "StallCount", value: evaluatedValue, scopeName: "Local").ConfigureAwait(false); + await context.QueueStateUpdateAsync(key: "StallCount", value: evaluatedValue, scopeName: "Local"); return default; } @@ -1018,8 +1018,8 @@ public static class TestWorkflowProvider // protected override async ValueTask ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken) { - object? evaluatedValue = await context.EvaluateValueAsync("Search(Local.AvailableAgents, Local.TypedProgressLedger.next_speaker.answer, name)").ConfigureAwait(false); - await context.QueueStateUpdateAsync(key: "NextSpeaker", value: evaluatedValue, scopeName: "Local").ConfigureAwait(false); + object? evaluatedValue = await context.EvaluateValueAsync("Search(Local.AvailableAgents, Local.TypedProgressLedger.next_speaker.answer, name)"); + await context.QueueStateUpdateAsync(key: "NextSpeaker", value: evaluatedValue, scopeName: "Local"); return default; } @@ -1033,7 +1033,7 @@ public static class TestWorkflowProvider // protected override async ValueTask ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken) { - bool condition0 = await context.EvaluateValueAsync("CountRows(Local.NextSpeaker) = 1").ConfigureAwait(false); + bool condition0 = await context.EvaluateValueAsync("CountRows(Local.NextSpeaker) = 1"); if (condition0) { return "conditionItem_GmigcU"; @@ -1051,21 +1051,21 @@ public static class TestWorkflowProvider // protected override async ValueTask ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken) { - string? agentName = await context.EvaluateValueAsync("First(Local.NextSpeaker).agentid").ConfigureAwait(false); + string? agentName = await context.EvaluateValueAsync("First(Local.NextSpeaker).agentid"); if (string.IsNullOrWhiteSpace(agentName)) { throw new InvalidOperationException($"Agent name must be defined: {this.Id}"); } - string? conversationId = await context.ReadStateAsync(key: "ConversationId", scopeName: "System").ConfigureAwait(false); + string? conversationId = await context.ReadStateAsync(key: "ConversationId", scopeName: "System"); bool autoSend = true; string additionalInstructions = await context.FormatTemplateAsync( """ {Local.TypedProgressLedger.instruction_or_question.answer} """); - IList? inputMessages = await context.ReadListAsync(key: "SeedTask", scopeName: "Local").ConfigureAwait(false); + IList? inputMessages = await context.ReadListAsync(key: "SeedTask", scopeName: "Local"); AgentRunResponse agentResponse = await InvokeAgentAsync( @@ -1075,14 +1075,14 @@ public static class TestWorkflowProvider autoSend, additionalInstructions, inputMessages, - cancellationToken).ConfigureAwait(false); + cancellationToken); if (autoSend) { - await context.AddEventAsync(new AgentRunResponseEvent(this.Id, agentResponse)).ConfigureAwait(false); + await context.AddEventAsync(new AgentRunResponseEvent(this.Id, agentResponse)); } - await context.QueueStateUpdateAsync(key: "AgentResponse", value: agentResponse.Messages, scopeName: "Local").ConfigureAwait(false); + await context.QueueStateUpdateAsync(key: "AgentResponse", value: agentResponse.Messages, scopeName: "Local"); return default; } @@ -1096,8 +1096,8 @@ public static class TestWorkflowProvider // protected override async ValueTask ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken) { - object? evaluatedValue = await context.EvaluateValueAsync("Last(Local.AgentResponse).Text").ConfigureAwait(false); - await context.QueueStateUpdateAsync(key: "AgentResponseText", value: evaluatedValue, scopeName: "Local").ConfigureAwait(false); + object? evaluatedValue = await context.EvaluateValueAsync("Last(Local.AgentResponse).Text"); + await context.QueueStateUpdateAsync(key: "AgentResponseText", value: evaluatedValue, scopeName: "Local"); return default; } @@ -1111,7 +1111,7 @@ public static class TestWorkflowProvider { protected override async ValueTask ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken) { - await context.QueueStateUpdateAsync(key: "SeedTask", value: UnassignedValue.Instance, scopeName: "Local").ConfigureAwait(false); + await context.QueueStateUpdateAsync(key: "SeedTask", value: UnassignedValue.Instance, scopeName: "Local"); return default; } @@ -1132,7 +1132,7 @@ public static class TestWorkflowProvider """ ); AgentRunResponse response = new([new ChatMessage(ChatRole.Assistant, activityText)]); - await context.AddEventAsync(new AgentRunResponseEvent(this.Id, response)).ConfigureAwait(false); + await context.AddEventAsync(new AgentRunResponseEvent(this.Id, response)); return default; } @@ -1146,8 +1146,8 @@ public static class TestWorkflowProvider // protected override async ValueTask ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken) { - object? evaluatedValue = await context.EvaluateValueAsync("Local.StallCount + 1").ConfigureAwait(false); - await context.QueueStateUpdateAsync(key: "StallCount", value: evaluatedValue, scopeName: "Local").ConfigureAwait(false); + object? evaluatedValue = await context.EvaluateValueAsync("Local.StallCount + 1"); + await context.QueueStateUpdateAsync(key: "StallCount", value: evaluatedValue, scopeName: "Local"); return default; } diff --git a/dotnet/samples/GettingStarted/Workflows/Declarative/ExecuteCode/Program.cs b/dotnet/samples/GettingStarted/Workflows/Declarative/ExecuteCode/Program.cs index e7072c69c1..7837194d32 100644 --- a/dotnet/samples/GettingStarted/Workflows/Declarative/ExecuteCode/Program.cs +++ b/dotnet/samples/GettingStarted/Workflows/Declarative/ExecuteCode/Program.cs @@ -76,7 +76,7 @@ internal sealed class Program string? messageId = null; - await foreach (WorkflowEvent workflowEvent in run.WatchStreamAsync().ConfigureAwait(false)) + await foreach (WorkflowEvent workflowEvent in run.WatchStreamAsync()) { switch (workflowEvent) { diff --git a/dotnet/samples/GettingStarted/Workflows/Declarative/ExecuteWorkflow/Program.cs b/dotnet/samples/GettingStarted/Workflows/Declarative/ExecuteWorkflow/Program.cs index d0a5f6275f..67f463b1c6 100644 --- a/dotnet/samples/GettingStarted/Workflows/Declarative/ExecuteWorkflow/Program.cs +++ b/dotnet/samples/GettingStarted/Workflows/Declarative/ExecuteWorkflow/Program.cs @@ -150,7 +150,7 @@ internal sealed class Program string? messageId = null; - await foreach (WorkflowEvent workflowEvent in run.Run.WatchStreamAsync().ConfigureAwait(false)) + await foreach (WorkflowEvent workflowEvent in run.Run.WatchStreamAsync()) { switch (workflowEvent) { @@ -187,12 +187,12 @@ internal sealed class Program if (response is not null) { ExternalResponse requestResponse = requestInfo.Request.CreateResponse(response); - await run.Run.SendResponseAsync(requestResponse).ConfigureAwait(false); + await run.Run.SendResponseAsync(requestResponse); response = null; } else { - await run.Run.DisposeAsync().ConfigureAwait(false); + await run.Run.DisposeAsync(); return requestInfo.Request; } break; diff --git a/dotnet/samples/GettingStarted/Workflows/HumanInTheLoop/HumanInTheLoopBasic/Program.cs b/dotnet/samples/GettingStarted/Workflows/HumanInTheLoop/HumanInTheLoopBasic/Program.cs index e3628b11e5..62f1925fb3 100644 --- a/dotnet/samples/GettingStarted/Workflows/HumanInTheLoop/HumanInTheLoopBasic/Program.cs +++ b/dotnet/samples/GettingStarted/Workflows/HumanInTheLoop/HumanInTheLoopBasic/Program.cs @@ -24,18 +24,18 @@ public static class Program private static async Task Main() { // Create the workflow - var workflow = await WorkflowHelper.GetWorkflowAsync().ConfigureAwait(false); + var workflow = await WorkflowHelper.GetWorkflowAsync(); // Execute the workflow - await using StreamingRun handle = await InProcessExecution.StreamAsync(workflow, NumberSignal.Init).ConfigureAwait(false); - await foreach (WorkflowEvent evt in handle.WatchStreamAsync().ConfigureAwait(false)) + await using StreamingRun handle = await InProcessExecution.StreamAsync(workflow, NumberSignal.Init); + await foreach (WorkflowEvent evt in handle.WatchStreamAsync()) { switch (evt) { case RequestInfoEvent requestInputEvt: // Handle `RequestInfoEvent` from the workflow ExternalResponse response = HandleExternalRequest(requestInputEvt.Request); - await handle.SendResponseAsync(response).ConfigureAwait(false); + await handle.SendResponseAsync(response); break; case WorkflowOutputEvent outputEvt: diff --git a/dotnet/samples/GettingStarted/Workflows/HumanInTheLoop/HumanInTheLoopBasic/WorkflowHelper.cs b/dotnet/samples/GettingStarted/Workflows/HumanInTheLoop/HumanInTheLoopBasic/WorkflowHelper.cs index 5fcc6cf765..c87ddc00cb 100644 --- a/dotnet/samples/GettingStarted/Workflows/HumanInTheLoop/HumanInTheLoopBasic/WorkflowHelper.cs +++ b/dotnet/samples/GettingStarted/Workflows/HumanInTheLoop/HumanInTheLoopBasic/WorkflowHelper.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft. All rights reserved. using Microsoft.Agents.AI.Workflows; -using Microsoft.Agents.AI.Workflows.Reflection; namespace WorkflowHumanInTheLoopBasicSample; @@ -39,7 +38,7 @@ internal enum NumberSignal /// /// Executor that judges the guess and provides feedback. /// -internal sealed class JudgeExecutor() : ReflectingExecutor("Judge"), IMessageHandler +internal sealed class JudgeExecutor() : Executor("Judge") { private readonly int _targetNumber; private int _tries; @@ -53,21 +52,20 @@ internal sealed class JudgeExecutor() : ReflectingExecutor("Judge this._targetNumber = targetNumber; } - public async ValueTask HandleAsync(int message, IWorkflowContext context, CancellationToken cancellationToken = default) + public override async ValueTask HandleAsync(int message, IWorkflowContext context, CancellationToken cancellationToken = default) { this._tries++; if (message == this._targetNumber) { - await context.YieldOutputAsync($"{this._targetNumber} found in {this._tries} tries!", cancellationToken) - .ConfigureAwait(false); + await context.YieldOutputAsync($"{this._targetNumber} found in {this._tries} tries!", cancellationToken); } else if (message < this._targetNumber) { - await context.SendMessageAsync(NumberSignal.Below, cancellationToken: cancellationToken).ConfigureAwait(false); + await context.SendMessageAsync(NumberSignal.Below, cancellationToken: cancellationToken); } else { - await context.SendMessageAsync(NumberSignal.Above, cancellationToken: cancellationToken).ConfigureAwait(false); + await context.SendMessageAsync(NumberSignal.Above, cancellationToken: cancellationToken); } } } diff --git a/dotnet/samples/GettingStarted/Workflows/Loop/Program.cs b/dotnet/samples/GettingStarted/Workflows/Loop/Program.cs index a5f4168767..15d930216f 100644 --- a/dotnet/samples/GettingStarted/Workflows/Loop/Program.cs +++ b/dotnet/samples/GettingStarted/Workflows/Loop/Program.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft. All rights reserved. using Microsoft.Agents.AI.Workflows; -using Microsoft.Agents.AI.Workflows.Reflection; namespace WorkflowLoopSample; @@ -33,8 +32,8 @@ public static class Program .BuildAsync(); // Execute the workflow - await using StreamingRun run = await InProcessExecution.StreamAsync(workflow, NumberSignal.Init).ConfigureAwait(false); - await foreach (WorkflowEvent evt in run.WatchStreamAsync().ConfigureAwait(false)) + await using StreamingRun run = await InProcessExecution.StreamAsync(workflow, NumberSignal.Init); + await foreach (WorkflowEvent evt in run.WatchStreamAsync()) { if (evt is WorkflowOutputEvent outputEvent) { @@ -57,7 +56,7 @@ internal enum NumberSignal /// /// Executor that makes a guess based on the current bounds. /// -internal sealed class GuessNumberExecutor : ReflectingExecutor, IMessageHandler +internal sealed class GuessNumberExecutor : Executor { /// /// The lower bound of the guessing range. @@ -83,20 +82,20 @@ internal sealed class GuessNumberExecutor : ReflectingExecutor (this.LowerBound + this.UpperBound) / 2; - public async ValueTask HandleAsync(NumberSignal message, IWorkflowContext context, CancellationToken cancellationToken = default) + public override async ValueTask HandleAsync(NumberSignal message, IWorkflowContext context, CancellationToken cancellationToken = default) { switch (message) { case NumberSignal.Init: - await context.SendMessageAsync(this.NextGuess, cancellationToken: cancellationToken).ConfigureAwait(false); + await context.SendMessageAsync(this.NextGuess, cancellationToken: cancellationToken); break; case NumberSignal.Above: this.UpperBound = this.NextGuess - 1; - await context.SendMessageAsync(this.NextGuess, cancellationToken: cancellationToken).ConfigureAwait(false); + await context.SendMessageAsync(this.NextGuess, cancellationToken: cancellationToken); break; case NumberSignal.Below: this.LowerBound = this.NextGuess + 1; - await context.SendMessageAsync(this.NextGuess, cancellationToken: cancellationToken).ConfigureAwait(false); + await context.SendMessageAsync(this.NextGuess, cancellationToken: cancellationToken); break; } } @@ -105,7 +104,7 @@ internal sealed class GuessNumberExecutor : ReflectingExecutor /// Executor that judges the guess and provides feedback. /// -internal sealed class JudgeExecutor : ReflectingExecutor, IMessageHandler +internal sealed class JudgeExecutor : Executor { private readonly int _targetNumber; private int _tries; @@ -120,21 +119,21 @@ internal sealed class JudgeExecutor : ReflectingExecutor, IMessag this._targetNumber = targetNumber; } - public async ValueTask HandleAsync(int message, IWorkflowContext context, CancellationToken cancellationToken = default) + public override async ValueTask HandleAsync(int message, IWorkflowContext context, CancellationToken cancellationToken = default) { this._tries++; if (message == this._targetNumber) { await context.YieldOutputAsync($"{this._targetNumber} found in {this._tries} tries!", cancellationToken) - .ConfigureAwait(false); + ; } else if (message < this._targetNumber) { - await context.SendMessageAsync(NumberSignal.Below, cancellationToken: cancellationToken).ConfigureAwait(false); + await context.SendMessageAsync(NumberSignal.Below, cancellationToken: cancellationToken); } else { - await context.SendMessageAsync(NumberSignal.Above, cancellationToken: cancellationToken).ConfigureAwait(false); + await context.SendMessageAsync(NumberSignal.Above, cancellationToken: cancellationToken); } } } diff --git a/dotnet/samples/GettingStarted/Workflows/Observability/ApplicationInsights/Program.cs b/dotnet/samples/GettingStarted/Workflows/Observability/ApplicationInsights/Program.cs index 6c3debd003..f7894f707a 100644 --- a/dotnet/samples/GettingStarted/Workflows/Observability/ApplicationInsights/Program.cs +++ b/dotnet/samples/GettingStarted/Workflows/Observability/ApplicationInsights/Program.cs @@ -3,7 +3,6 @@ using System.Diagnostics; using Azure.Monitor.OpenTelemetry.Exporter; using Microsoft.Agents.AI.Workflows; -using Microsoft.Agents.AI.Workflows.Reflection; using OpenTelemetry; using OpenTelemetry.Resources; using OpenTelemetry.Trace; @@ -69,7 +68,7 @@ public static class Program /// /// First executor: converts input text to uppercase. /// -internal sealed class UppercaseExecutor() : ReflectingExecutor("UppercaseExecutor"), IMessageHandler +internal sealed class UppercaseExecutor() : Executor("UppercaseExecutor") { /// /// Processes the input message by converting it to uppercase. @@ -79,14 +78,14 @@ internal sealed class UppercaseExecutor() : ReflectingExecutorThe to monitor for cancellation requests. /// The default is . /// The input text converted to uppercase - public async ValueTask HandleAsync(string message, IWorkflowContext context, CancellationToken cancellationToken = default) => + public override async ValueTask HandleAsync(string message, IWorkflowContext context, CancellationToken cancellationToken = default) => message.ToUpperInvariant(); // The return value will be sent as a message along an edge to subsequent executors } /// /// Second executor: reverses the input text and completes the workflow. /// -internal sealed class ReverseTextExecutor() : ReflectingExecutor("ReverseTextExecutor"), IMessageHandler +internal sealed class ReverseTextExecutor() : Executor("ReverseTextExecutor") { /// /// Processes the input message by reversing the text. @@ -96,6 +95,6 @@ internal sealed class ReverseTextExecutor() : ReflectingExecutorThe to monitor for cancellation requests. /// The default is . /// The input text reversed - public async ValueTask HandleAsync(string message, IWorkflowContext context, CancellationToken cancellationToken = default) + public override async ValueTask HandleAsync(string message, IWorkflowContext context, CancellationToken cancellationToken = default) => new(message.Reverse().ToArray()); } diff --git a/dotnet/samples/GettingStarted/Workflows/Observability/AspireDashboard/Program.cs b/dotnet/samples/GettingStarted/Workflows/Observability/AspireDashboard/Program.cs index ddd88e7709..c04a397c55 100644 --- a/dotnet/samples/GettingStarted/Workflows/Observability/AspireDashboard/Program.cs +++ b/dotnet/samples/GettingStarted/Workflows/Observability/AspireDashboard/Program.cs @@ -2,7 +2,6 @@ using System.Diagnostics; using Microsoft.Agents.AI.Workflows; -using Microsoft.Agents.AI.Workflows.Reflection; using OpenTelemetry; using OpenTelemetry.Logs; using OpenTelemetry.Metrics; @@ -71,7 +70,7 @@ public static class Program /// /// First executor: converts input text to uppercase. /// -internal sealed class UppercaseExecutor() : ReflectingExecutor("UppercaseExecutor"), IMessageHandler +internal sealed class UppercaseExecutor() : Executor("UppercaseExecutor") { /// /// Processes the input message by converting it to uppercase. @@ -81,14 +80,14 @@ internal sealed class UppercaseExecutor() : ReflectingExecutorThe to monitor for cancellation requests. /// The default is . /// The input text converted to uppercase - public async ValueTask HandleAsync(string message, IWorkflowContext context, CancellationToken cancellationToken = default) => + public override async ValueTask HandleAsync(string message, IWorkflowContext context, CancellationToken cancellationToken = default) => message.ToUpperInvariant(); // The return value will be sent as a message along an edge to subsequent executors } /// /// Second executor: reverses the input text and completes the workflow. /// -internal sealed class ReverseTextExecutor() : ReflectingExecutor("ReverseTextExecutor"), IMessageHandler +internal sealed class ReverseTextExecutor() : Executor("ReverseTextExecutor") { /// /// Processes the input message by reversing the text. @@ -98,6 +97,6 @@ internal sealed class ReverseTextExecutor() : ReflectingExecutorThe to monitor for cancellation requests. /// The default is . /// The input text reversed - public async ValueTask HandleAsync(string message, IWorkflowContext context, CancellationToken cancellationToken = default) + public override async ValueTask HandleAsync(string message, IWorkflowContext context, CancellationToken cancellationToken = default) => new(message.Reverse().ToArray()); } diff --git a/dotnet/samples/GettingStarted/Workflows/SharedStates/Program.cs b/dotnet/samples/GettingStarted/Workflows/SharedStates/Program.cs index 246bb776c9..6f4cfdf38b 100644 --- a/dotnet/samples/GettingStarted/Workflows/SharedStates/Program.cs +++ b/dotnet/samples/GettingStarted/Workflows/SharedStates/Program.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft. All rights reserved. using Microsoft.Agents.AI.Workflows; -using Microsoft.Agents.AI.Workflows.Reflection; namespace WorkflowSharedStatesSample; @@ -52,9 +51,9 @@ internal static class FileContentStateConstants public const string FileContentStateScope = "FileContentState"; } -internal sealed class FileReadExecutor() : ReflectingExecutor("FileReadExecutor"), IMessageHandler +internal sealed class FileReadExecutor() : Executor("FileReadExecutor") { - public async ValueTask HandleAsync(string message, IWorkflowContext context, CancellationToken cancellationToken = default) + public override async ValueTask HandleAsync(string message, IWorkflowContext context, CancellationToken cancellationToken = default) { // Read file content from embedded resource string fileContent = Resources.Read(message); @@ -72,9 +71,9 @@ internal sealed class FileStats public int WordCount { get; set; } } -internal sealed class WordCountingExecutor() : ReflectingExecutor("WordCountingExecutor"), IMessageHandler +internal sealed class WordCountingExecutor() : Executor("WordCountingExecutor") { - public async ValueTask HandleAsync(string message, IWorkflowContext context, CancellationToken cancellationToken = default) + public override async ValueTask HandleAsync(string message, IWorkflowContext context, CancellationToken cancellationToken = default) { // Retrieve the file content from the shared state var fileContent = await context.ReadStateAsync(message, scopeName: FileContentStateConstants.FileContentStateScope, cancellationToken) @@ -86,10 +85,9 @@ internal sealed class WordCountingExecutor() : ReflectingExecutor("ParagraphCountingExecutor"), - IMessageHandler +internal sealed class ParagraphCountingExecutor() : Executor("ParagraphCountingExecutor") { - public async ValueTask HandleAsync(string message, IWorkflowContext context, CancellationToken cancellationToken = default) + public override async ValueTask HandleAsync(string message, IWorkflowContext context, CancellationToken cancellationToken = default) { // Retrieve the file content from the shared state var fileContent = await context.ReadStateAsync(message, scopeName: FileContentStateConstants.FileContentStateScope, cancellationToken) @@ -101,11 +99,11 @@ internal sealed class ParagraphCountingExecutor() : ReflectingExecutor("AggregationExecutor"), IMessageHandler +internal sealed class AggregationExecutor() : Executor("AggregationExecutor") { private readonly List _messages = []; - public async ValueTask HandleAsync(FileStats message, IWorkflowContext context, CancellationToken cancellationToken = default) + public override async ValueTask HandleAsync(FileStats message, IWorkflowContext context, CancellationToken cancellationToken = default) { this._messages.Add(message); diff --git a/dotnet/samples/GettingStarted/Workflows/_Foundational/01_ExecutorsAndEdges/Program.cs b/dotnet/samples/GettingStarted/Workflows/_Foundational/01_ExecutorsAndEdges/Program.cs index ba70329383..68e2effd04 100644 --- a/dotnet/samples/GettingStarted/Workflows/_Foundational/01_ExecutorsAndEdges/Program.cs +++ b/dotnet/samples/GettingStarted/Workflows/_Foundational/01_ExecutorsAndEdges/Program.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft. All rights reserved. using Microsoft.Agents.AI.Workflows; -using Microsoft.Agents.AI.Workflows.Reflection; namespace WorkflowExecutorsAndEdgesSample; @@ -44,7 +43,7 @@ public static class Program /// /// First executor: converts input text to uppercase. /// -internal sealed class UppercaseExecutor() : ReflectingExecutor("UppercaseExecutor"), IMessageHandler +internal sealed class UppercaseExecutor() : Executor("UppercaseExecutor") { /// /// Processes the input message by converting it to uppercase. @@ -54,14 +53,14 @@ internal sealed class UppercaseExecutor() : ReflectingExecutorThe to monitor for cancellation requests. /// The default is . /// The input text converted to uppercase - public async ValueTask HandleAsync(string message, IWorkflowContext context, CancellationToken cancellationToken = default) => - message.ToUpperInvariant(); // The return value will be sent as a message along an edge to subsequent executors + public override ValueTask HandleAsync(string message, IWorkflowContext context, CancellationToken cancellationToken = default) => + ValueTask.FromResult(message.ToUpperInvariant()); // The return value will be sent as a message along an edge to subsequent executors } /// /// Second executor: reverses the input text and completes the workflow. /// -internal sealed class ReverseTextExecutor() : ReflectingExecutor("ReverseTextExecutor"), IMessageHandler +internal sealed class ReverseTextExecutor() : Executor("ReverseTextExecutor") { /// /// Processes the input message by reversing the text. @@ -71,9 +70,9 @@ internal sealed class ReverseTextExecutor() : ReflectingExecutorThe to monitor for cancellation requests. /// The default is . /// The input text reversed - public async ValueTask HandleAsync(string message, IWorkflowContext context, CancellationToken cancellationToken = default) + public override ValueTask HandleAsync(string message, IWorkflowContext context, CancellationToken cancellationToken = default) { // Because we do not suppress it, the returned result will be yielded as an output from this executor. - return string.Concat(message.Reverse()); + return ValueTask.FromResult(string.Concat(message.Reverse())); } } diff --git a/dotnet/samples/GettingStarted/Workflows/_Foundational/02_Streaming/Program.cs b/dotnet/samples/GettingStarted/Workflows/_Foundational/02_Streaming/Program.cs index 5ffd64aedb..021f191a5e 100644 --- a/dotnet/samples/GettingStarted/Workflows/_Foundational/02_Streaming/Program.cs +++ b/dotnet/samples/GettingStarted/Workflows/_Foundational/02_Streaming/Program.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft. All rights reserved. using Microsoft.Agents.AI.Workflows; -using Microsoft.Agents.AI.Workflows.Reflection; namespace WorkflowStreamingSample; @@ -30,7 +29,7 @@ public static class Program // Execute the workflow in streaming mode await using StreamingRun run = await InProcessExecution.StreamAsync(workflow, "Hello, World!"); - await foreach (WorkflowEvent evt in run.WatchStreamAsync().ConfigureAwait(false)) + await foreach (WorkflowEvent evt in run.WatchStreamAsync()) { if (evt is ExecutorCompletedEvent executorCompleted) { @@ -43,7 +42,7 @@ public static class Program /// /// First executor: converts input text to uppercase. /// -internal sealed class UppercaseExecutor() : ReflectingExecutor("UppercaseExecutor"), IMessageHandler +internal sealed class UppercaseExecutor() : Executor("UppercaseExecutor") { /// /// Processes the input message by converting it to uppercase. @@ -53,14 +52,14 @@ internal sealed class UppercaseExecutor() : ReflectingExecutorThe to monitor for cancellation requests. /// The default is . /// The input text converted to uppercase - public async ValueTask HandleAsync(string message, IWorkflowContext context, CancellationToken cancellationToken = default) => - message.ToUpperInvariant(); // The return value will be sent as a message along an edge to subsequent executors + public override ValueTask HandleAsync(string message, IWorkflowContext context, CancellationToken cancellationToken = default) => + ValueTask.FromResult(message.ToUpperInvariant()); // The return value will be sent as a message along an edge to subsequent executors } /// /// Second executor: reverses the input text and completes the workflow. /// -internal sealed class ReverseTextExecutor() : ReflectingExecutor("ReverseTextExecutor"), IMessageHandler +internal sealed class ReverseTextExecutor() : Executor("ReverseTextExecutor") { /// /// Processes the input message by reversing the text. @@ -70,9 +69,9 @@ internal sealed class ReverseTextExecutor() : ReflectingExecutorThe to monitor for cancellation requests. /// The default is . /// The input text reversed - public async ValueTask HandleAsync(string message, IWorkflowContext context, CancellationToken cancellationToken) + public override ValueTask HandleAsync(string message, IWorkflowContext context, CancellationToken cancellationToken = default) { // Because we do not suppress it, the returned result will be yielded as an output from this executor. - return string.Concat(message.Reverse()); + return ValueTask.FromResult(string.Concat(message.Reverse())); } } diff --git a/dotnet/samples/GettingStarted/Workflows/_Foundational/03_AgentsInWorkflows/Program.cs b/dotnet/samples/GettingStarted/Workflows/_Foundational/03_AgentsInWorkflows/Program.cs index 2b30f3f5a1..0a8ee0d6ee 100644 --- a/dotnet/samples/GettingStarted/Workflows/_Foundational/03_AgentsInWorkflows/Program.cs +++ b/dotnet/samples/GettingStarted/Workflows/_Foundational/03_AgentsInWorkflows/Program.cs @@ -50,7 +50,7 @@ public static class Program // The agents are wrapped as executors. When they receive messages, // they will cache the messages and only start processing when they receive a TurnToken. await run.TrySendMessageAsync(new TurnToken(emitEvents: true)); - await foreach (WorkflowEvent evt in run.WatchStreamAsync().ConfigureAwait(false)) + await foreach (WorkflowEvent evt in run.WatchStreamAsync()) { if (evt is AgentRunUpdateEvent executorComplete) { diff --git a/dotnet/samples/GettingStarted/Workflows/_Foundational/04_AgentWorkflowPatterns/Program.cs b/dotnet/samples/GettingStarted/Workflows/_Foundational/04_AgentWorkflowPatterns/Program.cs index aeb06cfb64..dc72f3c15c 100644 --- a/dotnet/samples/GettingStarted/Workflows/_Foundational/04_AgentWorkflowPatterns/Program.cs +++ b/dotnet/samples/GettingStarted/Workflows/_Foundational/04_AgentWorkflowPatterns/Program.cs @@ -86,7 +86,7 @@ public static class Program await using StreamingRun run = await InProcessExecution.StreamAsync(workflow, messages); await run.TrySendMessageAsync(new TurnToken(emitEvents: true)); - await foreach (WorkflowEvent evt in run.WatchStreamAsync().ConfigureAwait(false)) + await foreach (WorkflowEvent evt in run.WatchStreamAsync()) { if (evt is AgentRunUpdateEvent e) { diff --git a/dotnet/samples/GettingStarted/Workflows/_Foundational/05_MultiModelService/Program.cs b/dotnet/samples/GettingStarted/Workflows/_Foundational/05_MultiModelService/Program.cs index caa78430c1..4ca7289439 100644 --- a/dotnet/samples/GettingStarted/Workflows/_Foundational/05_MultiModelService/Program.cs +++ b/dotnet/samples/GettingStarted/Workflows/_Foundational/05_MultiModelService/Program.cs @@ -58,8 +58,7 @@ AIAgent reporter = new ChatClientAgent(anthropic, // Build a sequential workflow: Researcher -> Fact-Checker -> Reporter AIAgent workflowAgent = await AgentWorkflowBuilder.BuildSequential(researcher, factChecker, reporter) - .AsAgentAsync() - .ConfigureAwait(false); + .AsAgentAsync(); // Run the workflow, streaming the output as it arrives. string? lastAuthor = null;