Skip to content

[.NET] Fix ConfigureDurableAgents and ConfigureDurableWorkflows not composing - #67

Open
Shyju Krishnankutty (kshyju) wants to merge 4 commits into
mainfrom
kshyju-symmetrical-sniffle
Open

[.NET] Fix ConfigureDurableAgents and ConfigureDurableWorkflows not composing#67
Shyju Krishnankutty (kshyju) wants to merge 4 commits into
mainfrom
kshyju-symmetrical-sniffle

Conversation

@kshyju

@kshyju Shyju Krishnankutty (kshyju) commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Fixes #27

ConfigureDurableAgents(...) and ConfigureDurableWorkflows(...) could not be used together, forcing callers onto ConfigureDurableOptions(...).

Implementation: all three Functions extension methods now route through a shared ConfigureDurableCore, so the execution middleware is registered once with a predicate covering both agent and workflow entry points. At the core layer, separate markers track worker and client registration so a workerBuilder/clientBuilder supplied to a later call is no longer dropped. Both call orders now produce identical registrations.

Tests are committed separately (af0f0777b) and fail without the fix.

Covers #27.

Calling ConfigureDurableAgents and ConfigureDurableWorkflows together does not
compose today:

- Azure Functions, agents configured first: the agent path registers the
  built-in execution middleware with a predicate covering only agent entry
  points, and the guard in EnsureMiddlewareRegistered then short-circuits the
  workflow path, so workflow entry points are never routed to
  BuiltInFunctionExecutor.
- Azure Functions, workflows configured first: the agent path registers the
  middleware again, duplicating it in the invocation pipeline.
- Core hosting: EnsureDurableServicesRegistered returns early on its marker, so
  worker and client builders passed to a later Configure* call are dropped.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 889a6ebe-a00c-48f4-b5e9-ec0872f872db
`ConfigureDurableAgents` and `ConfigureDurableWorkflows` did not compose when
both were called on the same application, forcing users onto
`ConfigureDurableOptions`.

Azure Functions layer:

- `ConfigureDurableAgents` registered its own `UseWhen` middleware filter whose
  predicate only covered the three agent entry points, then registered
  `BuiltInFunctionExecutor`. A later `ConfigureDurableWorkflows` saw that
  executor registration and early-returned from `EnsureMiddlewareRegistered`,
  so workflow functions got metadata but no `IFunctionExecutor` and never ran.
- In the reverse order the agent path registered the middleware and executor a
  second time, duplicating them in the invocation pipeline.

All three public entry points now funnel through a single `ConfigureDurableCore`
helper, so the full middleware predicate is registered exactly once no matter
which combination of methods is called or in which order. Default agent options
are applied only to agents added by that call, so agents auto-registered by a
workflow no longer gain an HTTP trigger just because `ConfigureDurableAgents`
happened to run afterwards.

Core service collection layer:

- `EnsureDurableServicesRegistered` guarded the whole registration block with a
  single marker, so a `workerBuilder` or `clientBuilder` passed to any call
  after the first was silently dropped and no worker or client was registered.

Worker and client registration are now tracked with their own markers and are
independent of the shared services guard, so each is registered at most once
while still honoring a builder supplied by a later call.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 889a6ebe-a00c-48f4-b5e9-ec0872f872db
The Azure Functions "workflow and agents" sample steered users to
`ConfigureDurableOptions` as the way to register both agents and workflows,
because separate `ConfigureDurableAgents` and `ConfigureDurableWorkflows` calls
did not compose. Now that they do, the sample uses the split calls and mentions
`ConfigureDurableOptions` as an equivalent alternative.

Also corrects the console sample comments that described the three methods as
mutually exclusive, and documents composition in the durable agents README.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 889a6ebe-a00c-48f4-b5e9-ec0872f872db
Copilot AI lite review requested due to automatic review settings August 12, 2026 16:01

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes configuration composition so ConfigureDurableAgents(...) and ConfigureDurableWorkflows(...) can be used together (in any order) without forcing callers onto ConfigureDurableOptions(...), aligning Azure Functions and core IServiceCollection behavior with the intended additive options model.

Changes:

  • Unifies Azure Functions configuration paths via a shared core registration method so built-in middleware/executor routing works for both agent and workflow entry points regardless of call order.
  • Fixes core DI registration so workerBuilder / clientBuilder provided in a later Configure* call are no longer silently ignored.
  • Adds regression tests plus sample/docs updates and changelog entries documenting the supported, composable configuration experience.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
