.NET: [Bug]: Concurrency capability is not preserved by function and subworkflow bindings

Open
#8,341 1 comment 0 reactions 1 assignee View on GitHub

@peibekwe is already working on this.

Since Sep 13, 2026.

Assessment

This issue has not been assessed yet.

Description

.NET reproduced workflows
Description

ExecutorBinding.SupportsConcurrentSharedExecution contributes to whether a workflow can be used with InProcessExecution.Concurrent.

I found two binding paths where the underlying concurrency capability is not preserved:

  1. BindAsExecutor(..., threadsafe: false) creates a FunctionExecutor that is not cross-run shareable, but the configured binding currently reports concurrent shared execution as supported.
  2. SubworkflowBinding reports concurrent shared execution as supported even when its child workflow is not concurrent-capable.

As a result, workflows can be accepted by the concurrent execution path even though one of the shared execution paths does not support concurrent runs.

The subworkflow case is independently reproducible using a direct non-shareable executor, so it does not depend on the function-binding behavior.

Expected behavior:

  • threadsafe: false, including the default value, should make a shared function binding ineligible for concurrent workflow runs.
  • threadsafe: true should remain eligible.
  • A subworkflow binding should reflect whether its child workflow supports concurrent runs.
  • Invalid concurrent execution should be rejected at the appropriate workflow boundary.
Code Sample
Function binding
Func<int, int> handler = static value => value;

ExecutorBinding binding =
    handler.BindAsExecutor("Function", threadsafe: false);

Workflow workflow =
    new WorkflowBuilder(binding).Build();

await using StreamingRun run =
    await InProcessExecution.Concurrent.OpenStreamingAsync(workflow);

// Actual: the concurrent run is accepted.
// Expected: InvalidOperationException.
Independent subworkflow case
static ValueTask HandleAsync(
    int message,
    IWorkflowContext context,
    CancellationToken cancellationToken) => default;

FunctionExecutor<int> childExecutor =
    new("Child", HandleAsync, declareCrossRunShareable: false);

Workflow child =
    new WorkflowBuilder(childExecutor.BindExecutor()).Build();

ExecutorBinding childBinding =
    child.BindAsExecutor("ChildWorkflow");

Workflow parent =
    new WorkflowBuilder(childBinding).Build();

await using StreamingRun run =
    await InProcessExecution.Concurrent.OpenStreamingAsync(parent);

// Actual: the parent passes the concurrent eligibility check.
// Expected: the parent is rejected because its child workflow is not
// concurrent-capable.
Error Messages / Stack Traces

No exception is produced at the affected eligibility boundary.

The expected behavior is the existing InvalidOperationException used when concurrent execution is requested for a workflow containing a binding that does not support concurrent shared execution.

Package Versions

Microsoft.Agents.AI.Workflows: 1.21.0

The same affected implementation is present in the dotnet-1.21.0 source tag. Runtime reproduction below was performed against current microsoft/agent-framework main; the release tag was inspected at source level only.

.NET Version

.NET SDK 10.0.401

Additional Context

The threadsafe parameter already describes whether a function handler may be used simultaneously by multiple runs. The function case appears to lose that capability when the FunctionExecutor is converted into a configured binding.

The subworkflow case appears to be the same capability-propagation issue at the workflow boundary: the child workflow can be non-concurrent while the binding presented to its parent reports concurrent support.

I have a small patch and deterministic regression coverage for both cases. If maintainers would prefer the subworkflow case to be handled separately, I am happy to split it into a follow-up.

I'm happy to work on the fix if this direction looks appropriate.

Dominant language
Python
Stars
13.6k
Forks
2.3k
Avg merge
1d 20h
Merged PRs (30d)
342

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from microsoft/agent-framework

All issues in microsoft/agent-framework

Similar issues

More Python issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.