diff --git a/dotnet/src/Microsoft.Agents.AI.Workflows/ChatProtocolExecutor.cs b/dotnet/src/Microsoft.Agents.AI.Workflows/ChatProtocolExecutor.cs
index 480c2e0ce3..56fb326338 100644
--- a/dotnet/src/Microsoft.Agents.AI.Workflows/ChatProtocolExecutor.cs
+++ b/dotnet/src/Microsoft.Agents.AI.Workflows/ChatProtocolExecutor.cs
@@ -8,23 +8,40 @@ using Microsoft.Extensions.AI;
namespace Microsoft.Agents.AI.Workflows;
-internal class ChatProtocolExecutorOptions
+///
+/// Provides configuration options for .
+///
+public class ChatProtocolExecutorOptions
{
+ ///
+ /// Gets or sets the chat role to use when converting string messages to instances.
+ /// If set, the executor will accept string messages and convert them to chat messages with this role.
+ ///
public ChatRole? StringMessageChatRole { get; set; }
}
-// TODO: Make this a public type (in a later PR; todo: make an issue)
-internal abstract class ChatProtocolExecutor : StatefulExecutor>
+///
+/// Provides a base class for executors that implement the Agent Workflow Chat Protocol.
+/// This executor maintains a list of chat messages and processes them when a turn is taken.
+///
+public abstract class ChatProtocolExecutor : StatefulExecutor>
{
private readonly static Func> s_initFunction = () => [];
private readonly ChatRole? _stringMessageChatRole;
- internal ChatProtocolExecutor(string id, ChatProtocolExecutorOptions? options = null, bool declareCrossRunShareable = false)
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The unique identifier for this executor instance. Cannot be null or empty.
+ /// Optional configuration settings for the executor. If null, default options are used.
+ /// Declare that this executor may be used simultaneously by multiple runs safely.
+ protected ChatProtocolExecutor(string id, ChatProtocolExecutorOptions? options = null, bool declareCrossRunShareable = false)
: base(id, () => [], declareCrossRunShareable: declareCrossRunShareable)
{
this._stringMessageChatRole = options?.StringMessageChatRole;
}
+ ///
protected override RouteBuilder ConfigureRoutes(RouteBuilder routeBuilder)
{
if (this._stringMessageChatRole.HasValue)
@@ -40,6 +57,13 @@ internal abstract class ChatProtocolExecutor : StatefulExecutor(this.TakeTurnAsync);
}
+ ///
+ /// Adds a single chat message to the accumulated messages for the current turn.
+ ///
+ /// The chat message to add.
+ /// The workflow context in which the executor executes.
+ /// The to monitor for cancellation requests.
+ /// A representing the asynchronous operation.
protected ValueTask AddMessageAsync(ChatMessage message, IWorkflowContext context, CancellationToken cancellationToken = default)
{
return this.InvokeWithStateAsync(ForwardMessageAsync, context, cancellationToken: cancellationToken);
@@ -52,6 +76,13 @@ internal abstract class ChatProtocolExecutor : StatefulExecutor
+ /// Adds multiple chat messages to the accumulated messages for the current turn.
+ ///
+ /// The collection of chat messages to add.
+ /// The workflow context in which the executor executes.
+ /// The to monitor for cancellation requests.
+ /// A representing the asynchronous operation.
protected ValueTask AddMessagesAsync(IEnumerable messages, IWorkflowContext context, CancellationToken cancellationToken = default)
{
return this.InvokeWithStateAsync(ForwardMessageAsync, context, cancellationToken: cancellationToken);
@@ -64,6 +95,13 @@ internal abstract class ChatProtocolExecutor : StatefulExecutor
+ /// Handles a turn token by processing all accumulated chat messages and then resetting the message state.
+ ///
+ /// The turn token that triggers message processing.
+ /// The workflow context in which the executor executes.
+ /// The to monitor for cancellation requests.
+ /// A representing the asynchronous operation.
public ValueTask TakeTurnAsync(TurnToken token, IWorkflowContext context, CancellationToken cancellationToken = default)
{
return this.InvokeWithStateAsync(InvokeTakeTurnAsync, context, cancellationToken: cancellationToken);
@@ -81,5 +119,13 @@ internal abstract class ChatProtocolExecutor : StatefulExecutor
+ /// When overridden in a derived class, processes the accumulated chat messages for a single turn.
+ ///
+ /// The list of chat messages accumulated since the last turn.
+ /// The workflow context in which the executor executes.
+ /// Indicates whether events should be emitted during processing. If null, the default behavior is used.
+ /// The to monitor for cancellation requests.
+ /// A representing the asynchronous operation.
protected abstract ValueTask TakeTurnAsync(List messages, IWorkflowContext context, bool? emitEvents, CancellationToken cancellationToken = default);
}