Skip to content

.NET: fix: pass IServiceProvider to ChatClientAgent in AddAIAgent overloads#4483

Open
max-montes wants to merge 1 commit intomicrosoft:mainfrom
max-montes:fix/hosting-service-provider-passthrough
Open

.NET: fix: pass IServiceProvider to ChatClientAgent in AddAIAgent overloads#4483
max-montes wants to merge 1 commit intomicrosoft:mainfrom
max-montes:fix/hosting-service-provider-passthrough

Conversation

@max-montes
Copy link

Motivation and Context

All four AddAIAgent overloads in AgentHostingServiceCollectionExtensions were creating ChatClientAgent without forwarding the IServiceProvider. This meant tools registered via dependency injection could not resolve their dependencies at invocation time.

Description

Pass services: sp to each ChatClientAgent constructor call so that the FunctionInvokingChatClient middleware receives the application's service provider and can resolve tool dependencies correctly.

Fixes #4453

Contribution Checklist

  • [ X] The code builds clean without any errors or warnings
  • [ X] The PR follows the Contribution Guidelines
  • [ X] All unit tests pass, and I have added new tests where possible
  • Is this a breaking change? If yes, add "[BREAKING]" prefix to the title of the PR.

Copilot AI review requested due to automatic review settings March 4, 2026 22:12
@github-actions github-actions bot changed the title fix: pass IServiceProvider to ChatClientAgent in AddAIAgent overloads .NET: fix: pass IServiceProvider to ChatClientAgent in AddAIAgent overloads Mar 4, 2026
Copy link
Contributor

Copilot AI left a comment

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 a bug (#4453) where AddAIAgent overloads in AgentHostingServiceCollectionExtensions were not forwarding the IServiceProvider to ChatClientAgent, causing tools registered via dependency injection to fail to resolve their dependencies at invocation time.

Changes:

  • Pass services: sp to each of the four ChatClientAgent constructor calls in AddAIAgent overloads so the FunctionInvokingChatClient middleware receives the application's service provider.
  • Add four regression tests (one per overload) and a MockChatClient helper class to verify that the FunctionInvokingChatClient is present in the chat client pipeline.

Reviewed changes

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

File Description
dotnet/src/Microsoft.Agents.AI.Hosting/AgentHostingServiceCollectionExtensions.cs Adds services: sp to all four ChatClientAgent constructor calls to forward the DI container's IServiceProvider.
dotnet/tests/Microsoft.Agents.AI.Hosting.UnitTests/AgentHostingServiceCollectionExtensionsTests.cs Adds four regression tests and a MockChatClient class to verify the service provider is passed through each AddAIAgent overload.

Comment on lines +228 to +231
// The FunctionInvokingChatClient in the pipeline should have been
// constructed with the application's IServiceProvider (not null).
var funcClient = agent!.ChatClient.GetService<FunctionInvokingChatClient>();
Assert.NotNull(funcClient);
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

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

These tests assert only that FunctionInvokingChatClient exists in the pipeline (GetService<FunctionInvokingChatClient>() is not null), but this would be true even without the services: sp fix — the FunctionInvokingChatClient is always created by WithDefaultAgentMiddleware, regardless of whether a service provider is passed. The tests don't actually validate that the correct (application's) IServiceProvider was forwarded.

To be a meaningful regression test for issue #4453, the tests should verify that a service registered in the DI container is resolvable from the FunctionInvokingChatClient's service provider. For example, register a custom service, then retrieve the FunctionInvokingChatClient and verify its underlying IServiceProvider can resolve that service, or invoke a tool that depends on DI resolution and verify it succeeds.

Copilot uses AI. Check for mistakes.
Copy link
Contributor

Copilot AI left a comment

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 2 out of 2 changed files in this pull request and generated 1 comment.

Comment on lines +299 to +306

if (spField is not null)
{
var innerProvider = spField.GetValue(funcClient) as IServiceProvider;
Assert.NotNull(innerProvider);
var marker = innerProvider!.GetService<IMarkerService>();
Assert.NotNull(marker);
}
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

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

The if (spField is not null) guard means that if FunctionInvokingChatClient renames or removes the _serviceProvider field in a future version of Microsoft.Extensions.AI, the reflection lookup silently returns null, all the critical assertions inside the block are skipped, and the test passes without actually verifying anything. This undermines the purpose of the regression test.

Consider adding Assert.NotNull(spField) (or using Assert.Fail in the else branch) to ensure the test fails loudly if the internal field disappears, making it clear that the verification approach needs to be updated.

Suggested change
if (spField is not null)
{
var innerProvider = spField.GetValue(funcClient) as IServiceProvider;
Assert.NotNull(innerProvider);
var marker = innerProvider!.GetService<IMarkerService>();
Assert.NotNull(marker);
}
Assert.NotNull(spField);
var innerProvider = spField!.GetValue(funcClient) as IServiceProvider;
Assert.NotNull(innerProvider);
var marker = innerProvider!.GetService<IMarkerService>();
Assert.NotNull(marker);

Copilot uses AI. Check for mistakes.
All four AddAIAgent overloads in AgentHostingServiceCollectionExtensions
were creating ChatClientAgent without forwarding the IServiceProvider.
This meant tools registered via dependency injection could not resolve
their dependencies at invocation time.

Pass services: sp to each ChatClientAgent constructor call so that the
FunctionInvokingChatClient middleware receives the application's service
provider and can resolve tool dependencies correctly.

Fixes microsoft#4453

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@max-montes max-montes force-pushed the fix/hosting-service-provider-passthrough branch from 8906f26 to a3d7b31 Compare March 5, 2026 04:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

.NET: [Bug]: Microsoft.Agents.AI.Hosting Add AddAIAgent Tool call is not adding the service provider to the agent.

3 participants