diff --git a/dotnet/samples/03-workflows/Agents/WorkflowAsAnAgent/WorkflowFactory.cs b/dotnet/samples/03-workflows/Agents/WorkflowAsAnAgent/WorkflowFactory.cs index 669b9ac87c..2fdfe703bf 100644 --- a/dotnet/samples/03-workflows/Agents/WorkflowAsAnAgent/WorkflowFactory.cs +++ b/dotnet/samples/03-workflows/Agents/WorkflowAsAnAgent/WorkflowFactory.cs @@ -41,6 +41,7 @@ internal static class WorkflowFactory /// /// Executor that aggregates the results from the concurrent agents. /// + [YieldsOutput(typeof(string))] private sealed class ConcurrentAggregationExecutor() : Executor>("ConcurrentAggregationExecutor"), IResettableExecutor { diff --git a/dotnet/samples/03-workflows/Checkpoint/CheckpointAndRehydrate/WorkflowFactory.cs b/dotnet/samples/03-workflows/Checkpoint/CheckpointAndRehydrate/WorkflowFactory.cs index 5c55293708..49fb4648c3 100644 --- a/dotnet/samples/03-workflows/Checkpoint/CheckpointAndRehydrate/WorkflowFactory.cs +++ b/dotnet/samples/03-workflows/Checkpoint/CheckpointAndRehydrate/WorkflowFactory.cs @@ -41,6 +41,7 @@ internal enum NumberSignal /// /// Executor that makes a guess based on the current bounds. /// +[SendsMessage(typeof(int))] internal sealed class GuessNumberExecutor() : Executor("Guess") { /// @@ -104,6 +105,8 @@ internal sealed class GuessNumberExecutor() : Executor("Guess") /// /// Executor that judges the guess and provides feedback. /// +[SendsMessage(typeof(NumberSignal))] +[YieldsOutput(typeof(string))] internal sealed class JudgeExecutor() : Executor("Judge") { private readonly int _targetNumber; diff --git a/dotnet/samples/03-workflows/Checkpoint/CheckpointAndResume/WorkflowFactory.cs b/dotnet/samples/03-workflows/Checkpoint/CheckpointAndResume/WorkflowFactory.cs index aa8b3fd192..60269f6129 100644 --- a/dotnet/samples/03-workflows/Checkpoint/CheckpointAndResume/WorkflowFactory.cs +++ b/dotnet/samples/03-workflows/Checkpoint/CheckpointAndResume/WorkflowFactory.cs @@ -41,6 +41,7 @@ internal enum NumberSignal /// /// Executor that makes a guess based on the current bounds. /// +[SendsMessage(typeof(int))] internal sealed class GuessNumberExecutor() : Executor("Guess") { /// @@ -104,6 +105,8 @@ internal sealed class GuessNumberExecutor() : Executor("Guess") /// /// Executor that judges the guess and provides feedback. /// +[SendsMessage(typeof(NumberSignal))] +[YieldsOutput(typeof(string))] internal sealed class JudgeExecutor() : Executor("Judge") { private readonly int _targetNumber; diff --git a/dotnet/samples/03-workflows/Checkpoint/CheckpointWithHumanInTheLoop/WorkflowFactory.cs b/dotnet/samples/03-workflows/Checkpoint/CheckpointWithHumanInTheLoop/WorkflowFactory.cs index df79a1ee61..8fc1a05236 100644 --- a/dotnet/samples/03-workflows/Checkpoint/CheckpointWithHumanInTheLoop/WorkflowFactory.cs +++ b/dotnet/samples/03-workflows/Checkpoint/CheckpointWithHumanInTheLoop/WorkflowFactory.cs @@ -53,6 +53,8 @@ internal sealed class SignalWithNumber /// /// Executor that judges the guess and provides feedback. /// +[SendsMessage(typeof(SignalWithNumber))] +[YieldsOutput(typeof(string))] internal sealed class JudgeExecutor() : Executor("Judge") { private readonly int _targetNumber; diff --git a/dotnet/samples/03-workflows/Concurrent/Concurrent/Program.cs b/dotnet/samples/03-workflows/Concurrent/Concurrent/Program.cs index 8ed879c685..57b650ce82 100644 --- a/dotnet/samples/03-workflows/Concurrent/Concurrent/Program.cs +++ b/dotnet/samples/03-workflows/Concurrent/Concurrent/Program.cs @@ -72,6 +72,8 @@ public static class Program /// /// Executor that starts the concurrent processing by sending messages to the agents. /// +[SendsMessage(typeof(ChatMessage))] +[SendsMessage(typeof(TurnToken))] internal sealed partial class ConcurrentStartExecutor() : Executor("ConcurrentStartExecutor") { @@ -97,7 +99,8 @@ internal sealed partial class ConcurrentStartExecutor() : /// /// Executor that aggregates the results from the concurrent agents. /// -internal sealed class ConcurrentAggregationExecutor() : +[YieldsOutput(typeof(string))] +internal sealed partial class ConcurrentAggregationExecutor() : Executor>("ConcurrentAggregationExecutor") { private readonly List _messages = []; diff --git a/dotnet/samples/03-workflows/Concurrent/MapReduce/Program.cs b/dotnet/samples/03-workflows/Concurrent/MapReduce/Program.cs index 81fbb6b28a..9049bde982 100644 --- a/dotnet/samples/03-workflows/Concurrent/MapReduce/Program.cs +++ b/dotnet/samples/03-workflows/Concurrent/MapReduce/Program.cs @@ -128,6 +128,7 @@ public static class Program /// /// Splits data into roughly equal chunks based on the number of mapper nodes. /// +[SendsMessage(typeof(SplitComplete))] internal sealed class Split(string[] mapperIds, string id) : Executor(id) { @@ -186,6 +187,7 @@ internal sealed class Split(string[] mapperIds, string id) : /// /// Maps each token to a count of 1 and writes pairs to a per-mapper file. /// +[SendsMessage(typeof(MapComplete))] internal sealed class Mapper(string id) : Executor(id) { /// @@ -212,6 +214,7 @@ internal sealed class Mapper(string id) : Executor(id) /// /// Groups intermediate pairs by key and partitions them across reducers. /// +[SendsMessage(typeof(ShuffleComplete))] internal sealed class Shuffler(string[] reducerIds, string[] mapperIds, string id) : Executor(id) { @@ -311,6 +314,7 @@ internal sealed class Shuffler(string[] reducerIds, string[] mapperIds, string i /// /// Sums grouped counts per key for its assigned partition. /// +[SendsMessage(typeof(ReduceComplete))] internal sealed class Reducer(string id) : Executor(id) { /// @@ -352,6 +356,7 @@ internal sealed class Reducer(string id) : Executor(id) /// /// Joins all reducer outputs and yields the final output. /// +[YieldsOutput(typeof(List))] internal sealed class CompletionExecutor(string id) : Executor>(id) { diff --git a/dotnet/samples/03-workflows/ConditionalEdges/01_EdgeCondition/Program.cs b/dotnet/samples/03-workflows/ConditionalEdges/01_EdgeCondition/Program.cs index f22ab6e269..de4f252deb 100644 --- a/dotnet/samples/03-workflows/ConditionalEdges/01_EdgeCondition/Program.cs +++ b/dotnet/samples/03-workflows/ConditionalEdges/01_EdgeCondition/Program.cs @@ -228,6 +228,7 @@ internal sealed class EmailAssistantExecutor : Executor /// Executor that sends emails. /// +[YieldsOutput(typeof(string))] internal sealed class SendEmailExecutor() : Executor("SendEmailExecutor") { /// @@ -240,6 +241,7 @@ internal sealed class SendEmailExecutor() : Executor("SendEmailEx /// /// Executor that handles spam messages. /// +[YieldsOutput(typeof(string))] internal sealed class HandleSpamExecutor() : Executor("HandleSpamExecutor") { /// diff --git a/dotnet/samples/03-workflows/ConditionalEdges/02_SwitchCase/Program.cs b/dotnet/samples/03-workflows/ConditionalEdges/02_SwitchCase/Program.cs index 69a8ec0826..7dd5927711 100644 --- a/dotnet/samples/03-workflows/ConditionalEdges/02_SwitchCase/Program.cs +++ b/dotnet/samples/03-workflows/ConditionalEdges/02_SwitchCase/Program.cs @@ -252,6 +252,7 @@ internal sealed class EmailAssistantExecutor : Executor /// Executor that sends emails. /// +[YieldsOutput(typeof(string))] internal sealed class SendEmailExecutor() : Executor("SendEmailExecutor") { /// @@ -264,6 +265,7 @@ internal sealed class SendEmailExecutor() : Executor("SendEmailEx /// /// Executor that handles spam messages. /// +[YieldsOutput(typeof(string))] internal sealed class HandleSpamExecutor() : Executor("HandleSpamExecutor") { /// @@ -285,6 +287,7 @@ internal sealed class HandleSpamExecutor() : Executor("HandleSp /// /// Executor that handles uncertain emails. /// +[YieldsOutput(typeof(string))] internal sealed class HandleUncertainExecutor() : Executor("HandleUncertainExecutor") { /// diff --git a/dotnet/samples/03-workflows/ConditionalEdges/03_MultiSelection/Program.cs b/dotnet/samples/03-workflows/ConditionalEdges/03_MultiSelection/Program.cs index 22eb589dbb..d41c0ff275 100644 --- a/dotnet/samples/03-workflows/ConditionalEdges/03_MultiSelection/Program.cs +++ b/dotnet/samples/03-workflows/ConditionalEdges/03_MultiSelection/Program.cs @@ -310,6 +310,7 @@ internal sealed class EmailAssistantExecutor : Executor /// Executor that sends emails. /// +[YieldsOutput(typeof(string))] internal sealed class SendEmailExecutor() : Executor("SendEmailExecutor") { /// @@ -322,6 +323,7 @@ internal sealed class SendEmailExecutor() : Executor("SendEmailEx /// /// Executor that handles spam messages. /// +[YieldsOutput(typeof(string))] internal sealed class HandleSpamExecutor() : Executor("HandleSpamExecutor") { /// @@ -343,6 +345,7 @@ internal sealed class HandleSpamExecutor() : Executor("HandleSpa /// /// Executor that handles uncertain messages. /// +[YieldsOutput(typeof(string))] internal sealed class HandleUncertainExecutor() : Executor("HandleUncertainExecutor") { /// diff --git a/dotnet/samples/03-workflows/HumanInTheLoop/HumanInTheLoopBasic/WorkflowFactory.cs b/dotnet/samples/03-workflows/HumanInTheLoop/HumanInTheLoopBasic/WorkflowFactory.cs index 460de5ede1..5f36faded9 100644 --- a/dotnet/samples/03-workflows/HumanInTheLoop/HumanInTheLoopBasic/WorkflowFactory.cs +++ b/dotnet/samples/03-workflows/HumanInTheLoop/HumanInTheLoopBasic/WorkflowFactory.cs @@ -38,6 +38,8 @@ internal enum NumberSignal /// /// Executor that judges the guess and provides feedback. /// +[SendsMessage(typeof(NumberSignal))] +[YieldsOutput(typeof(string))] internal sealed class JudgeExecutor() : Executor("Judge") { private readonly int _targetNumber; diff --git a/dotnet/samples/03-workflows/Loop/Program.cs b/dotnet/samples/03-workflows/Loop/Program.cs index 00f20191b8..dba811d84c 100644 --- a/dotnet/samples/03-workflows/Loop/Program.cs +++ b/dotnet/samples/03-workflows/Loop/Program.cs @@ -56,6 +56,7 @@ internal enum NumberSignal /// /// Executor that makes a guess based on the current bounds. /// +[SendsMessage(typeof(int))] internal sealed class GuessNumberExecutor : Executor { /// @@ -104,6 +105,8 @@ internal sealed class GuessNumberExecutor : Executor /// /// Executor that judges the guess and provides feedback. /// +[SendsMessage(typeof(NumberSignal))] +[YieldsOutput(typeof(string))] internal sealed class JudgeExecutor : Executor { private readonly int _targetNumber; @@ -124,8 +127,7 @@ internal sealed class JudgeExecutor : Executor this._tries++; if (message == this._targetNumber) { - await context.YieldOutputAsync($"{this._targetNumber} found in {this._tries} tries!", cancellationToken) - ; + await context.YieldOutputAsync($"{this._targetNumber} found in {this._tries} tries!", cancellationToken); } else if (message < this._targetNumber) { diff --git a/dotnet/samples/03-workflows/SharedStates/Program.cs b/dotnet/samples/03-workflows/SharedStates/Program.cs index 1ee842fd84..ebe3aaeb3b 100644 --- a/dotnet/samples/03-workflows/SharedStates/Program.cs +++ b/dotnet/samples/03-workflows/SharedStates/Program.cs @@ -99,6 +99,10 @@ internal sealed class ParagraphCountingExecutor() : Executor( } } +/// +/// The aggregation executor collects results from both executors and yields the final output. +/// +[YieldsOutput(typeof(string))] internal sealed class AggregationExecutor() : Executor("AggregationExecutor") { private readonly List _messages = []; diff --git a/dotnet/samples/03-workflows/_StartHere/06_MixedWorkflowAgentsAndExecutors/Program.cs b/dotnet/samples/03-workflows/_StartHere/06_MixedWorkflowAgentsAndExecutors/Program.cs index 7b961d1a4c..c566054146 100644 --- a/dotnet/samples/03-workflows/_StartHere/06_MixedWorkflowAgentsAndExecutors/Program.cs +++ b/dotnet/samples/03-workflows/_StartHere/06_MixedWorkflowAgentsAndExecutors/Program.cs @@ -205,6 +205,8 @@ internal sealed class TextInverterExecutor(string id) : Executor /// 1. Sending ChatMessage(s) /// 2. Sending a TurnToken to trigger processing /// +[SendsMessage(typeof(ChatMessage))] +[SendsMessage(typeof(TurnToken))] internal sealed class StringToChatMessageExecutor(string id) : Executor(id) { public override async ValueTask HandleAsync(string message, IWorkflowContext context, CancellationToken cancellationToken = default) @@ -234,6 +236,8 @@ internal sealed class StringToChatMessageExecutor(string id) : Executor( /// The AIAgentHostExecutor sends response.Messages which has runtime type List<ChatMessage>. /// The message router uses exact type matching via message.GetType(). /// +[SendsMessage(typeof(ChatMessage))] +[SendsMessage(typeof(TurnToken))] internal sealed class JailbreakSyncExecutor() : Executor>("JailbreakSync") { public override async ValueTask HandleAsync(List message, IWorkflowContext context, CancellationToken cancellationToken = default)