Description
When a hosted agent uses a pre-registered toolbox with a per-user OAuth MCP connection, the consent link in its oauth_consent_request can't be completed. Signing in ends on /nextgen/closeMe with Something went wrong while authenticating. Error: Code <id> not found.
The callback's userCtx has userId set to the project's system-assigned managed identity, not the user who called the agent. The container authenticates to the toolbox proxy with that identity (the MSAL log shows the system_assigned_managed_identity token cache), so the proxy creates the consent session for it. The inbound request did carry the user: the container log shows HasUserId=True HasCallId=True.
The call id should reach the proxy too. AgentFrameworkResponseHandler re-applies HostedCallContext.CallId before toolbox egress, and FoundryToolboxBearerTokenHandler forwards it as x-agent-foundry-call-id "so the toolbox proxy can resolve the server-side caller context".
Credential lookup does follow the calling user. When the same user calls the toolbox MCP endpoint directly with their own token, tools/list returns -32006 with a link bound to them, and sign-in succeeds. The agent's next request then lists and calls the toolbox tools with that user's credential. A principal that never signed in still gets CONSENT_REQUIRED. Only the link produced on the hosted path is bound to the wrong identity.
Steps to reproduce:
- Create a project connection with custom OAuth2 (an Entra app with a delegated scope) to a remote MCP server, and a toolbox that references it.
- Host an agent that calls
AddFoundryToolboxes(new DefaultAzureCredential(), "<toolbox>") on the Responses protocol 2.0.0, and deploy it.
- Call the agent endpoint with a user's Entra token. The response is
incomplete with an oauth_consent_request.
- Open the consent link and sign in as that user.
Expected: the sign-in is stored for the calling user, and resending the request runs the tool.
Actual: sign-in fails with the error above, and every later request returns a new link bound to the managed identity.
Code Sample
var credential = new DefaultAzureCredential();
var agent = new AIProjectClient(projectEndpoint, credential)
.AsAIAgent(model: deploymentName, instructions: instructions, name: "orchestrator");
var builder = AgentHost.CreateBuilder(args);
builder.Services.AddFoundryResponses(agent);
builder.Services.AddFoundryToolboxes(credential, toolboxName);
builder.RegisterProtocol("responses", endpoints => endpoints.MapFoundryResponses());
builder.Build().Run();
Error Messages / Stack Traces
Something went wrong while authenticating. Please close this window and try again.
Error: Code <id> not found.
closeMe userCtx (decoded): {"userId":"<project managed identity object ID>","tenantId":"<tenant>","connectionName":"<connection>.<id>.<id>","projectUrl":"<project endpoint>"}
Package Versions
Microsoft.Agents.AI.Foundry.Hosting: 1.21.0-preview.260911.1, Azure.AI.Projects: 3.0.0-beta.2, Azure.Identity: 1.21.0
.NET Version
.NET 10.0 (Linux x64 container, runtime 10.0.12)
Additional Context
Follows #6562, which made the consent link visible (fixed in #6718). ToolboxOAuthConsentHostedAgentTests is skipped on main, and it only asserts that a consent link is returned, so completing consent isn't covered.
Our workaround is taking the consent link from a direct toolbox tools/list call made with the user's token.
Description
When a hosted agent uses a pre-registered toolbox with a per-user OAuth MCP connection, the consent link in its
oauth_consent_requestcan't be completed. Signing in ends on/nextgen/closeMewithSomething went wrong while authenticating. Error: Code <id> not found.The callback's
userCtxhasuserIdset to the project's system-assigned managed identity, not the user who called the agent. The container authenticates to the toolbox proxy with that identity (the MSAL log shows thesystem_assigned_managed_identitytoken cache), so the proxy creates the consent session for it. The inbound request did carry the user: the container log showsHasUserId=True HasCallId=True.The call id should reach the proxy too.
AgentFrameworkResponseHandlerre-appliesHostedCallContext.CallIdbefore toolbox egress, andFoundryToolboxBearerTokenHandlerforwards it asx-agent-foundry-call-id"so the toolbox proxy can resolve the server-side caller context".Credential lookup does follow the calling user. When the same user calls the toolbox MCP endpoint directly with their own token,
tools/listreturns-32006with a link bound to them, and sign-in succeeds. The agent's next request then lists and calls the toolbox tools with that user's credential. A principal that never signed in still getsCONSENT_REQUIRED. Only the link produced on the hosted path is bound to the wrong identity.Steps to reproduce:
AddFoundryToolboxes(new DefaultAzureCredential(), "<toolbox>")on the Responses protocol 2.0.0, and deploy it.incompletewith anoauth_consent_request.Expected: the sign-in is stored for the calling user, and resending the request runs the tool.
Actual: sign-in fails with the error above, and every later request returns a new link bound to the managed identity.
Code Sample
var credential = new DefaultAzureCredential(); var agent = new AIProjectClient(projectEndpoint, credential) .AsAIAgent(model: deploymentName, instructions: instructions, name: "orchestrator"); var builder = AgentHost.CreateBuilder(args); builder.Services.AddFoundryResponses(agent); builder.Services.AddFoundryToolboxes(credential, toolboxName); builder.RegisterProtocol("responses", endpoints => endpoints.MapFoundryResponses()); builder.Build().Run();Error Messages / Stack Traces
Package Versions
Microsoft.Agents.AI.Foundry.Hosting: 1.21.0-preview.260911.1, Azure.AI.Projects: 3.0.0-beta.2, Azure.Identity: 1.21.0
.NET Version
.NET 10.0 (Linux x64 container, runtime 10.0.12)
Additional Context
Follows #6562, which made the consent link visible (fixed in #6718).
ToolboxOAuthConsentHostedAgentTestsis skipped on main, and it only asserts that a consent link is returned, so completing consent isn't covered.Our workaround is taking the consent link from a direct toolbox
tools/listcall made with the user's token.