* .NET: Add Hosted-Toolbox-AuthPaths sample and auto-map /readiness with toolbox health gating (#5777) Add a new hosted agent sample demonstrating five MCP tool authentication paths (API key, agent MI, project MI, custom OAuth, literal token) via a Foundry Toolbox. Package changes (Microsoft.Agents.AI.Foundry.Hosting): - MapFoundryResponses now auto-maps GET /readiness via MapHealthChecks, idempotent across Tier 1/2 (AgentHost, already mapped) and Tier 3 (WebApplication, gap filled). - AddFoundryResponses registers AddHealthChecks() so the pipeline is available. - AddFoundryToolboxes registers FoundryToolboxHealthCheck on the /readiness aggregate, gating readiness on pre-registered toolbox startup outcome (per spec section 3.1). - FoundryToolboxService now exposes StartupStatus and FailedToolboxNames properties. New types: - FoundryToolboxStartupStatus (public enum): Pending, Healthy, Failed, NoEndpoint. - FoundryToolboxHealthCheck (internal IHealthCheck): adapts startup status to the AspNetCore HealthChecks pipeline with failed toolbox names in result data. Tests: - 3 new tests for /readiness auto-mapping (Tier 3 default, pre-mapped skip, idempotent). - 4 new tests for FoundryToolboxHealthCheck (Pending, NoEndpoint, Failed, Healthy). - 3 enhanced FoundryToolboxServiceTests with StartupStatus assertions. * .NET: Align FoundryToolboxService with tools-integration-spec (#5777 Part A) Bring Microsoft.Agents.AI.Foundry.Hosting's toolbox path into compliance with tools-integration-spec.md sections 2-4, 6.3, and 9. Empirically validated against tao-foundry-prj: the previous code (reading FOUNDRY_AGENT_TOOLSET_ENDPOINT, which the platform never injects) silently registered zero tools in production. Package changes (Microsoft.Agents.AI.Foundry.Hosting): - FoundryToolboxService.StartAsync now derives the toolbox proxy base URL from the platform-injected FOUNDRY_PROJECT_ENDPOINT and constructs the per-toolbox URL as {FOUNDRY_PROJECT_ENDPOINT}/toolboxes/{name}/mcp?api-version={ApiVersion} per spec sections 2-3. The legacy FOUNDRY_AGENT_TOOLSET_ENDPOINT env var is removed outright (preview package, no production consumers). - FoundryToolboxOptions.ApiVersion default flipped to 'v1' to match spec example. - FoundryToolboxBearerTokenHandler always sends the mandatory Foundry-Features: Toolboxes=V1Preview header per spec section 2, merging any additional flags supplied via the FOUNDRY_AGENT_TOOLSET_FEATURES env var. - FoundryToolboxBearerTokenHandler token scope changed from https://cognitiveservices.azure.com/.default to https://ai.azure.com/.default per spec section 4. - FoundryToolboxBearerTokenHandler propagates W3C trace context (traceparent, tracestate, baggage) from Activity.Current per spec section 6.3. Sample changes: - Hosted-Toolbox-AuthPaths and Hosted-Toolbox Program.cs, README.md, and .env.example corrected to describe the actual env-var contract (FOUNDRY_PROJECT_ENDPOINT auto-injected; AZURE_AI_PROJECT_ENDPOINT as the local-dev fallback). Removes the misleading 'auto-injected by Foundry runtime' claims for FOUNDRY_AGENT_TOOLSET_ENDPOINT. - Hosted-Toolbox-AuthPaths/agent.manifest.yaml declares the toolbox and model dependencies under resources[] per the AgentManifest schema so azd ai agent init users get them provisioned automatically. Tests: - 4 new FoundryToolboxServiceTests covering env-var derivation, EndpointOverride precedence, trailing-slash normalization, and the existing NoEndpoint behavior under the new env var name. - 4 new FoundryToolboxBearerTokenHandlerTests covering token scope, mandatory feature header always present, header merging with override, no duplicate mandatory flag, trace context propagation from Activity.Current, and no override of caller-set traceparent. - New FoundryProjectEndpointEnvFixture xUnit collection definition serializes env-var-mutating tests across FoundryToolboxServiceTests and FoundryToolboxHealthCheckTests, preventing parallel-execution races. - FoundryToolboxHealthCheckTests adjusted for the new env var name. * .NET: Drop ACA prereq from Hosted-Toolbox-AuthPaths README (#5777 Part B) Empirically verified that any Azure Cognitive Services MCP endpoint already in the Foundry project (e.g., a Language service MCP) accepts Entra tokens and can serve Paths 2 and 3 without deploying a separate Azure MCP Server to ACA. README updates: - Step 0 rewritten: 'Identify an Entra-authenticated MCP target in your project' instead of 'Deploy Azure MCP Server to Azure Container Apps' (the original azmcp-foundry-aca-mi setup is now optional, not required). - Auth-paths matrix updated to describe AAD-based connections targeting a Cognitive Services MCP URL (e.g., Language service) instead of an ACA URL. - Step 2 connections table updated: the Entra ID category is now a single 'AAD' authType. The original 'Agent Identity' vs 'Project Managed Identity' as selectable connection sub-types is NOT exposed via the ARM control plane today; the platform selects the calling principal contextually. Both connections in the walkthrough share the same shape and target. - Added an explicit RBAC note: the agent identity AND project MI must hold the required role (typically Cognitive Services User) on the target resource; without it the MCP server returns HTTP 401 even though the connection wiring is correct. - Toolbox tool entries renamed lang_entra_agent / lang_entra_project to match the new connection names. Empirical validation supporting these changes is captured in the session plan.md (Part B addendum). * .NET: Document correct connection shape for Hosted-Toolbox-AuthPaths Paths 2/3 (#5777) Updates the sample README with the verified connection shape and RBAC procedure for Microsoft Entra agent-identity and project-managed-identity MCP authentication: - Connection authType values: AgenticIdentityToken (agent identity) and ProjectManagedIdentity (project MI), both with category=RemoteTool. - Top-level audience property required; for Cognitive Services targets the value is https://cognitiveservices.azure.com. - Connections created via ARM REST (the Foundry portal wizard does not yet expose these authTypes). - RBAC grants target the project's shared agent identity blueprint principal (project.properties.agentIdentity.agentIdentityId) for Path 2 and the project's system-assigned MI (project.identity.principalId) for Path 3. - Troubleshooting table updated with the audience-mismatch symptom and the startup-cache behavior of FoundryToolboxService. * .NET: Drop Path 3 (project MI) and align with new agent model in Hosted-Toolbox-AuthPaths (#5777) Updates the sample to use only the new Foundry agent object model and removes the project managed identity path: - Auth-path matrix reduced to four paths: key, Entra agent identity, custom OAuth, inline authorization. Project managed identity is moved into a note describing when it applies (multiple agents sharing access) rather than as a documented sample path. - RBAC instructions reference the agent's own instance_identity.principal_id from the agent ARM resource (new agent object model) instead of the project's shared agent identity blueprint (legacy model). - Step 2 (connections) creates only the AgenticIdentityToken connection. - Step 3 (toolbox tools) lists four tool entries instead of five. - Sample prompts and troubleshooting table updated to match. * .NET: Restore Path 3 (project MI) to Hosted-Toolbox-AuthPaths matrix (#5777) The sample's purpose is to enumerate every authentication path a Foundry toolbox can drive, not to pick one. Path 3 belongs alongside the other four with explicit guidance for when each path is the right choice. - Path 3 (project managed identity, authType=ProjectManagedIdentity) restored to the matrix with a 'When to pick this' column. - Step 2 (connections) provisions both lang-mcp-agent-id and lang-mcp-project-mi via ARM REST. - Step 3 (toolbox) lists five tool entries (one per path). - RBAC instructions cover both the agent's instance identity (Path 2) and the project's system-assigned MI (Path 3). - Sample prompts include all five paths. - Troubleshooting table updated accordingly. * .NET: Fix duplicate line in Hosted-Toolbox-AuthPaths README (#5777) * .NET: Fix broken markdown link to ToolCallingApprovalHostedAgentFixture (#5777) * .NET: Fix relative path depth in markdown link (#5777) * .NET: Address Copilot review feedback for #5777 - FoundryToolboxHealthCheck description: rename FOUNDRY_AGENT_TOOLSET_ENDPOINT → FOUNDRY_PROJECT_ENDPOINT (stale reference; operator-facing in /readiness body). - FoundryToolboxStartupStatus.NoEndpoint XML doc: same rename. - ServiceCollectionExtensions XML docs: same rename + URL shape update. - Foundry.Hosting.IntegrationTests.TestContainer: remove explicit app.MapGet('/readiness') — now redundant + would conflict with the auto-mapped readiness route from MapFoundryResponses. - Hosted-Toolbox-AuthPaths agent.manifest.yaml: parameterize TOOLBOX_NAME via {{TOOLBOX_NAME}} template substitution and declare it under parameters with a default of 'auth-paths-toolbox' so the README's 'use any name' guidance actually works for hosted deployments. * .NET: Address Copilot review round 2 — fallback env + dedup + naming (#5777) - FoundryToolboxService.StartAsync: fall back to AZURE_AI_PROJECT_ENDPOINT when FOUNDRY_PROJECT_ENDPOINT is absent. Matches the local-dev convention used by the samples and resolves the doc/code mismatch flagged in review. - FoundryToolboxHealthCheck description updated for the fallback. - AddFoundryToolboxes: guard against duplicate health-check registration via an explicit name-uniqueness check on HealthCheckServiceOptions.Registrations. AddCheck<T>(name, ...) does not dedupe by name, so repeated AddFoundryToolboxes calls would have registered multiple instances. - FoundryToolboxOptions.EndpointOverride doc: clarify URL becomes {EndpointOverride}/toolboxes/{name}/mcp (was missing /toolboxes/ segment). - Hosted-Toolbox sample (Program.cs + README): switch FOUNDRY_TOOLBOX_NAME to TOOLBOX_NAME (the FOUNDRY_* prefix is reserved by the platform), default changed from 'my-toolset' to 'my-toolbox', terminology updated from 'Toolset' to 'Toolbox'. - FoundryToolboxServiceTests: 2 test renames to reflect what they actually assert (StartupStatus + FailedToolboxNames, not URL shape directly). - Tests adjusted to clear both env vars in NoEndpoint scenarios. * .NET: Fix stale NoEndpoint XML doc and misleading test comment (#5777) Update FoundryToolboxStartupStatus.NoEndpoint XML doc to mention both FOUNDRY_PROJECT_ENDPOINT and AZURE_AI_PROJECT_ENDPOINT (the service checks both since the fallback was added). Fix test comment that claimed URL derivation validation when the test only asserts on StartupStatus and FailedToolboxNames. * Remove OAuth consent path from AuthPaths sample, keep four working auth paths The interactive OAuth identity passthrough path needs a protocol gap closed in the hosting package (the proprietary oauth_consent_request item is not representable through the OpenAI/MEAI abstractions), so it is deferred to a separate spike branch. This strips the OAuth path from the AuthPaths sample, the companion REPL client, the agent manifest, and the docs, then renumbers the inline Authorization path so the sample teaches four contiguous paths: API key via connection, Entra agent identity, Entra project managed identity, and inline Authorization (anti-pattern). Package code is unchanged; the consent infrastructure already present in main stays as baseline. Both samples build with --warnaserror and all 246 hosting unit tests pass. * .NET: Drop project MI auth path and dedicated client from Hosted-Toolbox-AuthPaths (#5777) Live validation against tao-foundry-prj showed the ProjectManagedIdentity path failing with an unresolved token audience 401, so the sample now ships three working auth paths instead of four: connection key, agent managed identity, and inline Authorization. Changes: - Remove the project managed identity path from the AuthPaths sample matrix, prerequisites, connections, toolbox table, prompts, Program.cs instructions and agent.manifest.yaml. - Delete the near duplicate Hosted-Toolbox-AuthPaths-Client project and remove it from the solution. The README now drives the agent with the shared SimpleAgent REPL via AsAIAgent(agentEndpoint). - Correct the troubleshooting note: the Foundry toolbox tools/list is all or nothing, so one bad source returns -32007, fails startup, and returns 424 for every path. Add the allowed_tools caveat that names must match the upstream server. - Mark the toolbox startup status and health check experimental under AgentsAIExperiments (MAAI001) instead of AIOpenAIResponses, and update the package NoWarn set accordingly. * .NET: Address PR review nits for Hosted-Toolbox-AuthPaths (#5777) - Remove duplicated NU1903 comment in Foundry.Hosting csproj. - Fix stale 'four-tool' cross-links in Hosted-Toolbox and Hosted-McpTools READMEs to describe the three-path toolbox driven by the shared SimpleAgent REPL. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * .NET: Address toolbox startup-status review feedback (#5777) - Rename FoundryToolboxStartupStatus.Failed to Unhealthy so it is the proper opposite of Healthy, and clarify the doc comment covers the partial-failure case. - Raise the missing-endpoint toolbox log from Information to Warning, since enabling toolboxes is an explicit opt-in and a silently disabled toolbox warrants a higher-severity signal. - Update unit tests and the AuthPaths README troubleshooting row accordingly. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * .NET: Reword toolbox-wiring comment to avoid hosting-layer internals (#5777) Address PR review feedback: explain how a Foundry Toolbox is attached using the public API (AddFoundryToolboxes vs the CreateHostedMcpToolbox marker) and observable behavior, instead of naming the internal AgentFrameworkResponseHandler type and FoundryToolboxService.Tools property. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
15 KiB
Hosted Toolbox — Authentication Paths
A hosted Foundry agent backed by a single Foundry Toolbox that bundles MCP tools using three different authentication paths. The educational surface lives in the toolbox configuration (which you provision in the Foundry portal) and in this README — the agent code itself is identical to the existing Hosted-Toolbox/ sample.
Drive the agent interactively across the auth paths with the shared Using-Samples/SimpleAgent/ REPL client, pointed at this agent.
What this sample teaches
| Aspect | This sample | Existing siblings |
|---|---|---|
| Toolbox marker pattern | FoundryAITool.CreateHostedMcpToolbox(name) + AddFoundryToolboxes(name) |
Same as Hosted-Toolbox/ |
| Tools per toolbox | Three MCP tools, each with a different auth method | Hosted-Toolbox/: typically one demo tool |
| Consumption | Server-side (Foundry resolves the marker) | Same |
| Client | Shared Using-Samples/SimpleAgent/ REPL, pointed at this agent |
Hosted-Toolbox/: any client |
Related samples:
Hosted-Toolbox/— simpler single-tool toolbox.Hosted-McpTools/— contrasts client-sideMcpClientvs server-sideHostedMcpServerToolfor non-toolbox MCP servers.
Authentication-path matrix
The sample's purpose is to enumerate every authentication path a Foundry toolbox can drive, so each path appears alongside the others. Pick the ones your scenario needs — each connection in a toolbox is independent.
| # | Auth method | MCP target | Connection authType |
What flows where | When to pick this |
|---|---|---|---|---|---|
| 1 | Key-based via project connection | GitHub MCP at https://api.githubcopilot.com/mcp |
CustomKeys |
A PAT stored as Authorization: Bearer <pat> lives in the Foundry connection. The toolbox proxy reads it server-side and injects on every MCP call. |
The upstream service only accepts API keys or PATs. |
| 2 | Microsoft Entra — agent identity | Any Azure Cognitive Services MCP endpoint your project can reach (e.g., Language service MCP) | AgenticIdentityToken |
Foundry mints an Entra token for the agent's own identity (instance_identity in the new agent object model), scoped to the connection's audience, and forwards it to the MCP server. The agent identity must hold the required role (typically Cognitive Services User) on the target resource. |
Per-agent least-privilege access to Entra-protected services. Recommended default for new agents. |
| 3 | Inline Authorization (anti-pattern) |
https://gitmcp.io/Azure/azure-rest-api-specs |
none | A literal bearer string lives on the toolbox tool entry's authorization field. Do not do this in production — there's no rotation, no secret store, no per-user identity. Shown for completeness. |
Local-dev or public MCP servers that accept any (or no) bearer. |
Prerequisites
0. (Path #2 only) Identify an Entra-authenticated MCP target
Path #2 requires an MCP server that accepts Microsoft Entra tokens. Any Azure Cognitive Services resource that exposes an MCP endpoint works — they all accept Entra ID tokens and gate access via standard RBAC.
The reference walkthrough below uses an Azure Language service MCP endpoint:
https://<your-language-service>.cognitiveservices.azure.com/language/mcp?api-version=2025-11-15-preview
Substitute any other Cognitive Services MCP endpoint you have. If your project has none, omit tool #2 from your toolbox — the remaining two paths still work.
RBAC for path #2
Grant the Cognitive Services User role on the target resource to the agent's instance identity. Find it on the agent ARM resource (Azure portal → your agent → JSON view) at instance_identity.principal_id. This is the principal the Foundry proxy uses when minting tokens for AgenticIdentityToken connections.
$lang = "/subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.CognitiveServices/accounts/<lang-svc>"
az role assignment create `
--assignee-object-id <agent-instance-identity-principal-id> `
--assignee-principal-type ServicePrincipal `
--role "Cognitive Services User" `
--scope $lang
Repeat for any additional Cognitive Services resources the agent identity needs to call.
The RBAC grant requires
Microsoft.Authorization/roleAssignments/writeon the target scope. In many enterprise subscriptions this needs a PIM JIT activation.
1. Foundry project + Azure AI User role
- An active Microsoft Foundry project (create one).
- The Azure AI User role on the project assigned to:
- The developer (you) creating the toolbox.
- The agent identity for tool invocation.
2. Create the project connections
The Entra-based connection (path #2) is not available in the Foundry portal connection wizard today. Create it via ARM REST:
$armToken = az account get-access-token --query accessToken -o tsv
$h = @{ Authorization = "Bearer $armToken"; "Content-Type" = "application/json" }
$proj = "/subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.CognitiveServices/accounts/<foundry-account>/projects/<project>"
$lang = "https://<lang-svc>.cognitiveservices.azure.com/language/mcp?api-version=2025-11-15-preview"
# Path 2 — agent identity
$body2 = @{ properties = @{
category = "RemoteTool"; target = $lang
authType = "AgenticIdentityToken"; audience = "https://cognitiveservices.azure.com"
isSharedToAll = $false
}} | ConvertTo-Json -Depth 5
az rest --method PUT --headers "Content-Type=application/json" `
--url "https://management.azure.com$proj/connections/lang-mcp-agent-id?api-version=2025-04-01-preview" `
--body $body2
Connection summary:
| Connection name (used by the toolbox) | category |
authType |
audience |
|---|---|---|---|
github-mcp-key |
CustomKeys |
CustomKeys |
n/a (key value carries Authorization: Bearer <pat>) |
lang-mcp-agent-id |
RemoteTool |
AgenticIdentityToken |
https://cognitiveservices.azure.com |
Path #3 (gitmcp.io) needs no connection — the auth lives on the toolbox tool entry itself.
The audience value is the token resource identifier of the target service — for any Cognitive Services resource it is https://cognitiveservices.azure.com. For other Azure services consult Agent identity — runtime token exchange.
3. Create the toolbox
In the Foundry portal → Tools → Add Toolbox. Name it auth-paths-toolbox (or whatever you prefer; export the name as TOOLBOX_NAME). Add three MCP tool entries:
Tool server_label |
server_url |
Auth |
|---|---|---|
github_pat |
https://api.githubcopilot.com/mcp |
project_connection_id: github-mcp-key |
lang_agent |
Your Language service MCP URL | project_connection_id: lang-mcp-agent-id |
gitmcp_inline |
https://gitmcp.io/Azure/azure-rest-api-specs |
authorization: "Bearer demo-only-not-real" (no project_connection_id) |
Each entry should also carry:
require_approval: never(this sample is focused on auth, not approval flows; seeToolCallingApprovalHostedAgentFixture.csfor that concern).- A tight
allowed_toolslist. GitHub MCP exposes ~50 tools; restrict to what you actually want the model to invoke. For example:github_pat→["search_issues", "list_pull_requests"]. Every name inallowed_toolsmust match a real tool on the upstream server — an unknown name (e.g.,get_issue, which GitHub MCP does not expose) makes the whole source fail enumeration. See the partial-failure note below.
Sidebar — what the toolbox-creation code looks like
This sample assumes the toolbox already exists; it does not provision one programmatically. For an end-to-end code example of toolbox creation from a publisher script (suitable for a CI/CD pipeline), see 02-agents/AgentsWithFoundry/Agent_Step25_FoundryToolboxMcp/Program.cs — its CreateSampleToolboxAsync helper uses AgentAdministrationClient.GetAgentToolboxes().CreateToolboxVersionAsync(...) and is the canonical pattern.
Run the agent
Set environment variables (or copy .env.example to .env and fill it in):
$env:AZURE_AI_PROJECT_ENDPOINT = "https://<account>.services.ai.azure.com/api/projects/<project>"
$env:AZURE_AI_MODEL_DEPLOYMENT_NAME = "gpt-4o"
$env:TOOLBOX_NAME = "auth-paths-toolbox"
Locally, the Foundry.Hosting package reads AZURE_AI_PROJECT_ENDPOINT as a fallback when FOUNDRY_PROJECT_ENDPOINT is absent. In the hosted Foundry runtime, the platform auto-injects FOUNDRY_PROJECT_ENDPOINT and the package builds the toolbox proxy URL as {FOUNDRY_PROJECT_ENDPOINT}/toolboxes/{TOOLBOX_NAME}/mcp?api-version=v1 per tools-integration-spec.md §2–§3.
Then sign in (az login) and start the server:
dotnet run --tl:off
The server logs at http://localhost:8088/. In Development it also maps the per-agent OpenAI route shape (MapDevTemporaryLocalAgentEndpoint()), so the shared SimpleAgent REPL client can reach it through AsAIAgent(agentEndpoint) — the only supported way to consume a hosted Foundry agent. In a separate terminal:
Against the local dev server (point the client at localhost; the {project} segment is a wildcard the server ignores):
cd ../Using-Samples/SimpleAgent
$env:AZURE_AI_PROJECT_ENDPOINT = "http://localhost:8088/api/projects/local"
$env:AZURE_AI_AGENT_NAME = "hosted-toolbox-auth-paths-agent"
dotnet run --tl:off
Against a deployed agent (point the client at the real project endpoint and the deployed agent name):
cd ../Using-Samples/SimpleAgent
$env:AZURE_AI_PROJECT_ENDPOINT = "https://<account>.services.ai.azure.com/api/projects/<project>"
$env:AZURE_AI_AGENT_NAME = "hosted-toolbox-auth-paths-agent"
dotnet run --tl:off
Either way the client derives the per-agent endpoint URL ({AZURE_AI_PROJECT_ENDPOINT}/agents/{AZURE_AI_AGENT_NAME}/endpoint/protocols/openai) and consumes the agent via AsAIAgent(agentEndpoint). Run az login first so the client can mint a bearer token.
Parallel-run warning:
Hosted-Toolbox/and otherHosted-*samples default to the same port (8088) and the same agent name slot. Always set a uniqueAGENT_NAME(this sample defaults tohosted-toolbox-auth-paths-agent) and stop other hosted samples before starting this one.
Sample prompts
One per auth path so each tool gets exercised at least once:
List the latest 3 issues in microsoft/agent-framework. # path #1 — GitHub MCP (key)
Detect the language of "Bonjour le monde". # path #2 — Language MCP (agent identity)
What's the latest API version for Microsoft.CognitiveServices? # path #3 — gitmcp.io (inline Authorization)
Troubleshooting / partial-failure semantics
AddFoundryToolboxes resolves the toolbox at startup by listing its tools via MCP tools/list. This enumeration is all-or-nothing: if any single tool source fails to enumerate, the Foundry toolbox proxy returns a top-level JSON-RPC error (-32007) instead of a partial list, the hosting package marks the toolbox startup as failed, /readiness returns 503, and every invoke against the agent returns HTTP 424 — even for the auth paths that are configured correctly. So one misconfigured connection or one bad allowed_tools entry bricks the whole agent at startup, not just at tool-call time. Get each source enumerating cleanly before deploying. Symptoms per auth path:
| Symptom | Likely cause |
|---|---|
| All invokes return HTTP 424 ("Failed Dependency") | One or more tool sources failed tools/list at startup (see all-or-nothing note above). Common causes: an allowed_tools name that does not exist on the upstream server, or an Entra connection whose token is rejected. Reproduce by calling the toolbox tools/list directly with your own token — a -32007 top-level error names the failing source. |
| HTTP 401 "audience is incorrect" | The connection's audience field is missing or does not match the OAuth resource identifier the target service accepts. For Cognitive Services targets, set audience: "https://cognitiveservices.azure.com". |
| HTTP 401 / 403 "principal does not have access" | Path #1: PAT expired or scope insufficient. Path #2: the agent's instance identity is missing the required role on the target resource. |
| Container reports zero tools but startup succeeded | FoundryToolboxService.StartAsync caches the tools/list result at startup. If a connection or RBAC grant changed after the container started, force a fresh container (re-deploy the agent version) — the cache won't pick up the change until then. |
| HTTP 404 from a tool call | Toolbox name mismatch (TOOLBOX_NAME vs the name in the portal), or the toolbox was deleted. |
| Server logs a warning "Neither FOUNDRY_PROJECT_ENDPOINT nor AZURE_AI_PROJECT_ENDPOINT is set; toolbox support is disabled" | Local dev without the env var set. The agent will load with zero tools and respond as if it has none. Set AZURE_AI_PROJECT_ENDPOINT (local-dev fallback) or FOUNDRY_PROJECT_ENDPOINT to your project endpoint. |
| Tools appear but model never invokes them | instructions: in Program.cs may not surface what each tool is for. Tighten the allowed_tools lists and rephrase prompts to mention the upstream service by name. |
Region and model compatibility
Foundry Toolboxes have region constraints; some tool types are limited to specific models. This sample defaults to gpt-4o, which works in all supported regions. For the full matrix, see the Foundry tools compatibility matrix.
Anti-pattern note for path #3
Inline authorization on a toolbox tool entry stores credentials inside the toolbox definition. There is no rotation, no per-user scoping, no secret-store integration. Use it only for:
- Public MCP servers that ignore the bearer (the
gitmcp.iocase demonstrated here). - Local development against a test MCP server with a throwaway token.
For everything else use project_connection_id and let the platform inject credentials.