Repository navigation
.NET: [Bug]: Protocol hosting ignores AIAgent lifetimes and lacks consistent request-time selection #7733
Description
Description
AddAIAgent explicitly supports Singleton, Scoped, and Transient registrations through its ServiceLifetime parameter. ASP.NET Core creates one request scope and exposes it through HttpContext.RequestServices.
The Agent Framework protocol hosting integrations currently bypass that request scope and resolve hosted agents or protocol services from the root provider.
Current behavior:
| Integration | Resolution behavior |
|---|---|
| AG-UI | MapAGUIServer(IHostedAgentBuilder, ...) and the named overload resolve the keyed AIAgent from endpoints.ServiceProvider during endpoint mapping |
| OpenAI Chat Completions | Hosted overload resolves the keyed agent from endpoints.ServiceProvider during endpoint mapping |
| OpenAI Responses direct hosted overload | Resolves and captures the keyed agent during endpoint mapping |
| OpenAI Responses service-based path | HostedAgentResponseExecutor is singleton and resolves named agents from its captured root IServiceProvider |
| A2A | Registers a keyed singleton A2AServer, which resolves and captures the keyed agent and session store from the root provider |
This means a scoped agent registration is either rejected by scope validation or effectively promoted/captured beyond its configured lifetime. It also prevents agent factories from consuming request-scoped services such as DbContext, tenant configuration, authenticated request state, or scoped tools.
There is a related usability gap: applications need a simple, consistent way to select a hosted agent at request time based on route values, authenticated claims, tenant configuration, headers, or other request state. Existing proposals have added AG-UI-specific factories, but the same requirement applies to AG-UI, OpenAI Chat Completions, OpenAI Responses, and A2A.
The solution should therefore cover two related capabilities consistently across hosting extensions:
- honor the configured DI lifetime of an existing named/hosted registration;
- select which hosted registration handles the request before resolving its agent and session services.
Expected behavior:
- Hosted/named endpoint overloads resolve the keyed
AIAgentfromHttpContext.RequestServicesfor each request. - The associated keyed
AgentSessionStore, isolation services, handlers, and protocol adapters are resolved from the same request scope. - Singleton registrations continue to return the same instance.
- Scoped registrations return one instance per HTTP request and can consume scoped dependencies.
- Transient registrations follow normal DI semantics.
- Direct instance overloads remain fixed-instance APIs.
- Session persistence remains stable across request-scoped agent instances. The hosting layer must use an explicit stable logical identity (for example, the hosted registration name) or fail clearly when a request-created agent cannot safely resume the previously serialized session. It must not silently reset persistence because a newly created agent received a new default ID.
- Multi-user isolation continues to use
AgentIsolationKeyProvider; resolving from the request scope does not make a client-supplied continuation ID an authorization boundary. - Each ASP.NET Core protocol integration provides the same request-time hosted-agent selection pattern.
- Selection occurs before resolving the
AIAgent, session store, protocol handler, or other agent-owned services. - The returned agent exposes a stable logical identity compatible with session persistence. The hosting integration resolves the associated session store and agent-owned services from the request scope.
- A missing selection produces the protocol-appropriate not-found response; authorization failures remain application-owned and must occur before loading session state.
- The selector can use ASP.NET Core request state, including route values and authenticated claims, without requiring
IHttpContextAccessorinside the agent implementation.
A possible common API shape is to use Func<HttpContext, AIAgent> consistently across protocol integrations:
app.MapAGUIServer(
"/agents/{agentId}/ag-ui",
context => ResolveAgent(context));
app.MapOpenAIChatCompletions(
"/agents/{agentId}/v1/chat/completions",
context => ResolveAgent(context));
app.MapOpenAIResponses(
"/agents/{agentId}/v1/responses",
context => ResolveAgent(context));
app.MapA2AHttpJson(
"/agents/{agentId}/a2a",
context => ResolveAgent(context));The returned agent must have a stable logical identity so its session state can be restored across requests.
Code Sample
Request-scoped hosted agent registration:
IHostedAgentBuilder hostedAgent = builder.Services.AddAIAgent(
"assistant",
(services, name) =>
{
var scopedDependency = services.GetRequiredService<MyScopedDependency>();
var chatClient = services.GetRequiredKeyedService<IChatClient>("model");
return chatClient
.AsAIAgent(name: name)
.AsBuilder()
.Use((inner, services) =>
new MyScopedAgentDecorator(inner, scopedDependency))
.Build(services);
},
ServiceLifetime.Scoped);
hostedAgent.WithSessionStore(
(services, _) => services.GetRequiredService<AgentSessionStore>());
app.MapAGUIServer(hostedAgent, "/ag-ui");
app.MapOpenAIResponses(hostedAgent, "/v1/responses");
hostedAgent.AddA2AServer();
app.MapA2AHttpJson(hostedAgent, "/a2a");All endpoints should resolve the assistant registration from the active request scope and should observe the same scoped dependencies for that request.
The request-time factory receives HttpContext and returns the agent to invoke. The hosting integration resolves the associated session store and agent-owned services from HttpContext.RequestServices.
Error Messages / Stack Traces
With scope validation enabled, resolving a scoped registration from the root provider can fail with errors equivalent to:
Cannot resolve scoped service 'Microsoft.Agents.AI.AIAgent' from root provider.
Without validation, the scoped instance can become captive and behave like a singleton.
Package Versions
Current main versions of:
Microsoft.Agents.AI.HostingMicrosoft.Agents.AI.Hosting.AGUI.AspNetCoreMicrosoft.Agents.AI.Hosting.OpenAIMicrosoft.Agents.AI.Hosting.A2AMicrosoft.Agents.AI.Hosting.A2A.AspNetCore
.NET Version
.NET 8, 9, and 10
Additional Context
Microsoft documentation confirms that:
AddAIAgent(..., ServiceLifetime)defaults to singleton but accepts another DI lifetime.- MEAI
AddChatClientandAddKeyedChatClientalso acceptServiceLifetime. - ASP.NET Core creates one request scope and exposes scoped services through
HttpContext.RequestServices.
Related issues and PRs that cover portions of this cross-host requirement:
- .NET: Support dynamic agent resolution in AG-UI endpoints (MapAGUI with factory delegate) #2988 — dynamic AG-UI agent resolution
- .NET: MapAGUI supports per-request agent selection #2343 — per-request AG-UI agent selection
- .NET: Support dynamic agent resolution in AG-UI endpoints #3162 — dynamic AG-UI factory/resolver
- .NET: Add MapAGUI overload that resolves the agent per request via a factory #6251 — current per-request AG-UI factory implementation with stable identity work
- .NET: ADR for unified dynamic agent resolution across AG-UI, Responses, and A2A #6643 — cross-host ADR
- .NET: Add factory delegate overload to MapAGUI for per-request agent resolution #6659 — AG-UI factory overload implementation
- .NET: Add name-derived MapAGUIServer overloads #2547 — hosted/name overload consistency; currently still resolves from the root provider
Request-time selection should use the same Func<HttpContext, AIAgent> pattern across every protocol integration. Returned agents must preserve stable identity and session compatibility across requests.
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsNo status
Activity
[-].NET: [Bug]: Protocol hosting ignores configured AIAgent service lifetimes[/-][+].NET: [Bug]: Protocol hosting ignores AIAgent lifetimes and lacks consistent request-time selection[/+]hansmbakker commentedon Sep 2, 2026
Javier Calvarro Nelson (@javiercn) Thank you for logging this issue! This issue is bothering me for some time now.
I used
IServiceScopeFactoryinjected in function tools as a workaround but that might not cover all places where it is needed, and it is a workaround - not a proper solution.Could you or Evan Mattson (@moonbox3) please give me some insight into where this issue is on the roadmap?
marcominerva commentedon Sep 29, 2026
Now that the AG-UI .NET SDK has shipped its first stable release (#8769), and with more and more customers starting to show interest in it, providing full support for the AIAgent lifetime during registration is more important than ever.
TsengSR commentedon Oct 14, 2026
Having same issue with agent and workflows. While I can change the lifetime of the workflow and agent, DevUi call fails for same reason: It attempts to resolve from root container.
This bite me just 3 days into development. We really need scoped support everywhere for scoped services like EF Core (DbContext) etc. and popping CreateScope() everywhere isn't going to bring us anytime (makes unit tests incredibly more complicated).
marcominerva commentedon Oct 14, 2026
I've put together a PR to address this issue: #9382.
I hope it can serve as a starting point for adding lifetime support, as this is a highly requested feature. I have several customers who are currently unable to use AG-UI specifically because this capability is missing.