dotnet/tests/Microsoft.Agents.AI.Hosting.AzureFunctions.UnitTests/FunctionsDurableConfigurationCompositionTests.cs New regression tests validating built-in entry points route to BuiltInFunctionExecutor and middleware/executor are registered once.
dotnet/tests/Microsoft.Agents.AI.DurableTask.UnitTests/DurableConfigurationCompositionTests.cs New regression tests validating additive agent/workflow registration and honoring worker/client builders across multiple calls.
dotnet/src/Microsoft.Agents.AI.Hosting.AzureFunctions/FunctionsApplicationBuilderExtensions.cs Refactors durable configuration into a shared core path and expands middleware predicate coverage to include workflow entry points.
dotnet/src/Microsoft.Agents.AI.Hosting.AzureFunctions/CHANGELOG.md Documents the Azure Functions composition fix.
dotnet/src/Microsoft.Agents.AI.DurableTask/ServiceCollectionExtensions.cs Splits “core shared services” registration from worker/client registration so later worker/client builders are honored without duplicating shared services.
dotnet/src/Microsoft.Agents.AI.DurableTask/DurableServicesMarker.cs Introduces dedicated markers for worker/client configuration to support composition across calls.
dotnet/src/Microsoft.Agents.AI.DurableTask/CHANGELOG.md Documents the core IServiceCollection builder-composition fix.
dotnet/samples/DurableWorkflows/ConsoleApps/04_WorkflowAndAgents/Program.cs Updates sample narrative to reflect that all three configuration methods compose additively.
dotnet/samples/DurableWorkflows/AzureFunctions/05_WorkflowAndAgents/README.md Updates sample docs to show separate, composable ConfigureDurableAgents + ConfigureDurableWorkflows usage (and optional ConfigureDurableOptions).
dotnet/samples/DurableWorkflows/AzureFunctions/05_WorkflowAndAgents/Program.cs Switches sample implementation to separate composable configuration calls.
docs/features/durable-agents/README.md Updates feature documentation to explicitly describe hosting workflows alongside agents using composable calls.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Agent names are case-insensitive in DurableAgentsOptions and in the
Functions agent options registry. Match that comparer when snapshotting
agent keys so the set semantics cannot drift.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 889a6ebe-a00c-48f4-b5e9-ec0872f872db
Copilot AI review requested due to automatic review settings August 12, 2026 16:12

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated no new comments.

Suppressed comments (2)

dotnet/tests/Microsoft.Agents.AI.Hosting.AzureFunctions.UnitTests/FunctionsDurableConfigurationCompositionTests.cs:51

  • The built-in entry point routing tests don't cover all entry points that EnsureMiddlewareRegistered routes to BuiltInFunctionExecutionMiddleware (notably the agent MCP tool trigger, workflow MCP tool trigger, and workflow HTTP response entry point). Adding these cases would better protect against regressions in the shared predicate and ensure composition works for all built-in triggers.
    public static TheoryData<string> BuiltInEntryPointNames() =>
    [
        "AgentHttp",
        "AgentEntity",
        "WorkflowOrchestrationHttp",
        "WorkflowOrchestration",
        "WorkflowActivity",
        "WorkflowStatusHttp",
    ];

    private static string ResolveEntryPoint(string name) => name switch
    {
        "AgentHttp" => BuiltInFunctions.RunAgentHttpFunctionEntryPoint,
        "AgentEntity" => BuiltInFunctions.RunAgentEntityFunctionEntryPoint,
        "WorkflowOrchestrationHttp" => BuiltInFunctions.RunWorkflowOrchestrationHttpFunctionEntryPoint,
        "WorkflowOrchestration" => BuiltInFunctions.RunWorkflowOrchestrationFunctionEntryPoint,
        "WorkflowActivity" => BuiltInFunctions.InvokeWorkflowActivityFunctionEntryPoint,
        "WorkflowStatusHttp" => BuiltInFunctions.GetWorkflowStatusHttpFunctionEntryPoint,
        _ => throw new ArgumentOutOfRangeException(nameof(name), name, "Unknown built-in entry point."),
    };

dotnet/src/Microsoft.Agents.AI.Hosting.AzureFunctions/FunctionsApplicationBuilderExtensions.cs:70

  • The parameter indentation on ConfigureDurableWorkflows is off by one space compared to the rest of the file, which makes the signature formatting inconsistent and harder to scan.
    public static FunctionsApplicationBuilder ConfigureDurableWorkflows(
         this FunctionsApplicationBuilder builder,
         Action<DurableWorkflowOptions> configure)

@kshyju
Shyju Krishnankutty (kshyju) marked this pull request as ready for review August 12, 2026 20:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Make Durable Agent and Durable Workflow configuration APIs compose naturally

2 participants