Skip to content

.NET: [Bug]: AddFanInBarrierEdge never invokes the target executor after all source executors complete #4884

@MaguireKrist-ITK

Description

@MaguireKrist-ITK

Description

AddFanInBarrierEdge(...) does not appear to advance the target executor, even when all source executors run successfully and each
produces a message/result.

I reproduced this in an isolated minimal console app using InProcessExecution.RunStreamingAsync(...).

What I observed:

  • AddFanOutEdge(...) works as expected
  • all fan-out source executors are invoked
  • each source executor completes successfully
  • the fan-in target executor is never invoked
  • no workflow output is produced from the fan-in target

I reproduced this with:

  1. generic Executor<TIn, TOut> executors that return values
  2. explicit message-based executors that call context.SendMessageAsync(...)

Code Sample

using Microsoft.Agents.AI.Workflows;

  var start = new StartExec();
  var a = new AExec();
  var b = new BExec();
  var agg = new AggExec();

  var workflow = new WorkflowBuilder(start)
      .AddFanOutEdge(start, [a, b])
      .AddFanInBarrierEdge([a, b], agg)
      .WithOutputFrom(agg)
      .Build();

  await using var run = await InProcessExecution.RunStreamingAsync(workflow, "x");

  await foreach (var evt in run.WatchStreamAsync())
  {
      Console.WriteLine($"{evt.GetType().Name}: {evt}");
      if (evt is WorkflowOutputEvent output)
      {
          Console.WriteLine($"OUTPUT: {output.Data}");
      }
  }

  internal sealed class StartExec() : Executor<string, string>("start")
  {
      public override ValueTask<string> HandleAsync(
          string input,
          IWorkflowContext context,
          CancellationToken cancellationToken = default)
      {
          Console.WriteLine("start");
          return ValueTask.FromResult($"{input}-start");
      }
  }

  internal sealed class AExec() : Executor<string, string>("a")
  {
      public override ValueTask<string> HandleAsync(
          string input,
          IWorkflowContext context,
          CancellationToken cancellationToken = default)
      {
          Console.WriteLine("a");
          return ValueTask.FromResult($"{input}-a");
      }
  }

  internal sealed class BExec() : Executor<string, string>("b")
  {
      public override ValueTask<string> HandleAsync(
          string input,
          IWorkflowContext context,
          CancellationToken cancellationToken = default)
      {
          Console.WriteLine("b");
          return ValueTask.FromResult($"{input}-b");
      }
  }

  internal sealed class AggExec() : Executor<List<string>, string>("agg")
  {
      public override ValueTask<string> HandleAsync(
          List<string> input,
          IWorkflowContext context,
          CancellationToken cancellationToken = default)
      {
          Console.WriteLine($"agg:{input.Count}");
          return ValueTask.FromResult(string.Join(",", input));
      }
  }

Error Messages / Stack Traces

Package Versions

10.0.0-rc4

.NET Version

.NET 10.0

Additional Context

Expected Behavior

After both a and b complete, the barrier should release and invoke agg with both messages/results.

I expected output like:

  • agg:2
  • a WorkflowOutputEvent containing both values

Actual Behavior

Only start, a, and b run. agg is never invoked.

Additional Context

  • I also reproduced the same behavior with non-generic Executor implementations that explicitly call context.SendMessageAsync(...)
    and declare routes in ConfigureProtocol(...).
  • In that variation, fan-out still works, but the fan-in target still never runs.
  • ExecutorOptions.Default reports AutoSendMessageHandlerResultObject = true and AutoYieldOutputHandlerResultObject = true, so this
    does not appear to be caused by those defaults.
  • The package docs for AddFanInBarrierEdge(...) describe the barrier as waiting for one message from each source and then advancing
    the target on the following step.
  • The public concurrent sample in the repo also suggests this pattern should work.

References:

  • Docs:

https://learn.microsoft.com/en-us/dotnet/api/microsoft.agents.ai.workflows.workflowbuilder.addfaninbarrieredge?view=agent-framework-dotnet-latest

Metadata

Metadata

Assignees

Labels

.NETbugSomething isn't workingv1.0Features being tracked for the version 1.0 GA

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions