Use Toolbox in a Hosted Agent
Hosted agents access Foundry-managed tools through a Toolbox MCP endpoint. Unlike prompt agents that wire tools directly, hosted agents connect to a single MCP-compatible endpoint that exposes all configured tools. The platform handles credential injection, token refresh, and policy enforcement.
๐ For endpoint format, MCP protocol details, auth, OAuth consent handling, testing, citation pattern, and troubleshooting, see toolbox-reference.md.
>
๐ For wiring a remote tool (catalog tile or generic MCP server) into a project connection that a toolbox can attach to, see foundry-tool-catalog.md.
>
๐ For the full list of supported tool types and their per-type fields, see agent-tools.md and the per-tool
tool-*.mdfiles.
๐ก **This skill is scoped to *consuming* an existing toolbox from agent code โ endpoint resolution, env-var contract, payload shape gathered before agent runtime, verification, and tracing. Toolbox and connection CRUD belongs in Foundry Toolkit (VS Code) or the Foundry Portal** โ those surfaces give you tool browsing, metadata, connection wizards, and validation. Use the imperative
azd aiCLI only for *operational* tasks (retarget the default version, smoke-test an endpoint).
โจ Recommendation: enable Tool Search
Before adding more than ~5 tools to a toolbox, add { "type": "toolbox_search_preview" } to the toolbox. This replaces the full tools/list shown to the model with two meta-tools โ tool_search (natural-language discovery) and call_tool (invoke a discovered tool) โ so context cost stays flat as the toolbox grows.
- The
toolbox_search_previewentry doesn't count toward the unnamed-tool-per-type limit. - All other tools in the toolbox are hidden from the initial
tools/listand surfaced only bytool_search(or by per-user auto-pinning of hot tools). - Pin specific high-traffic tools or add ranking-only keywords via
tool_configs.{tool_name}(withpin: trueandadditional_search_text). - In the agent's system prompt, instruct the model to call
tool_searchwhenever a needed capability isn't already visible.
Full configuration recipe in tool-tool-search.md and the public Tool Search (preview) docs.
Quick Reference
| Property | Value |
|---|---|
| Toolbox Docs | https://learn.microsoft.com/azure/foundry/agents/how-to/tools/toolbox |
| Tool Catalog Docs | https://learn.microsoft.com/azure/foundry/agents/concepts/tool-catalog |
| Tool Search Docs | https://learn.microsoft.com/azure/foundry/agents/how-to/tools/tool-search |
| Foundry Toolkit (VS Code) โ set up tools/toolboxes | https://code.visualstudio.com/docs/intelligentapps/tool-catalog |
| Foundry Portal | https://ai.azure.com/ |
| Default Sample (Python, Agent Framework + toolbox) | https://github.com/microsoft-foundry/foundry-samples/tree/main/samples/python/hosted-agents/agent-framework/responses/04-foundry-toolbox |
Python Hosted Agent โ responses (BYO) | https://github.com/microsoft-foundry/foundry-samples/tree/main/samples/python/hosted-agents/bring-your-own/responses |
Python Hosted Agent โ invocations (BYO) | https://github.com/microsoft-foundry/foundry-samples/tree/main/samples/python/hosted-agents/bring-your-own/invocations |
| C# (.NET) Hosted Agent + toolbox | https://github.com/microsoft-foundry/foundry-samples/tree/main/samples/csharp/hosted-agents/agent-framework/foundry-toolbox-server-side |
| Supported Toolbox Scenarios (sample-side reference) | https://github.com/microsoft-foundry/foundry-samples/blob/main/samples/python/hosted-agents/SUPPORTEDTOOLBOXSCENARIOS.md |
Resolve Toolbox Endpoint
If the user provides a toolbox name or endpoint URL, or the project already references a toolbox (e.g., in .env or agent.manifest.yaml) โ use it directly.
Otherwise, ask one question:
"Would you like to provide your toolbox endpoint? (you can create one with the Foundry Toolkit in VS Code or the Foundry Portal)"
Once the user supplies the toolbox name/endpoint โ either an existing one or a new one they create via the Foundry Toolkit or Foundry Portal โ set it on the agent (e.g., TOOLBOX_ENDPOINT in .env) and continue with verification.
Use the env var name
TOOLBOX_ENDPOINT(noFOUNDRY_prefix). The Foundry platform reservesFOUNDRY_-prefixed env vars and may silently overwrite them at runtime โ see toolbox-reference.md ยง Agent env contract.
When asking the question, always include the doc links inline for the manual options โ the Foundry Toolkit in VS Code and the Foundry Portal โ so the user knows where to go to create a tool/toolbox themselves. Don't just name the options; render them as clickable links every time.
Before printing out any step-by-step guidance for the Foundry Toolkit (VS Code) path, fetch and read Use Tool Catalog to connect tools and Toolboxes in Foundry Toolkit first, then summarize the relevant steps for them. Don't paraphrase from memory โ the Toolkit UI changes; quote the current doc.
Available tool types
The full set is documented in agent-tools.md and โ authoritatively โ in the public Toolbox docs (Configure tools). At time of writing the supported type values are:
type | Tool | Connection required? | Detail |
|---|---|---|---|
mcp | Remote MCP server (third-party via catalog, BYO OAuth, or generic) | Optional (none / static key / project MI / OAuth) | tool-mcp.md |
web_search | Web search (basic Bing; optional web_search.custom_search_configuration for Bing Custom Search to scope grounding to specific domains) | No (basic); Yes for Custom Search | tool-web-search.md |
azure_ai_search | Azure AI Search index | Yes (Search service connection) | tool-azure-ai-search.md |
code_interpreter | Sandboxed Python execution | No | tool-code-interpreter.md |
file_search | Vector-store-backed retrieval over uploaded files | No (vector store is part of the toolbox) | tool-file-search.md |
openapi | REST API exposed via an OpenAPI 3.x spec | Conditional (connection requires project_connection_id; managed_identity does not โ uses project MI + audience) | tool-openapi.md |
a2a_preview | Call another Foundry agent as a tool | Optional | tool-a2a.md |
work_iq_preview | Microsoft 365 work context (mail / meetings / files / chats) via Work IQ | Yes (Work IQ RemoteA2A OAuth connection; BYO Entra app; M365 Copilot license per user) | tool-work-iq.md |
fabric_iq_preview | Microsoft Fabric data (Ontology / Fabric data agent / Power BI semantic model) | Yes (Fabric IQ OAuth connection; tenant admin consent) | tool-fabric-iq.md |
toolbox_search_preview | Tool Search โ a directive (not a tool) that swaps tools/list for tool_search + call_tool meta-tools | No | tool-tool-search.md |
Adjacent (not a type in a toolbox version):
- Agent Memory โ use the
MemorySearchToolSDK class on prompt agents; for hosted agents, configure the memory store via the project (separate from the toolbox). See tool-memory.md. - Routines (preview) โ not a tool; an agent trigger (
schedule/timer/github_issue/custom) that invokes an existing agent. See the public Routines docs.
Information to Gather Before Building a Toolbox Payload
When the user asks to "add an MCP tool" or similar, never guess. Confirm each field before generating any JSON or azure.yaml snippet:
| # | Question | Why needed |
|---|---|---|
| 1 | MCP server URL? | The server_url field on the mcp tool entry |
| 2 | Auth type? none / key / mi / oauth | Determines whether a project connection is required and which shape to create (see foundry-tool-catalog.md) |
| 3 | Project connection name (if auth โ none) | The project_connection_id field; must already exist in the Foundry project |
| 4 | server_label | Short prefix for the tool names exposed by this server (e.g. myserver) |
| 5 | Toolbox name | The container that will hold the tool entries |
| 6 | Foundry project endpoint | Where the toolbox is created โ read from PROJECT_ENDPOINT / AZURE_AI_PROJECT_ENDPOINT (avoid FOUNDRY_-prefixed names) |
| 7 | Many tools planned? (> ~5) | If yes, also add { "type": "toolbox_search_preview" } so the model uses Tool Search instead of seeing the full list. |
Toolbox payload โ MCP with a project connection
{
"name": "<TOOLBOX_NAME>",
"description": "MCP server with key or OAuth auth",
"tools": [
{
"type": "mcp",
"server_label": "<LABEL>",
"server_url": "<SERVER_URL>",
"require_approval": "never",
"project_connection_id": "<CONNECTION_NAME>"
}
]
}Toolbox payload โ public MCP (no auth)
{
"name": "api-specs",
"description": "Public MCP server, no connection needed",
"tools": [
{
"type": "mcp",
"server_label": "api_specs",
"server_url": "https://gitmcp.io/Azure/azure-rest-api-specs",
"require_approval": "never"
}
]
}Toolbox payload โ large toolbox with Tool Search
{
"name": "big-toolbox",
"description": "Many tools โ model uses tool_search to discover",
"tools": [
{ "type": "toolbox_search_preview" },
{ "type": "web_search" },
{ "type": "azure_ai_search", "name": "docs_index", "project_connection_id": "search-conn", "index_name": "docs" },
{
"type": "mcp", "server_label": "github", "server_url": "<github-mcp-url>",
"project_connection_id": "gh-conn",
"tool_configs": {
"search_issues": { "pin": true, "additional_search_text": "GitHub issues bug tracking" },
"*": { "additional_search_text": "GitHub repositories code" }
}
}
]
}Declarative path via azd
If the project already uses azd ai agent init, prefer declaring the toolbox in azure.yaml so azd deploy provisions it and injects TOOLBOX_ENDPOINT automatically:
# Declare secret parameters first; azd will prompt for the value on `azd up`
# (or read it from `AZURE_<NAME>` env vars) and never store it in plaintext.
params:
- name: github_pat
type: securestring
resources:
- kind: connection
name: <CONNECTION_NAME>
target: <MCP_SERVER_URL>
category: remoteTool
credentials:
type: CustomKeys
keys:
# Header name comes from the catalog entry's x-ms-connection-parameters.
# {{ github_pat }} is resolved from the `params` block above.
Authorization: "Bearer {{ github_pat }}"
- kind: toolbox
name: agent-tools
tools:
- type: toolbox_search_preview # recommended for any toolbox > ~5 tools
- type: web_search
- type: mcp
server_label: <LABEL>
server_url: <MCP_SERVER_URL>
project_connection_id: <CONNECTION_NAME>See azd params reference for the full parameter syntax.
Operational helpers via azd ai CLI
The
azd aiCLI also exposesagent connection create,toolbox create,toolbox list, andtoolbox delete. Prefer Foundry Toolkit (VS Code) or the Foundry Portal for those โ the UI gives you tool browsing, connection wizards, and validation. The two commands below are the ones the skill should still drive directly because they're *operational*, not setup.
All commands require
--project-endpoint <PROJECT_ENDPOINT>(the value ofPROJECT_ENDPOINT, e.g.https://<account>.services.ai.azure.com/api/projects/<project>). To avoid repeating it, export it once:
>
$PE = "https://<account>.services.ai.azure.com/api/projects/<project>"
Retarget the default version โ azd ai toolbox update
Each toolbox version is immutable. The version an agent actually hits is the one marked * in version list โ i.e. the default version. Use update to point that pointer at any existing version (e.g. rollback to a known-good version after a bad publish).
# Inspect first โ current default is marked with '*'
azd ai toolbox version list my-toolbox --project-endpoint $PE
# Retarget the default
azd ai toolbox update my-toolbox --default-version 20 --project-endpoint $PE --no-prompt
# Verify (Default version / Shown version / Endpoint all reflect the new value)
azd ai toolbox show my-toolbox --project-endpoint $PE--default-versionis the only fieldupdateaccepts today.- Validated: switched
default-tbfrom version 21 โ 20 โ 21; bothshowand the computed MCP endpoint (.../toolboxes/<name>/versions/<n>/mcp?api-version=v1) tracked the change immediately.
End-to-end smoke test
After the toolbox is created (via Toolkit / Portal / azd), hit the MCP endpoint directly to confirm the tool is reachable before pointing an agent at it:
$TOK = az account get-access-token --resource "https://ai.azure.com" --query accessToken -o tsv
$H = @{
Authorization = "Bearer $TOK"
"Content-Type" = "application/json"
"Foundry-Features" = "Toolboxes=V1Preview"
}
$URL = "$PE/toolboxes/my-toolbox/mcp?api-version=v1"
$body = @{ jsonrpc = "2.0"; id = 1; method = "tools/list"; params = @{} } | ConvertTo-Json
(Invoke-RestMethod -Method POST -Uri $URL -Headers $H -Body $body).result.tools | Select-Object name?api-version=v1 and the Foundry-Features: Toolboxes=V1Preview header are both required.
Code Integration Patterns
The sample repo provides integration patterns for both Python and C#. Read the sample code and adapt it to the user's project.
Python samples:
| Sample | Framework | Protocol | When to use |
|---|---|---|---|
agent-framework/responses/04-foundry-toolbox/ โ recommended | Agent Framework (MAF) | Responses | Default choice |
bring-your-own/responses/langgraph-toolbox/ | LangGraph (BYO) | Responses | LangGraph hosted agent with toolbox |
bring-your-own/responses/bring-your-own-toolbox/ | Generic MCP (BYO) | Responses | Raw httpx MCP client โ works with any framework |
bring-your-own/invocations/toolbox/ | Generic MCP (BYO) | Invocations | Toolbox via Invocations protocol |
C# (.NET) samples:
| Sample | Description |
|---|---|
csharp/hosted-agents/agent-framework/foundry-toolbox-server-side/ โ recommended | Agent Framework agent with toolbox MCP (Responses protocol) |
Notes (apply to all patterns, both Python and C#):
- Auth: Inject a bearer token with scope
https://ai.azure.com/.defaulton every request (Python:httpx.Authsubclass; C#:DefaultAzureCredential+BearerTokenAuthenticationPolicy). - Header: Always include
Foundry-Features: Toolboxes=V1Preview. - MCP client: Pass
load_prompts=Falseโ the toolbox endpoint does not supportprompts/list. - Endpoint: Construct from
{project_endpoint}/toolboxes/{toolbox_name}/mcp?api-version=v1. - Multi-tool toolboxes: at most one tool per unnamed type, and unique
server_labelper MCP tool (see toolbox-reference.md).toolbox_search_previewdoesn't count toward this limit. - Tool naming: MCP-sourced tools are prefixed
{server_label}.{tool_name}; all other tool types use the entry'snamefield value (or the default tool name).
๐ก Tip: If MCP tools have
require_approval: "always"in_meta.tool_configuration, the agent runtime must ask the user for confirmation before invoking. The toolbox endpoint does not enforce this โ your agent code is responsible.
Tracing
All toolbox samples emit OpenTelemetry traces. No code changes are required to enable export to Azure Monitor โ it's purely a configuration step.
- Local development: set
APPLICATIONINSIGHTS_CONNECTION_STRINGin the agent's.env. - Deployed: the platform injects
APPLICATIONINSIGHTS_CONNECTION_STRINGautomatically when the Foundry project is linked to an Application Insights resource. - Per-framework instrumentation hooks (already present in the samples):
mafโmain.pycallsenable_instrumentation().langgraph/azdโ auto-instrumented byazure-ai-agentserver-core[tracing].- Viewing traces: Azure Portal โ Application Insights โ Investigate โ Transaction search (per-trace) or Application map (dependency graph).