Files
agent-framework/dotnet/src/Microsoft.Agents.AI.Workflows.Declarative/Interpreter/DelegateActionExecutor.cs
T
Jacob AlberandGitHub 6a3d22598f .NET: [BREAKING] Implement Polymorphic Routing (#3792)
* feat: Implement Polymorphic Routing

* feat: Add support for Send/Yield annotations with basic Executor

* Adds annotations to Declarative workflow executors

* fix: Address PR Comments

* Implicit filter in collection loops
* Remove debug / usused / superfluous code
* Fix ProtocolBuilder implicit output registrations
* Fix logic error in ExecuteRouteGeneratorTests.ClassWithManualConfigureProtocol_DoesNotGenerate

* fix: Solidify type checks and send/yield type registrations

* fix: Suppress generation of TurnTokens out of AggregateTurnMessagesExecutor

* Fixes an issue where ConcurrentEndExecutor is not expecting TurnTokens.

* fix: Add ProtocolBuilder support for chained-delegation

* Updates Declarative pacakge to rely on chained-delegation Send/Yield registration
* Renames DeclarativeActionExectuor's new ExecuteAsync to ExecuteActionAsync to avoid colliding with Executor.ExecutoeAsync

* fix: Address PR Comments

* Fixes type mapping in FanInEdgeRunner
* Fixes and expalins send/yield type registration in FunctionExecutor

* fixup: build-break

* fix: Add missing SendsMesage declaration to InvokeAzureAgentExecutor
2026-02-19 14:09:03 +00:00

72 lines
2.7 KiB
C#

// Copyright (c) Microsoft. All rights reserved.
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Agents.AI.Workflows.Declarative.Extensions;
using Microsoft.Agents.AI.Workflows.Declarative.Kit;
using Microsoft.Agents.AI.Workflows.Declarative.PowerFx;
namespace Microsoft.Agents.AI.Workflows.Declarative.Interpreter;
internal sealed class DelegateActionExecutor(string actionId, WorkflowFormulaState state, DelegateAction<ActionExecutorResult>? action = null, bool emitResult = true)
: DelegateActionExecutor<ActionExecutorResult>(actionId, state, action, emitResult)
{
public override ValueTask HandleAsync(ActionExecutorResult message, IWorkflowContext context, CancellationToken cancellationToken)
{
Debug.WriteLine($"RESULT #{this.Id} - {message.Result ?? "(null)"}");
return base.HandleAsync(message, context, cancellationToken);
}
}
internal class DelegateActionExecutor<TMessage> : Executor<TMessage>, IResettableExecutor, IModeledAction where TMessage : notnull
{
private readonly WorkflowFormulaState _state;
private readonly DelegateAction<TMessage>? _action;
private readonly bool _emitResult;
public DelegateActionExecutor(string actionId, WorkflowFormulaState state, DelegateAction<TMessage>? action = null, bool emitResult = true)
: base(actionId)
{
this._state = state;
this._action = action;
this._emitResult = emitResult;
}
protected override ProtocolBuilder ConfigureProtocol(ProtocolBuilder protocolBuilder)
{
ProtocolBuilder baseBuilder = base.ConfigureProtocol(protocolBuilder);
if (this._emitResult)
{
baseBuilder.SendsMessage<TMessage>();
}
// We chain to the provided delegate, so let the protocol know we have additional Send/Yield types that may not be
// available on the HandleAsync override.
return (this._action != null) ? baseBuilder.AddDelegateAttributeTypes(this._action)
: baseBuilder;
}
/// <inheritdoc/>
public ValueTask ResetAsync()
{
return default;
}
[SendsMessage(typeof(ActionExecutorResult))]
public override async ValueTask HandleAsync(TMessage message, IWorkflowContext context, CancellationToken cancellationToken = default)
{
if (this._action is not null)
{
await this._action.Invoke(new DeclarativeWorkflowContext(context, this._state), message, cancellationToken).ConfigureAwait(false);
}
if (this._emitResult)
{
await context.SendResultMessageAsync(this.Id, cancellationToken).ConfigureAwait(false);
}
}
}