你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
Warning
当您连接到非 Foundry 工具时,可能会产生费用,并且数据可能会被发送到 Foundry 的合规边界之外,并根据适用的条款和数据处理政策进行处理。 请参阅该工具的文档,了解如何管理对该工具的访问。
单个代理可以依赖于多个工具-API、模型上下文协议(MCP)服务器、连接器和流-每个工具都有自己的身份验证模型和拥有团队。 在整个组织扩展时,团队会独立地重新实现相同的工具,凭据被重复创建,治理变得不一致,并且几乎无法了解有何工具或者谁在使用它们。 开发人员停滞不前,不是因为模型不能够,而是因为工具集成成为瓶颈。
企业已有基础结构:网关、凭据保管库、策略和可观测性。 缺少的是将此基础结构打包成可重用、可发现和默认受管理的开发人员体验。
工具箱提供该体验。 定义一次特选的工具集,在 Foundry 中集中管理它们,并通过任何代理可以使用的单个 MCP 兼容终结点公开它们。 平台在运行时处理凭据注入、令牌刷新和企业策略强制实施。
工具箱通过四个支柱涵盖了整个工具生命周期,生成与消费现已推出。
| 支柱 | 地位 | 它所实现的功能是什么 |
|---|---|---|
| 构建 | 今天可用 | 选择工具,集中配置身份验证,并发布任何团队可以使用的可重用工具箱。 |
| 消费 | 今天可用 | 将任何代理连接到与 MCP 兼容的单个终结点,以动态发现和调用工具箱中的所有工具。 |
可以在 Foundry 中创建工具箱,但消费界面是开放的。 任何与 MCP 兼容的代理运行时或客户端都可以使用工具箱-包括使用任何框架生成的代理、已启用 MCP 的 IDE 和自定义代码。
由于工具箱是托管资源,因此无需更改代理中的代码即可添加、删除或重新配置工具。 代理始终连接到单个终结点。 工具箱版本控制使你能够显式控制更改何时生效 - 创建并测试新版本,然后在准备就绪时将其提升为默认值。 指向工具箱的每个代理都会自动选取升级的版本,无需更改代码,也无需重新部署。
在本文中,您将学到如何:
- 使用一个或多个工具创建工具箱。
- 获取工具包 MCP 终结点。
- 验证工具是否已正确加载。
- 将工具箱集成到托管代理中。
- 管理工具箱版本并将版本提升为默认值。
- 将护栏(RAI 策略)应用于工具箱版本。
有关每种工具类型的工具配置语法和身份验证选项,请参阅 “配置工具”。
功能支持
| 功能 | Python SDK | REST API | .NET SDK | JavaScript SDK | azd | Foundry 工具包 |
|---|---|---|---|---|---|---|
| 工具包更新、列出、获取和删除 | ✔️ | ✔️ | ✔️ | ✔️ | N/A | ✔️ |
| 工具箱版本创建 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
| 工具箱版本列表、获取和删除 | ✔️ | ✔️ | ✔️ | ✔️ | N/A | 不。 UI 仅显示最新版本。 |
| MCP 工具 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
| Web 搜索工具 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
| Azure AI 搜索工具 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
| 代码解释器工具 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
| 文件搜索工具 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
| OpenAPI 工具 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | 不 |
| 代理对代理工具(A2A) | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | 不 |
| Fabric IQ 工具 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
| 护栏 (RAI 策略) | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
| 技能参考 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | 不 |
| 工具搜索 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
| Work IQ 工具 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
| 浏览器自动化工具 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | 不 |
先决条件
正在进行的Microsoft Foundry 项目。
RBAC:为符合您场景的每个身份授予 Foundry 项目中的 Foundry 用户角色:
- 开发人员 (始终必需)-用于创建、更新和管理工具箱版本的标识。
- 代理标识 (如果使用托管代理时需要) - 在运行时调用工具的代理托管标识。
- 最终用户(仅 OAuth 流程需要)— 任何通过 OAuth 或 UserEntraToken 连接(例如,基于 OAuth 的 MCP 或用户 Entra 令牌(托管用户标识直通)流代理其标识的用户。
Foundry 项目需要位于支持的 区域之一。 工具箱中的单个工具类型受区域和模型进一步限制 ,并非所有工具类型都可用于每个区域或每个模型。 请参阅 区域和模型兼容性。
从 Visual Studio Code 市场安装 Microsoft Foundry Toolkit for Visual Studio Code 扩展。
Python SDK:
pip install azure-ai-projects azure-identity.NET SDK:
dotnet add package Azure.AI.Projects --prerelease和dotnet add package Azure.IdentityJavaScript SDK:
npm install @azure/ai-projects @azure/identityAzure Developer CLI:安装 Azure Developer CLI(
azd、1.25 或更高版本)和统一 Foundry CLI 扩展捆绑包:# Install the unified bundle (provides azd ai agent, connection, inspector, # project, routine, skill, and toolbox). azd ext install microsoft.foundry
重要
- 工具箱最多支持每个工具类型一个工具,没有
name字段(Web 搜索、Azure AI 搜索、代码解释器、文件搜索)。 若要包含同一工具类型的多个实例,请在每个实例上设置一个唯一的name实例来区分它们。 包含两个没有name的相同类型的实例会返回invalid_payload错误。 有关详细信息,请参阅 多个工具类型。 - 将一个
description添加到工具箱中的每个工具,以帮助模型为每个请求选择正确的工具。 - 仔细查看每个工具的文档,详细了解各个工具设置、限制和警告。
Tip
如果你使用 GitHub Copilot for Azure 来搭建使用工具箱的托管智能体,以下技能引用描述了智能体必须实现的相同终结点契约(环境变量、标头、MCP 协议、引用模式和故障排除)。
- Toolbox 参考 — 终结点格式、MCP 协议、OAuth 同意处理、引文模式和故障排除。
- 在托管代理中使用工具箱 — 终结点解析、环境变量约定、有效负载结构、代码集成模式和追踪。
步骤 1:创建工具箱版本
根据所需的工具创建工具箱版本。
from azure.identity import DefaultAzureCredential
from azure.ai.projects import AIProjectClient
from azure.ai.projects.models import MCPTool, ToolboxSearchPreviewTool, WebSearchTool
# Create Foundry project client
endpoint = "https://<your-foundry-account>.services.ai.azure.com/api/projects/<your-project>"
project = AIProjectClient(
endpoint=endpoint,
credential=DefaultAzureCredential(),
)
# Create toolbox version with web search and MCP tools
toolbox_version = project.toolboxes.create_toolbox_version(
name="my-toolbox",
description="Toolbox with web search and an MCP server",
tools=[
WebSearchTool(),
MCPTool(
server_label="myserver",
server_url="https://your-mcp-server.example.com",
require_approval="never",
project_connection_id="my-key-auth-connection",
),
ToolboxSearchPreviewTool(),
],
)
print(f"Created toolbox: {toolbox_version.name}, version: {toolbox_version.version}")
using Azure.Identity;
using Azure.AI.Projects;
// Create Foundry project client
var projectEndpoint = "https://<your-foundry-account>.services.ai.azure.com/api/projects/<your-project>";
AIProjectClient projectClient = new(new Uri(projectEndpoint), new DefaultAzureCredential());
AgentToolboxes toolboxClient = projectClient.AgentAdministrationClient.GetAgentToolboxes();
ProjectsAgentTool webTool = ProjectsAgentTool.AsProjectTool(
ResponseTool.CreateWebSearchTool());
ProjectsAgentTool mcpTool = ProjectsAgentTool.AsProjectTool(ResponseTool.CreateMcpTool(
serverLabel: "myserver",
serverUri: new Uri("https://your-mcp-server.example.com"),
toolCallApprovalPolicy: new McpToolCallApprovalPolicy(
GlobalMcpToolCallApprovalPolicy.NeverRequireApproval
)
));
ToolboxSearchPreviewTool searchTool = new() { Name = "ToolBoxSearch" };
ToolboxVersion toolboxVersion = await toolboxClient.CreateToolboxVersionAsync(
toolboxName: "my-toolbox",
tools: [webTool, mcpTool, searchTool],
description: "Toolbox with web search, MCP, and tool search"
);
Console.WriteLine($"Created toolbox: {toolboxVersion.Name}, version: {toolboxVersion.Version}");
POST {project_endpoint}/toolboxes/my-toolbox/versions?api-version=v1
Authorization: Bearer {token}
Content-Type: application/json
{
"description": "Toolbox with web search, MCP, and tool search",
"tools": [
{
"type": "web_search",
"description": "Search the web for current information"
},
{
"type": "mcp",
"server_label": "myserver",
"server_url": "https://your-mcp-server.example.com",
"require_approval": "never",
"project_connection_id": "my-key-auth-connection"
},
{
"type": "toolbox_search_preview"
}
]
}
注意
获取持有者令牌时使用令牌范围 https://ai.azure.com/.default 。
import { DefaultAzureCredential } from "@azure/identity";
import { AIProjectClient } from "@azure/ai-projects";
// Create Foundry project client
const projectEndpoint = "https://<your-foundry-account>.services.ai.azure.com/api/projects/<your-project>";
const project = new AIProjectClient(projectEndpoint, new DefaultAzureCredential());
const toolboxVersion = await project.toolboxes.createVersion(
"my-toolbox",
[
{
type: "web_search",
description: "Search the web for current information",
},
{
type: "mcp",
server_label: "myserver",
server_url: "https://your-mcp-server.example.com",
require_approval: "never",
project_connection_id: "my-key-auth-connection",
},
{ type: "toolbox_search_preview" },
],
{
description: "Toolbox with web search, MCP, and tool search",
},
);
console.log(`Created toolbox: ${toolboxVersion.name}, version: ${toolboxVersion.version}`);
使用 Microsoft Foundry Toolkit for Visual Studio Code 扩展从 Tools 视图中创建和发布工具箱。
- 在活动栏中选择 Foundry Toolkit 。
- 在 “我的资源”下,展开 项目名称>“工具”。
- 选择“ + 添加工具箱” 图标。
- 在 “生成自定义工具箱 ”选项卡上,输入工具箱名称和说明,并添加所需的工具。
- 若要启用基于意向的工具路由,请选择 “工具搜索”。
- 选择发布。
发布新工具箱将创建其第一个版本。 该版本自动成为默认版本。
使用统一 microsoft.foundry 扩展捆绑包(请参阅 先决条件),在两个步骤中创建工具箱:
- 使用
azd ai connection create注册工具箱所引用的每个项目连接(每条凭据记录调用一次)。 - 使用
azd ai toolbox create --from-file <toolbox.yaml>创建工具箱。 YAML 按名称引用连接,并且永远不会嵌入凭据。
对于每个连接类型和身份验证类型,模式都是相同的:
每个 shell 只需设置一次当前活动项目:
azd ai project set $PROJECT_ENDPOINT与
azd ai connection create建立连接。 标志因身份验证类型而异,但命令形状始终为:azd ai connection create <name> \ --kind <remote-tool|remote-a2a|cognitive-search|GroundingWithCustomSearch> \ --target <endpoint-url> \ --auth-type <none|custom-keys|api-key|oauth2|user-entra-token|project-managed-identity|agentic-identity> \ [--custom-key "Header=Value" | --key <key> | --client-id ... --client-secret ... --authorization-url ... --token-url ... | --audience <aad-resource-uri>]使用
azd ai connection list和azd ai connection show <name>检查连接以及azd ai connection delete <name> --force删除连接。编写一个按名称引用一个或多个现有连接的工具箱 YAML。 YAML 永远不会嵌入凭据:
# my-toolbox.yaml description: <human-readable description> connections: - name: <project-connection-name> # must already exist in the project # Optional: add connectionless built-in tools and policies. tools: - type: web_search name: web - type: code_interpreter container: { type: auto } name: code # Tool search is connectionless. - type: toolbox_search_preview # For Azure AI Search, set the index in the tool entry: # - type: azure_ai_search # name: search # azure_ai_search: # indexes: # - project_connection_id: <azure-ai-search-connection-name> # index_name: <search-index-name> # For Bing Custom Search, set the instance in the tool entry: # - type: bing_custom_search # name: bing # custom_search_configuration: # project_connection_id: <bing-connection-name> # instance_name: <bing-instance-name> # Optional: attach existing project skills as MCP resources. skills: - name: <skill-name> # uses the skill's default version - name: <other-skill> version: "2" # pin to a specific skill version (string) policies: rai_config: rai_policy_name: <policy-name> # must already exist on the project至少有一个
connections,skills或者tools必须是非空的。 技能引用必须指向同一 Foundry 项目中已存在的技能;请参阅 在 Foundry 中使用技能 以使用azd ai skill create创建这些技能。 有关端到端工具搜索设置详细信息,请参阅 “使用工具搜索”。从该文件创建工具箱:
azd ai toolbox create <toolbox-name> --from-file ./my-toolbox.yaml第一个版本将自动成为默认版本。 使用
azd ai toolbox list、azd ai toolbox show <name>管理和azd ai toolbox version list <name>azd ai toolbox delete <name> --force管理工具箱。
示例:具有基于密钥的身份验证的 MCP 服务器
# 1. Create the connection
azd ai connection create my-gh-conn \
--kind remote-tool \
--target https://api.githubcopilot.com/mcp/ \
--auth-type custom-keys \
--custom-key "Authorization=Bearer $GITHUB_PAT"
# 2. Create the toolbox
azd ai toolbox create my-toolbox \
--from-file ./my-toolbox.yaml \
--no-prompt
# my-toolbox.yaml
description: GitHub MCP toolbox
connections:
- name: my-gh-conn
步骤 2:获取工具箱 MCP 终结点
存在两种终结点模式,具体取决于角色:
| 作用 | 端点 | 何时使用 |
|---|---|---|
| 工具箱开发人员 | {project_endpoint}/toolboxes/{toolbox_name}/versions/{version}/mcp?api-version=v1 |
先测试或验证特定版本,然后再将其提升为默认值。 |
| 工具箱使用者 | {project_endpoint}/toolboxes/{toolbox_name}/mcp?api-version=v1 |
将代理连接到工具箱。 始终提供 default_version。 创建的第一个版本会自动设置为默认值。 |
用你自己的值替换占位符
-
{project_endpoint}是您的 Foundry 项目终结点,格式为https://<your-foundry-account>.services.ai.azure.com/api/projects/<your-project>。 从 Foundry 门户中项目的 概述 页复制它,或者从适用于 Visual Studio Code 的 Microsoft Foundry 工具包的 工具箱 视图中的 终结点 URL 列复制它。 -
{toolbox_name}和{version}是你在步骤 1中创建的工具箱名称和版本。
Tip
将代理连接到 工具箱消费者 端点。 它始终提供 default_version,因此您可以在不更改代理代码或重新部署的情况下推广新版本。 保留工具箱开发者(特定版本的)端点,用于在将该版本正式推广之前对其进行测试。
注意
新工具箱的第一个版本将自动提升为 default_version (v1)。 如果需要稍后更改默认值,请参阅 将版本提升为默认值。
在适用于 Visual Studio Code 的 Microsoft Foundry Toolkit 扩展中,从 Toolboxes 视图复制工具箱使用方终结点。
- 在活动栏中选择 Foundry Toolkit 。
- 在 “我的资源”下,展开 项目名称>“工具”。
- 在 “工具箱 ”选项卡上,找到工具箱。
- 在 “终结点 URL ”列中,复制终结点。
端点 URL 值是工具包使用者端点。 若要构造特定于版本的终结点,请使用上表中所示的开发人员模式。
步骤 3:验证工具可用性
在运行完整智能体之前,请使用 MCP 客户端 SDK 访问终结点,以确认工具包加载了预期工具。 使用 特定于版本的终结点 验证版本,然后再将其提升为默认值。
安装 MCP 客户端 SDK:
pip install mcp
连接到工具箱并列出工具
import asyncio
from azure.identity import DefaultAzureCredential
from mcp.client.streamable_http import streamablehttp_client
from mcp import ClientSession
url = "https://<account>.services.ai.azure.com/api/projects/<proj>/toolboxes/<name>/versions/<version>/mcp?api-version=v1"
token = DefaultAzureCredential().get_token("https://ai.azure.com/.default").token
headers = {
"Authorization": f"Bearer {token}",
}
async def verify_toolbox():
async with streamablehttp_client(url, headers=headers) as (read, write, _):
async with ClientSession(read, write) as session:
await session.initialize()
# List available tools
tools_result = await session.list_tools()
print(f"Tools found: {len(tools_result.tools)}")
for tool in tools_result.tools:
print(f" - {tool.name}: {(tool.description or '')[:80]}")
# Call a tool (replace with actual tool name and arguments)
result = await session.call_tool("<tool_name>", arguments={})
print(result)
asyncio.run(verify_toolbox())
注意
使用 REST API 选项卡验证.NET中的工具可用性,或使用 Python MCP 客户端 SDK。
在升级版本之前,请使用特定于版本的终结点 (/versions/{version}/mcp) 来验证版本。
1.初始化 MCP 会话:
POST {project_endpoint}/toolboxes/{toolbox_name}/versions/{version}/mcp?api-version=v1
Authorization: Bearer {token}
Content-Type: application/json
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}
2.发送初始化的通知:
POST {project_endpoint}/toolboxes/{toolbox_name}/versions/{version}/mcp?api-version=v1
Authorization: Bearer {token}
Content-Type: application/json
{"jsonrpc":"2.0","method":"notifications/initialized"}
3. 列出可用工具:
POST {project_endpoint}/toolboxes/{toolbox_name}/versions/{version}/mcp?api-version=v1
Authorization: Bearer {token}
Content-Type: application/json
{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}
4.调用工具:
POST {project_endpoint}/toolboxes/{toolbox_name}/versions/{version}/mcp?api-version=v1
Authorization: Bearer {token}
Content-Type: application/json
{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"<TOOL_NAME>","arguments":{}}}
安装 MCP 客户端 SDK:
npm install @modelcontextprotocol/sdk
连接到工具箱并列出工具
import { DefaultAzureCredential } from "@azure/identity";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
const url = "https://<account>.services.ai.azure.com/api/projects/<proj>/toolboxes/<name>/versions/<version>/mcp?api-version=v1";
const credential = new DefaultAzureCredential();
const token = await credential.getToken("https://ai.azure.com/.default");
const transport = new StreamableHTTPClientTransport(
new URL(url),
{
requestInit: {
headers: {
Authorization: `Bearer ${token.token}`,
},
},
},
);
const client = new Client({ name: "test", version: "1.0" });
await client.connect(transport);
// List available tools
const toolsResult = await client.listTools();
console.log(`Tools found: ${toolsResult.tools.length}`);
for (const tool of toolsResult.tools) {
console.log(` - ${tool.name}: ${(tool.description || "").slice(0, 80)}`);
}
// Call a tool (replace with actual tool name and arguments)
const result = await client.callTool({ name: "<tool_name>", arguments: {} });
console.log(result);
await client.close();
使用步骤 2 中的终结点和一个搭建的托管代理样本来验证 VS Code 中工具箱的加载。
- 在 Foundry Toolkit 的 “我的资源>你的项目名称>工具”下,找到要测试的工具箱。
- 选择 基架代码模板。
- 出现提示时选择项目文件夹。
- 按照生成的
README.md步骤安装依赖项、配置环境变量,并在本地运行示例。 - 使用 代理检查器 或运行
python main.py来确认工具箱工具加载和响应。
在发布新工具箱版本之前进行版本特定验证时,请使用此步骤中的Python或REST API选项卡。
注意
使用 REST API 选项卡验证工具可用性,或使用 Python MCP 客户端 SDK。
检查 - 初始化:HTTP 200。 如果跳过初始化步骤,后续调用将失败。
检查 — tools/list:
len(tools) > 0- 空表示未正确预配工具箱版本。每个工具都有
name,description以及inputSchema。 有关工具命名约定,请参阅 MCP 规范。inputSchema有一个properties字段(某些 MCP 服务器省略此字段,这会中断 OpenAI)。工具名称按工具类型划分命名空间:
工具类型 工具名称格式 示例: MCP {server_label}.{tool_name}myserver.some_toolOpenAPI {openapi_name}.{operationId}weatherapi.getForecastA2A 工具的 name(智能体名称),如果省略name则为连接名称myagent所有其他工具类型 name字段值或默认工具名称web_searchMCP 工具包括一个包含
_meta.tool_configuration运行时设置的块,例如require_approval。 请参阅 “处理工具审批要求”。请注意调用步骤的确切参数名称(例如
queryvsqueries)。
检查 - tools/call:
- 没有顶级
error字段。 如果存在,请检查error.code。 有关标准 MCP 错误代码,请参阅 MCP 规范:-
-32006需要 OAuth 授权同意(从error.message中提取 URL)。 - 其他代码→服务器端故障。
-
-
result.content[]包含带有"type": "text"的条目 - 这是工具输出。 - 对于 AI 搜索,请检查
result.structuredContent.documents[]的区块元数据(title、url、id、score)。 - 对于文件搜索,检查
result.content[].resource._meta以获取分块元数据(title、file_id、document_chunk_id、score)。 - 对于 Web 搜索,请检查
result.content[].resource._meta.annotations[]的 URL 引用(type、url、title、start_index、end_index)。 - 对于 Fabric IQ,请检查
result.structuredContent.documents[]是否有引文区块。 每个文档都包含title和url的字段,这些字段指向用于为响应提供依据的 Fabric 项(Ontology、数据代理或 Power BI 语义模型)。 - 在文本内容中留意
"ServerError",这表示工具已执行但遇到内部错误。
tools/call工具特定的参数示例:
| 工具类型 | 参数 |
|---|---|
| AI 搜索 | {"query": "search text"} |
| 文件搜索 | {"queries": ["search text"]} |
| 代码解释器 | {"code": "print(2 ** 100)"} |
| Web 搜索 | {"search_query": "weather in seattle"} |
| A2A | {"message": {"parts": [{"type": "text", "text": "Hello"}]}} |
| 织物智能 | 因公开工具而异 - 通常 {"query": "..."} 适用于查询工具 |
| 工作 IQ | {"message": {"parts": [{"type": "text", "text": "Hello"}]}} |
| MCP | {"query": "what is agent service"} |
步骤 4:将工具箱集成到代理中
LangGraph
请参阅完整示例以查看完整实现。
.env 文件:
FOUNDRY_PROJECT_ENDPOINT=https://<account>.services.ai.azure.com/api/projects/<project>
TOOLBOX_ENDPOINT=https://<account>.services.ai.azure.com/api/projects/<project>/toolboxes/<toolbox-name>/versions/<version>/mcp?api-version=v1
TOOLBOX_NAME=agent-tools
AZURE_AI_MODEL_DEPLOYMENT_NAME=gpt-4o
main.py(键模式):
from langchain_azure_ai.tools import AzureAIProjectToolbox
toolbox = AzureAIProjectToolbox(toolbox_name=TOOLBOX_NAME)
tools = await toolbox.get_tools()
重要
类 langchain_azure_ai.tools.AzureAIProjectToolbox 要求 langchain-azure-ai[tools]>1.2.3。
Microsoft代理框架
使用 Agent Framework SDK 中的 MCPStreamableHTTPTool 直接连接到工具包 MCP 终结点。
.env 文件:
FOUNDRY_PROJECT_ENDPOINT=https://<account>.services.ai.azure.com/api/projects/<project>
TOOLBOX_ENDPOINT=https://<account>.services.ai.azure.com/api/projects/<project>/toolboxes/<toolbox-name>/versions/<version>/mcp?api-version=v1
AZURE_AI_MODEL_DEPLOYMENT_NAME=gpt-4o
main.py(键模式):
# Auth: wrap token provider in an httpx.Auth subclass
credential = DefaultAzureCredential()
token_provider = get_bearer_token_provider(credential, "https://ai.azure.com/.default")
http_client = httpx.AsyncClient(
auth=_ToolboxAuth(token_provider),
timeout=120.0,
)
# Toolbox MCP endpoint (platform-injected at runtime via TOOLBOX_ENDPOINT)
TOOLBOX_ENDPOINT = "https://<account>.services.ai.azure.com/api/projects/<project>/toolboxes/<toolbox-name>/versions/<version>/mcp?api-version=v1"
# Connect MCPStreamableHTTPTool to the toolbox endpoint
mcp_tool = MCPStreamableHTTPTool(
name="toolbox",
url=TOOLBOX_ENDPOINT,
http_client=http_client,
load_prompts=False,
)
agent = chat_client.as_agent(
name="my-toolbox-agent",
instructions="You are a helpful assistant with access to Foundry toolbox tools.",
tools=[mcp_tool],
)
ResponsesAgentServerHost().run()
请参阅完整示例以查看完整实现。
Copilot SDK
使用 GitHub Copilot SDK 构建一个以工具箱驱动的代理,该代理将 Copilot 的工具调用桥接至 Foundry 工具箱 MCP 端点。
注意
Copilot SDK 拒绝包含点的工具名称。 桥会自动将工具名称中的.替换为_。 例如, myserver.get_info 变为 myserver_get_info.
.env 文件:
GITHUB_TOKEN=<your-github-token>
TOOLBOX_ENDPOINT=https://<account>.services.ai.azure.com/api/projects/<project>/toolboxes/<toolbox-name>/versions/<version>/mcp?api-version=v1
agent.py (关键模式 — MCP 桥):
# 1. Open an MCP session to the toolbox endpoint
bridge = McpBridge(endpoint=TOOLBOX_ENDPOINT, token=_get_toolbox_token())
await bridge.initialize()
mcp_tools = await bridge.list_tools()
# 2. Map MCP tool list to Copilot SDK tool definitions
# Dots in tool names are replaced with underscores (Copilot SDK requirement)
copilot_tools = [
{
"name": t["name"].replace(".", "_"),
"description": t.get("description", ""),
"parameters": t.get("inputSchema", {}),
}
for t in mcp_tools
]
# 3. Wire tool calls back to the MCP session
async def tool_handler(name: str, arguments: dict) -> str:
return await bridge.call_tool(name.replace("_", ".", 1), arguments)
# 4. Run the Copilot SDK agent
agent = Agent(
tools=copilot_tools,
tool_handler=tool_handler,
token=os.environ["GITHUB_TOKEN"],
)
Microsoft代理框架
使用 Agent Framework SDK 的ResponsesServer和自定义ToolboxMcpClient,通过 MCP 终结点发现和调用工具箱工具。
环境变量:
AZURE_OPENAI_ENDPOINT=https://<account>.services.ai.azure.com
AZURE_AI_MODEL_DEPLOYMENT_NAME=gpt-4o
TOOLBOX_MCP_ENDPOINT=https://<account>.services.ai.azure.com/api/projects/<project>/toolboxes/<toolbox-name>/versions/<version>/mcp?api-version=v1
Program.cs(键模式):
using Azure.AI.AgentServer.Responses;
using Azure.AI.AgentServer.Responses.Models;
using Azure.AI.OpenAI;
using Azure.Identity;
using Microsoft.Extensions.DependencyInjection;
using OpenAI.Chat;
// Azure OpenAI endpoint and model deployment
var openAiEndpoint = "https://<account>.services.ai.azure.com";
var deployment = "gpt-4o"; // supports all toolbox tool types
// Toolbox MCP endpoint (platform-injected at runtime via TOOLBOX_MCP_ENDPOINT)
var toolboxEndpoint = "https://<account>.services.ai.azure.com/api/projects/<project>/toolboxes/<toolbox-name>/versions/<version>/mcp?api-version=v1";
// Azure OpenAI client
var credential = new DefaultAzureCredential();
var openAIClient = new AzureOpenAIClient(new Uri(openAiEndpoint), credential);
var chatClient = openAIClient.GetChatClient(deployment);
// Toolbox MCP client — discovers tools via tools/list, calls them via tools/call
var toolboxClient = new ToolboxMcpClient(toolboxEndpoint, credential);
ResponsesServer.Run<ToolboxHandler>(configure: builder =>
{
builder.Services.AddSingleton(new AgentConfig(chatClient, toolboxClient));
});
ToolboxMcpClient 封装对 MCP 终结点的直接 JSON-RPC 调用。
ToolboxHandler 使用标准工具调用循环将 LLM 工具调用连接回 MCP 客户端。 有关这两个类的完整实现,请参阅 完整示例。
注意
此步骤的集成示例仅适用于Python和.NET。
注意
此步骤的集成示例仅适用于Python和.NET。
使用 Microsoft Foundry Toolkit for Visual Studio Code 扩展,搭建一个已与你的工具箱完成连接的托管代理示例项目。
- 在活动栏中选择 Foundry Toolkit 。
- 在 “我的资源”下,展开 项目名称>“工具”。
- 在 “工具箱 ”选项卡上,找到要使用的工具箱,然后选择 基架代码模板。
- 在命令面板中,出现提示时选择项目文件夹。
- 打开生成的
README.md并按照基架的设置、本地运行和部署步骤进行操作。
生成的项目包括托管智能体入口点、部署文件,以及包含确切设置、运行和部署步骤的 README.md。
如果要将工具箱集成到现有的托管代理项目中,而不是生成新示例,请在本节中将步骤 2 中复制的终结点与 Python 或 .NET 模式配合使用。
将工具箱终结点传递给代理
在 步骤 1 中创建工具箱后,检索其 MCP 终结点 azd ai toolbox show ,并将该终结点作为环境变量传递给代理代码。 代理在启动时读取变量,并使用它连接到工具箱。
获取工具箱端点:
azd ai toolbox show <toolbox-name> --output json响应中的
mcp_endpoint字段是使用者终结点,始终解析为工具箱的default_version。将终结点设置为代理在启动时读取的环境变量:
# .env (or however your runtime loads environment variables) TOOLBOX_ENDPOINT=https://<account>.services.ai.azure.com/api/projects/<project>/toolboxes/<toolbox-name>/mcp?api-version=v1在代理代码中,使用 MCP 客户端读取
TOOLBOX_ENDPOINT并连接到它。 请参考本节前文中的 Python 或 .NET 集成模式来进行客户端设置,以及设置 Entra 令牌(https://ai.azure.com/.default范围)。
处理工具审批要求
工具包会为每个由 _meta.tool_configuration 返回的工具条目返回一个 tools/list 对象。 如果工具 require_approval 已设置为 "always",代理运行时必须将挂起的操作呈现给用户,并在调用该工具之前等待确认。 MCP 终端 不会 阻止 tools/call — 强制执行完全是“代理运行时环境”的责任。
从require_approval中读取tools/list
tools/list 响应中的每个工具条目都包含工具箱返回的 _meta 块:
{
"name": "myserver.my_tool",
"description": "...",
"inputSchema": { "type": "object" },
"_meta": {
"tool_configuration": {
"type": "mcp",
"server_label": "myserver",
"server_url": "https://your-mcp-server.example.com",
"require_approval": "always"
}
}
}
require_approval 值 |
行为 |
|---|---|
"always" |
代理必须在每次调用之前请求用户确认。 |
"never" |
代理可以自由调用该工具。 |
实施审批限制 (LangGraph)
在启动时查询 tools/list 以构建审批映射,然后将约束注入到需要审批的任何工具的系统提示中:
async def _fetch_require_approval_tools(
endpoint: str,
auth: httpx.Auth,
extra_headers: dict,
) -> dict[str, str]:
async with httpx.AsyncClient(auth=auth, headers=extra_headers, timeout=30.0) as hc:
payload = {"jsonrpc": "2.0", "id": 1, "method": "tools/list", "params": {}}
resp = await hc.post(endpoint, json=payload)
resp.raise_for_status()
return {
t["name"]: t["_meta"]["tool_configuration"]["require_approval"]
for t in resp.json().get("result", {}).get("tools", [])
if t.get("_meta", {}).get("tool_configuration", {}).get("require_approval")
}
从 MCP 客户端加载工具后,检测哪些工具需要批准并调整系统提示:
approval_map = await _fetch_require_approval_tools(
TOOLBOX_ENDPOINT, toolbox_auth, extra_headers
)
always_approval = [name for name, val in approval_map.items() if val == "always"]
注意
- 检测在启动时发生。 在代理初始化时,"审批检查" 会运行一次。 没有任何与每个调用相关的额外费用。
- 正常回退。 如果没有工具
require_approval: "always",则系统提示保持不变,代理的行为与以前一样。 -
require_approval是代理强制执行的。 不论设置如何,工具箱 MCP 代理都会执行tools/call。 智能体运行时负责控制调用。
在工具上配置 require_approval
创建工具箱版本时设置 require_approval 。
步骤 1 中的 MCP 工具示例显示了"always"和"never"两种值。 还可以通过 SDK 设置它:
from azure.ai.projects.models import MCPTool
# Set require_approval on an MCP tool
toolbox_version = project.toolboxes.create_toolbox_version(
name="my-toolbox",
tools=[
MCPTool(
server_label="myserver",
server_url="https://your-mcp-server.example.com",
require_approval="always", # "always" | "never"
project_connection_id="my-connection",
)
],
)
{
"tools": [
{
"type": "mcp",
"server_label": "myserver",
"server_url": "https://your-mcp-server.example.com",
"require_approval": "always",
"project_connection_id": "my-connection"
}
]
}
ProjectsAgentTool mcpTool = ProjectsAgentTool.AsProjectTool(ResponseTool.CreateMcpTool(
serverLabel: "myserver",
serverUri: new Uri("https://your-mcp-server.example.com"),
toolCallApprovalPolicy: new McpToolCallApprovalPolicy(
GlobalMcpToolCallApprovalPolicy.AlwaysRequireApproval
)
));
const tools = [
{
type: "mcp",
server_label: "myserver",
server_url: "https://your-mcp-server.example.com",
require_approval: "always",
project_connection_id: "my-connection",
},
];
使用Python、.NET、JavaScript、REST API 或 azd 选项卡在工具箱定义中配置 require_approval。 本文中用于Visual Studio Code扩展工作流的 Microsoft Foundry 工具包侧重于在 Visual Studio Code 中创建和使用工具箱。
resources:
- kind: toolbox
name: my-toolbox
tools:
- type: mcp
server_label: myserver
server_url: https://your-mcp-server.example.com
require_approval: always
project_connection_id: my-connection
步骤 5:管理工具箱版本
注意
只能通过 Python SDK、.NET SDK、JavaScript SDK 和 REST API 删除工具箱版本。 azd CLI 支持 list、get 和 publish(默认版本提升)操作。
工具箱版本是工具箱工具配置的不可变快照。 每次调用创建终结点都会生成一个新的 ToolboxVersionObject。 父级ToolboxObject有一个default_version字段,用于控制MCP端点所提供的版本。 创建新版本不会自动发布它 - 你决定何时更新 default_version。 此过程允许你准备更改,独立测试新版本,并按自己的计划将其提升到生产环境。
注意
对于 Azure Developer CLI,以当前默认版本(azd ai toolbox connection add/remove 和 azd ai toolbox skill add/remove)为目标的每个变更操作都会创建一个新的工具箱版本,该版本会沿用之前附加的所有连接和技能,并应用所请求的更改。 这些命令都不会自动更改 default_version;在准备好使新版本处于活动状态时运行 azd ai toolbox publish <toolbox-name> <version> 。 若要查看待定的(非默认)版本,请使用 azd ai toolbox show <name> --version <n>。
| 对象 | 关键字段 | 描述 |
|---|---|---|
ToolboxObject |
id、 name、、 default_version |
工具箱容器。
default_version 指向活动版本。 |
ToolboxVersionObject |
id、、nameversion、description、created_at、、 tools[]policies |
工具箱工具列表在某个时间点的不可变快照。
policies.rai_config.rai_policy_name 指定应用于此版本的可选护栏。 |
创建新版本
每次创建调用都会生成新版本。 如果工具箱尚不存在,则该过程会自动创建它。 创建新工具箱的第一个版本时,默认版本是v1手动更新到另一个版本之前。
# Create a new toolbox version
toolbox_version = project.toolboxes.create_toolbox_version(
name="my-toolbox",
description="Updated tools v2",
tools=[...],
)
print(f"Created version: {toolbox_version.version}")
ToolboxVersion toolboxVersion = await toolboxClient.CreateToolboxVersionAsync(
toolboxName: "<toolbox-name>",
tools: [tool],
description: "Updated tools v2"
);
Console.WriteLine($"Created version: {toolboxVersion.Version}");
POST {project_endpoint}/toolboxes/<toolbox-name>/versions?api-version=v1
Authorization: Bearer {token}
Content-Type: application/json
{
"description": "Updated tools v2",
"tools": [...]
}
const toolboxVersion = await project.toolboxes.createVersion(
"<toolbox-name>",
[/* tools array */],
{ description: "Updated tools v2" },
);
console.log(`Created version: ${toolboxVersion.version}`);
使用Python、.NET、JavaScript 或 REST API 选项卡创建新的工具箱版本。 本文中的 Microsoft Foundry Toolkit for Visual Studio Code 扩展专注于创建工具箱,并搭建一个使用该工具箱的托管代理。
Azure开发人员 CLI 不支持此操作。 若要创建工具箱版本,请使用 Python、.NET、REST API 或 JavaScript 选项卡。
响应是一个包含新 ToolboxVersionObject 标识符的 version。
列出版本
# List all toolbox versions
versions = list(project.toolboxes.list_toolbox_versions(name="<toolbox-name>"))
for v in versions:
print(f"{v.version} — created {v.created_at}")
List<ToolboxVersion> versions = await toolboxClient
.GetToolboxVersionsAsync("<toolbox-name>")
.ToListAsync();
Console.WriteLine($"Found {versions.Count} toolbox version(s).");
foreach (ToolboxVersion v in versions)
{
Console.WriteLine($" - {v.Name} ({v.Version})");
}
GET {project_endpoint}/toolboxes/<toolbox-name>/versions?api-version=v1
Authorization: Bearer {token}
const versions = project.toolboxes.listVersions("<toolbox-name");
for await (const v of versions) {
console.log(`${v.version} — created ${v.created_at}`);
}
使用Python、.NET、JavaScript 或 REST API 选项卡列出工具箱版本。
# The current default version is marked with *
azd ai toolbox version list <toolbox-name>
获取特定版本
# Get a specific toolbox version
version_obj = project.toolboxes.get_toolbox_version(
toolbox_name="<toolbox-name>",
version="<version_id>",
)
ToolboxVersion versionObj = await toolboxClient.GetToolboxVersionAsync(
"<toolbox-name>",
"<version_id>"
);
Console.WriteLine($"Retrieved toolbox: {versionObj.Name} ({versionObj.Id})");
GET {project_endpoint}/toolboxes/<toolbox-name>/versions/{version}?api-version=v1
Authorization: Bearer {token}
const versionObj = await project.toolboxes.getVersion(
"<toolbox-name>",
"<version_id>",
);
console.log(`Retrieved version: ${versionObj.version}`);
使用Python、.NET、JavaScript 或 REST API 选项卡获取特定的工具箱版本。
azd ai toolbox version get <toolbox-name> <version_id>
将版本提升为默认值
MCP 终结点始终提供 default_version。 若要切换处于活动状态的版本,请更新工具箱:
# Promote a version to default
toolbox = project.toolboxes.update(
toolbox_name="<toolbox-name>",
default_version="<version_id>",
)
print(f"Active version: {toolbox.default_version}")
ToolboxRecord record = await toolboxClient.UpdateToolboxAsync(
"<toolbox-name>",
"<version_id>"
);
Console.WriteLine($"Active version: {record.DefaultVersion}");
PATCH {project_endpoint}/toolboxes/<toolbox-name>?api-version=v1
Authorization: Bearer {token}
Content-Type: application/json
{
"default_version": "<version_id>"
}
default_version 不能为空。 将其替换为新版本。
const toolbox = await project.toolboxes.update(
"<toolbox-name>",
"<version_id>",
);
console.log(`Active version: ${toolbox.default_version}`);
使用Python、.NET、JavaScript 或 REST API 选项卡将工具箱版本提升为默认值。
工具箱版本是不可变的。 用于 publish 使任何现有版本成为新的默认值:
# Roll back or forward to a specific version
azd ai toolbox publish <toolbox-name> <version_id> --no-prompt
publish 是通过 CLI 更改 default_version 的唯一途径;变更动词(connection add/remove、skill add/remove)始终创建新版本,但不会提升该版本。
删除版本
# Delete a toolbox version
project.toolboxes.delete_toolbox_version(
toolbox_name="<toolbox-name>",
version="<version_id>",
)
await toolboxClient.DeleteToolboxVersionAsync(
"<toolbox-name>",
"<version_id>"
);
DELETE {project_endpoint}/toolboxes/<toolbox-name>/versions/{version}?api-version=v1
Authorization: Bearer {token}
await project.toolboxes.deleteVersion(
"<toolbox-name>",
"<version_id>",
);
使用Python、.NET、JavaScript 或 REST API 选项卡删除工具箱版本。
Azure开发人员 CLI 不支持此操作。 若要删除工具箱版本,请使用 Python、.NET、REST API 或 JavaScript 选项卡。
配置工具
选择与方案匹配的工具类型和身份验证模式。 选择首选 SDK 或部署方法的选项卡。
下面的每个工具的 azd 选项卡都显示声明性工具箱 YAML。 若要在没有代理项目的情况下创建工具箱,请使用 通用的四步 azd ai toolbox create --from-file 工作流 并应用以下部分中所示的每工具数据。 若要使用托管代理部署工具箱,请在 azure.ai.toolbox 中将其建模为 azure.yaml 服务,并使用 uses: 或 toolboxes: 将代理连接到该服务。
多种工具类型
单个工具箱可以捆绑不同的工具类型。 以下示例将 Web 搜索、Azure AI 搜索和 MCP 服务器合并到一个工具箱中:
{
"description": "Web search, knowledge base search, and custom MCP server",
"tools": [
{
"type": "web_search",
"description": "Search the web for current information"
},
{
"type": "azure_ai_search",
"name": "my_aisearch",
"description": "Search internal product documentation",
"azure_ai_search": {
"indexes": [
{
"index_name": "<INDEX_NAME>",
"project_connection_id": "<CONNECTION_NAME>"
}
]
}
},
{
"type": "mcp",
"server_label": "myserver",
"server_url": "https://your-mcp-server.example.com",
"require_approval": "never",
"project_connection_id": "my-key-auth-connection"
}
]
}
注意
每个工具类型(web_search、、azure_ai_searchcode_interpreter、file_search)最多可以一次显示,而无需字段name。 要包含同一类型的多个实例,请在每个实例上设置一个唯一 name - 请参阅下一个示例。
多工具限制
最多可以包含每个内置工具类型的一个实例,而无需 name 工具箱中的字段。 如果包含两个不带 a name的相同类型的实例,API 将返回:
400 invalid_payload: Multiple tools without identifiers found...
同一工具类型的两个实例
使用 name 字段在一个工具箱中包含同一工具类型的多个实例。 每个命名实例都被视为单独的工具,并且必须具有唯一的名称。
{
"description": "Two Azure AI Search indexes in a single toolbox",
"tools": [
{
"type": "azure_ai_search",
"name": "product-search",
"description": "Search product catalog and specifications",
"azure_ai_search": {
"indexes": [
{
"index_name": "<PRODUCT_INDEX_NAME>",
"project_connection_id": "<PRODUCT_CONNECTION_NAME>"
}
]
}
},
{
"type": "azure_ai_search",
"name": "support-search",
"description": "Search support tickets and troubleshooting guides",
"azure_ai_search": {
"indexes": [
{
"index_name": "<SUPPORT_INDEX_NAME>",
"project_connection_id": "<SUPPORT_CONNECTION_NAME>"
}
]
}
}
]
}
以下部分详细介绍了每种工具类型的配置。
模型上下文协议 (MCP)
基于密钥的身份验证:
{
"description": "my-mcp-toolbox",
"tools": [
{
"type": "mcp",
"server_label": "myserver",
"server_url": "https://your-mcp-server.example.com",
"project_connection_id": "my-mcp-connection"
}
]
}
无身份验证(公共 MCP 服务器):
{
"description": "Public MCP server",
"tools": [
{
"type": "mcp",
"server_label": "myserver",
"server_url": "https://your-mcp-server.example.com"
}
]
}
OAuth 或基于身份的身份验证:
对于 OAuth(托管连接器、自定义应用注册)、代理身份或用户 Entra 令牌验证,请先在 Foundry 项目中创建合适的连接,然后使用 project_connection_id:
{
"description": "MCP server with OAuth/identity auth",
"tools": [
{
"type": "mcp",
"server_label": "myserver",
"server_url": "https://your-mcp-server.example.com",
"project_connection_id": "<OAUTH_OR_IDENTITY_CONNECTION_NAME>"
}
]
}
连接的 authType 确定身份验证流。 MCP 支持的连接身份验证类型包括 CustomKeys、OAuth2(托管或自定义)、AgenticIdentityToken 以及 UserEntraToken。 有关每个身份验证类型的连接配置示例,请参阅 azd 选项卡 。
from azure.ai.projects.models import MCPTool
tools = [
MCPTool(
server_label="myserver",
server_url="https://your-mcp-server.example.com",
project_connection_id="my-mcp-connection",
)
]
ProjectsAgentTool tool = ProjectsAgentTool.AsProjectTool(ResponseTool.CreateMcpTool(
serverLabel: "myserver",
serverUri: new Uri("https://your-mcp-server.example.com")
));
ToolboxVersion toolboxVersion = await toolboxClient.CreateToolboxVersionAsync(
toolboxName: "my-toolbox",
tools: [tool],
description: "my-mcp-toolbox"
);
const tools = [
{
type: "mcp",
server_label: "myserver",
server_url: "https://your-mcp-server.example.com",
project_connection_id: "my-mcp-connection",
},
];
使用与方案匹配的身份验证类型为 MCP 服务器创建项目连接,然后从最小工具箱 YAML 中引用它。
步骤 1。 创建连接
注意
导出项目端点,并将其设置为 azd ai 命令的活动项目:
PROJECT_ENDPOINT="https://<account>.services.ai.azure.com/api/projects/<project>"
azd ai project set $PROJECT_ENDPOINT
选择所需的身份验证变体:
# No auth — public MCP server
azd ai connection create my-mcp-conn \
--kind remote-tool \
--target https://learn.microsoft.com/api/mcp \
--auth-type none
# Custom-keys header (for example, GitHub PAT)
azd ai connection create my-mcp-conn \
--kind remote-tool \
--target https://api.githubcopilot.com/mcp/ \
--auth-type custom-keys \
--custom-key "Authorization=Bearer $GITHUB_PAT"
# OAuth — bring your own app registration
azd ai connection create my-mcp-conn \
--kind remote-tool \
--target https://your-mcp-server.example.com \
--auth-type oauth2 \
--authorization-url https://auth.example.com/authorize \
--token-url https://auth.example.com/token \
--client-id <oauth-client-id> \
--client-secret <oauth-client-secret> \
--scopes "<scope1> <scope2>"
# User Entra token (managed user identity passthrough; for example, Microsoft Fabric)
azd ai connection create my-mcp-conn \
--kind remote-tool \
--target https://api.fabric.microsoft.com/v1/mcp/fabricaihub/integrations/m365 \
--auth-type user-entra-token \
--audience https://analysis.windows.net/powerbi/api
# Project managed identity — the project's system-assigned MI
azd ai connection create my-mcp-conn \
--kind remote-tool \
--target https://<resource>.cognitiveservices.azure.com/language/mcp \
--auth-type project-managed-identity \
--audience https://cognitiveservices.azure.com
# Agentic identity — the agent's per-project identity
azd ai connection create my-mcp-conn \
--kind remote-tool \
--target https://<resource>.cognitiveservices.azure.com/language/mcp \
--auth-type agentic-identity \
--audience https://cognitiveservices.azure.com
--auth-type |
其他标志 |
|---|---|
none |
— |
custom-keys |
--custom-key "Header=Value" (可重复) |
oauth2 |
--authorization-url、--token-url、--client-id、--client-secret、--scopes |
user-entra-token |
--audience <entra-audience> |
project-managed-identity |
--audience <entra-audience>(可选) |
agentic-identity |
--audience <entra-audience> |
对于基于标识的身份验证(user-entra-token、project-managed-identity、agentic-identity),请先在目标资源上为相应主体分配所需的 RBAC 角色,然后再调用工具箱。
步骤 2。 定义工具箱
# my-toolbox.yaml
description: MCP server tools
connections:
- name: my-mcp-conn
步骤 3。 创建工具箱
azd ai toolbox create my-toolbox --from-file my-toolbox.yaml
重要
用户第一次在项目中调用具有基于 OAuth 的 MCP 的工具箱时,MCP 终结点会返回一个 CONSENT_REQUIRED 带有同意 URL 的错误(代码 -32006):
{
"error": {
"code": -32006,
"message": "User consent is required. Please visit: https://..."
}
}
此错误应为预期。 在浏览器中打开许可 URL,完成 OAuth 授权流,然后重试代理调用。 后续调用成功,无需重新提示。
Web 搜索
重要
- Web 搜索使用 Grounding with Bing Search 和 Grounding with Bing Custom Search,这些是受 Grounding with Bing 使用条款和 Microsoft 隐私声明约束的第一方消费服务。
- Microsoft 数据保护附录不适用于发送到 Grounding with Bing Search 和 Grounding with Bing Custom Search。 使用 Grounding with Bing Search 和 Grounding with Bing Custom Search 时,数据将传输至合规和地理边界外部。
- 使用 Grounding with Bing Search 和 Grounding with Bing Custom Search 会产生费用。 有关详细信息,请参阅 定价 。
- 请参阅 management 部分,了解有关Azure管理员如何管理 Web 搜索使用访问权限的信息。
使用此模式添加 Web 搜索。 使用 "Grounding with Bing" 进行 Web 搜索时不需要项目连接。 要使用 Grounding with Bing Custom Search 实例,请添加指向你的 Grounding with Bing Custom Search 连接的 web_search.custom_search_configuration 对象。
{
"description": "Built-in web search",
"tools": [
{
"type": "web_search",
"name": "<OPTIONAL_TOOL_NAME>",
"description": "<Optional description for the model>"
}
]
}
使用 Grounding with Bing Custom Search 连接:
{
"description": "Custom Bing Search instance",
"tools": [
{
"type": "web_search",
"name": "<OPTIONAL_TOOL_NAME>",
"description": "<Optional description for the model>",
"web_search": {
"custom_search_configuration": {
"project_connection_id": "<BING_CONNECTION_NAME>",
"instance_name": "<BING_INSTANCE_NAME>"
}
}
}
]
}
from azure.ai.projects.models import WebSearchTool
tools = [
WebSearchTool()
]
ProjectsAgentTool tool = ProjectsAgentTool.AsProjectTool(
ResponseTool.CreateWebSearchTool()
);
ToolboxVersion toolboxVersion = await toolboxClient.CreateToolboxVersionAsync(
toolboxName: "my-toolbox",
tools: [tool],
description: "Built-in web search"
);
const tools = [
{
type: "web_search",
name: "<OPTIONAL_TOOL_NAME>",
description: "<Optional description for the model>",
},
];
默认(使用必应搜索进行基础设置,无需连接):
# my-toolbox.yaml
description: Web search toolbox
tools:
- type: web_search
azd ai toolbox create my-toolbox --from-file my-toolbox.yaml
使用必应自定义搜索进行基础设置:
# Step 1. Create the Bing Custom Search connection
azd ai connection create my-bing-custom \
--kind GroundingWithCustomSearch \
--target https://api.bing.microsoft.com/ \
--auth-type api-key \
--key "<bing-custom-search-key>"
--kind GroundingWithCustomSearch 必须严格使用 PascalCase。
# Step 2. Define the toolbox (my-toolbox.yaml)
description: Bing Custom Search toolbox
connections:
- name: my-bing-custom
instance_name: your-bing-custom-instance
# Step 3. Create the toolbox
azd ai toolbox create my-toolbox --from-file my-toolbox.yaml
注意
当 Web 搜索通过 MCP 返回结果时,响应是包含 resource 内联 Markdown 源链接的合成答案的内容项。 URL 引用在 content[].resource._meta.annotations[] 中。 例如:
{
"jsonrpc": "2.0",
"id": "ws-call-1",
"result": {
"_meta": {
"tool_configuration": {
"type": "web_search",
"name": "web-search-default"
}
},
"content": [
{
"type": "resource",
"resource": {
"uri": "about:web-search-answer",
"mimeType": "text/plain",
"text": "Here are the latest updates on Azure OpenAI Service...\n\n- **GPT-image-1 Release (January 7, 2026)** Microsoft introduced GPT-image-1 ([serverless-solutions.com](https://...)).\n\n..."
},
"annotations": {
"audience": ["assistant"]
},
"_meta": {
"annotations": [
{
"type": "url_citation",
"url": "https://www.serverless-solutions.com/blog/...",
"title": "Microsoft Expands Azure AI Foundry with Powerful New OpenAI Models",
"start_index": 741,
"end_index": 879
}
],
"action": {
"type": "search",
"query": "Azure OpenAI service updates 2026",
"queries": ["Azure OpenAI service updates 2026"]
},
"response_id": "resp_001fcebcc300..."
}
}
],
"isError": false
}
}
Azure AI 搜索
{
"description": "Azure AI Search over my data",
"tools": [
{
"type": "azure_ai_search",
"name": "<OPTIONAL_TOOL_NAME>",
"description": "<Optional description for the model>",
"azure_ai_search": {
"indexes": [
{
"index_name": "<INDEX_NAME>",
"project_connection_id": "<CONNECTION_NAME>"
}
]
}
}
]
}
from azure.ai.projects.models import AzureAISearchTool
tools = [
AzureAISearchTool(
index_name="<INDEX_NAME>",
project_connection_id="<CONNECTION_NAME>",
)
]
ProjectsAgentTool tool = new AzureAISearchTool(
new AzureAISearchToolOptions(
indexes: [
new AzureAISearchIndexResource(
indexName: "<INDEX_NAME>",
projectConnectionId: "<CONNECTION_NAME>"
)
]
)
);
ToolboxVersion toolboxVersion = await toolboxClient.CreateToolboxVersionAsync(
toolboxName: "my-toolbox",
tools: [tool],
description: "Azure AI Search over my data"
);
const tools = [
{
type: "azure_ai_search",
name: "<OPTIONAL_TOOL_NAME>",
description: "<Optional description for the model>",
azure_ai_search: {
indexes: [
{
index_name: "<INDEX_NAME>",
project_connection_id: "<CONNECTION_NAME>",
},
],
},
},
];
# Step 1. Create the Azure AI Search connection
azd ai connection create my-search \
--kind cognitive-search \
--target "https://<your-search>.search.windows.net/" \
--auth-type api-key \
--key "<aisearch-admin-key>"
cognitive-search 连接也接受 --auth-type project-managed-identity (无密钥)。 使用项目托管标识时,请在搜索服务上为项目的系统分配的托管标识授予搜索索引数据读者角色。
# Step 2. Define the toolbox (my-toolbox.yaml)
description: Azure AI Search toolbox
connections:
- name: my-search
index: your-index-name
# Step 3. Create the toolbox
azd ai toolbox create my-toolbox --from-file my-toolbox.yaml
配置工具参数
| Azure AI 搜索工具参数 | 必填 | 笔记 |
|---|---|---|
project_connection_id |
是的 | 与 Azure AI 搜索 项目连接相关的资源 ID。 |
index_name |
是的 | Azure AI 搜索资源中的索引的名称。 |
top_k |
不 | 默认值为 5。 |
query_type |
不 | 默认值为 vector_semantic_hybrid. 支持的值:simple、、vectorsemantic、vector_simple_hybrid、 。 vector_semantic_hybrid |
filter |
不 | 适用于代理对索引进行的所有查询。 |
搜索结果在result.structuredContent.documents[]中包括区块元数据。 每个文档都包含title、url、id和score字段,这些字段可用于在应用程序中生成引文详细信息。
代码解释器
使用此模式可让代理编写和执行Python代码。 该模式不需要项目连接或额外配置。
要通过工具箱上传供代码解释器使用的文件,请在资源级别文件终结点 (POST {account_endpoint}/openai/v1/files) 上使用 x-aml-project-id 标头上传文件。 与提示智能体流不同,通过项目范围的文件终结点 (/api/projects/{name}/openai/v1/files) 上传的文件会收到一个工具箱容器无法验证的 owner_id,因此 tools/call 会因所有权验证错误而失败。
从Azure 资源管理器获取项目 GUID。 使用
properties.amlWorkspace.internalId(虚线 UUID 格式), 而不是properties.internalId(没有短划线 — 工具箱容器拒绝它):ARM_TOKEN=$(az account get-access-token --query accessToken -o tsv) PROJECT_GUID=$(curl -s -H "Authorization: Bearer $ARM_TOKEN" \ "https://management.azure.com/subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.CognitiveServices/accounts/{account}/projects/{project}?api-version=2025-06-01" \ | jq -r '.properties.amlWorkspace.internalId')使用
x-aml-project-id标头在帐户(资源)级别上传文件:TOKEN=$(az account get-access-token --resource https://ai.azure.com/.default --query accessToken -o tsv) curl -X POST "https://{account}.services.ai.azure.com/openai/v1/files" \ -H "Authorization: Bearer $TOKEN" \ -H "x-aml-project-id: $PROJECT_GUID" \ -F "purpose=assistants" \ -F "file=@your-file.csv"
返回的文件 id 就是你在工具配置中为 <FILE_ID> 提供的值。 文件挂载在沙盒中的 /mnt/data/{file-id}-{original-filename}。 有关其他上传示例和特定于语言的示例,请参阅 代码解释器 。
重要
当代码解释器通过托管代理中的工具箱使用时, 不支持用户隔离。 同一项目中的所有用户共享相同的容器上下文。
{
"description": "Code interpreter for data analysis",
"tools": [
{
"type": "code_interpreter",
"name": "<OPTIONAL_TOOL_NAME>",
"description": "<Optional description for the model>",
"container": {
"type": "auto",
"file_ids": ["<FILE_ID>"]
}
}
]
}
from azure.ai.projects.models import CodeInterpreterTool
tools = [
CodeInterpreterTool()
]
ProjectsAgentTool tool = ProjectsAgentTool.AsProjectTool(
ResponseTool.CreateCodeInterpreterTool(
new CodeInterpreterToolContainer()
)
);
ToolboxVersion toolboxVersion = await toolboxClient.CreateToolboxVersionAsync(
toolboxName: "my-toolbox",
tools: [tool],
description: "Code interpreter for data analysis"
);
const tools = [
{
type: "code_interpreter",
name: "<OPTIONAL_TOOL_NAME>",
description: "<Optional description for the model>",
container: {
type: "auto",
file_ids: ["<FILE_ID>"],
},
},
];
代码解释器是无连接的。 直接在 tools: 下声明它。
# my-toolbox.yaml
description: Code interpreter toolbox
tools:
- type: code_interpreter
container: { type: auto }
azd ai toolbox create my-toolbox --from-file my-toolbox.yaml
从代码解释器下载输出文件
当代码解释器生成输出文件(例如生成的 CSV 或图表)时,请使用以下步骤列出和下载它们。
步骤 1:使用容器 API 列出文件
从 container_id响应的 content[]._meta.container_id 中提取 tools/call,然后调用容器文件 API 列出容器中的所有文件:
GET {project_endpoint}/containers/{container_id}/files?api-version=v1
Authorization: Bearer {token}
响应返回具有其名称和 ID 的文件列表。
步骤 2:使用文件 API 下载文件
使用从步骤 1 获取的文件名通过 文件 API 下载接口来下载文件。
文件搜索
使用此模式可以让代理搜索存储在向量存储中的上传文件。 请提供已在 Foundry 项目中创建的引用矢量存储的 vector_store_ids。
若要创建供工具箱使用的文件和向量存储,请在 标头下将文件上传到 x-aml-project-id Files 端点(要求与 Code Interpreter 相同——有关如何从 properties.amlWorkspace.internalId 获取项目 GUID,请参阅上一节):
- 上传你的文件:使用
POST {account_endpoint}/openai/v1/files和标头purpose=assistants的x-aml-project-id: {project-guid}。 - 创建矢量存储:
POST {account_endpoint}/openai/v1/vector_stores使用返回的文件 ID 和相同的x-aml-project-id标头。
生成的向量存储 ID 是你提供的值 <VECTOR_STORE_ID>。 请参阅 文件搜索 ,了解每种语言的完整示例。
重要
当通过托管代理中的工具箱使用文件搜索时, 不支持用户隔离。 同一项目中的所有用户共享对同一向量存储的访问权限。
{
"description": "Search over uploaded documents",
"tools": [
{
"type": "file_search",
"name": "<OPTIONAL_TOOL_NAME>",
"description": "<Optional description for the model>",
"file_search": {
"vector_store_ids": ["<VECTOR_STORE_ID>"]
}
}
]
}
from azure.ai.projects.models import FileSearchTool
tools = [
FileSearchTool(
vector_store_ids=["<VECTOR_STORE_ID>"]
)
]
ProjectsAgentTool tool = ProjectsAgentTool.AsProjectTool(
ResponseTool.CreateFileSearchTool(
vectorStoreIds: ["<VECTOR_STORE_ID>"]
)
);
ToolboxVersion toolboxVersion = await toolboxClient.CreateToolboxVersionAsync(
toolboxName: "my-toolbox",
tools: [tool],
description: "Search over uploaded documents"
);
const tools = [
{
type: "file_search",
name: "<OPTIONAL_TOOL_NAME>",
description: "<Optional description for the model>",
file_search: {
vector_store_ids: ["<VECTOR_STORE_ID>"],
},
},
];
文件搜索是无连接的,但需要现有的矢量存储 ID。 直接在 tools: 下声明它。
# my-toolbox.yaml
description: File search toolbox
tools:
- type: file_search
vector_store_ids:
- vs_xxxxxxxxxxxx
azd ai toolbox create my-toolbox --from-file my-toolbox.yaml
注意
当文件搜索通过 MCP 返回结果时,区块元数据将嵌入工具响应内容中作为 【index†filename†file_id【 标记。 例如:
{
"jsonrpc": "2.0",
"id": "fs-call-1",
"result": {
"content": [
{
"type": "resource",
"resource": {
"uri": "file://assistant-tvfqncbtruyffxkfewenyy/",
"_meta": {
"title": "mcp-test-file.txt",
"file_id": "assistant-TVfQnCBtRuyfFxkfeweNYY",
"document_chunk_id": "f7327b7f-5ed0-43c6-9bee-e8e9552afcb5",
"score": 0.03333333507180214
},
"text": "# 【0†mcp-test-file.txt†assistant-TVfQnCBtRuyfFxkfeweNYY【\nContent Snippet:\nAzure OpenAI Service is a cloud service..."
}
}
]
}
}
每个资源项内的 _meta 块包含匹配块的 title、file_id、document_chunk_id 和相关性 score。 在应用程序中使用这些元数据字段生成引文详细信息或指向源文件的深层链接。
OpenAPI
使用此模式公开 OpenAPI 规范描述的任何 REST API。选择与 API 的安全模型匹配的 auth.type。
重要
使用托管标识身份验证时,必须为目标服务上的 Foundry 项目的托管标识分配适当的 RBAC 角色。 例如,在目标 Azure 资源上分配“读取者”或更高权限。 如果没有此分配,代理在调用 API 时会收到 401 Unauthorized 响应。 有关完整设置步骤,请参阅 使用托管标识进行身份验证。
匿名身份验证:
{
"description": "REST API via OpenAPI spec",
"tools": [
{
"type": "openapi",
"openapi": {
"name": "my-api",
"spec": { "<paste OpenAPI spec object here>" },
"auth": {
"type": "anonymous"
}
}
}
]
}
项目连接认证:
当 API 需要存储在 Foundry 项目连接中的密钥或令牌时,请使用此模式。
{
"description": "REST API with connection-based auth",
"tools": [
{
"type": "openapi",
"openapi": {
"name": "my-api",
"spec": { "<paste OpenAPI spec object here>" },
"auth": {
"type": "connection",
"security_scheme": {
"project_connection_id": "<CONNECTION_NAME>"
}
}
}
}
]
}
托管标识身份验证:
当目标 API 通过Microsoft Entra ID进行身份验证时,请使用此模式。 Foundry 项目的托管标识代表智能体调用 API。 使用此模式之前,请确保托管标识在目标服务上具有所需的 RBAC 角色权限。
{
"description": "REST API with managed identity auth",
"tools": [
{
"type": "openapi",
"openapi": {
"name": "my-api",
"spec": { "<paste OpenAPI spec object here>" },
"auth": {
"type": "managed_identity",
"security_scheme": {
"audience": "<TARGET_SERVICE_AUDIENCE>"
}
}
}
}
]
}
from azure.ai.projects.models import OpenAPITool
tools = [
OpenAPITool(
name="my-api",
spec={"<paste OpenAPI spec object here>"},
auth={"type": "anonymous"},
)
]
BinaryData specBytes = BinaryData.FromString("<OpenAPI spec JSON>");
ProjectsAgentTool tool = new OpenAPITool(
new OpenApiFunctionDefinition(
name: "my-api",
spec: specBytes,
openApiAuthentication: new OpenApiAnonymousAuthDetails()
)
);
ToolboxVersion toolboxVersion = await toolboxClient.CreateToolboxVersionAsync(
toolboxName: "my-toolbox",
tools: [tool],
description: "REST API via OpenAPI spec"
);
const tools = [
{
type: "openapi",
openapi: {
name: "my-api",
spec: { /* paste OpenAPI spec object here */ },
auth: {
type: "anonymous",
},
},
},
];
OpenAPI 工具将规范直接嵌入到 tools: 下。 基于连接的身份验证 (connection_auth) 引用项目连接;匿名 OpenAPI 工具无需连接。
步骤 1。 (可选)创建身份验证连接
跳过匿名 OpenAPI 工具的此步骤。
# API-key auth (passed by the platform on every call)
azd ai connection create my-api-conn \
--kind remote-tool \
--target https://api.example.com \
--auth-type custom-keys \
--custom-key "Authorization=Bearer <token>"
OpenAPI 工具还接受 --auth-type oauth2 连接。 有关 azd ai connection create 标志的完整列表,请参阅上文的 MCP 部分。
步骤 2。 定义工具箱
OpenAPI 规范直接写在 tools[].openapi.spec 下方。
# my-toolbox.yaml
description: OpenAPI toolbox
tools:
- type: openapi
name: my-api
openapi:
name: my-api
spec:
openapi: "3.0.1"
info:
title: "My API"
version: "1.0"
servers:
- url: https://api.example.com/v1
paths:
/search:
get:
operationId: search
parameters:
- name: query
in: query
required: true
schema:
type: string
responses:
"200":
description: OK
auth:
type: connection_auth
connection_id: my-api-conn
对于匿名 API,请将 auth: 块替换为:
auth:
type: anonymous
security_scheme:
type: anonymous
步骤 3。 创建工具箱
azd ai toolbox create my-toolbox --from-file my-toolbox.yaml
代理到代理 (A2A)
使用此模式调用另一个代理作为工具。 提供远程代理的基本 URL,如果需要身份验证,则提供项目连接。
{
"description": "Delegate tasks to a specialist agent",
"tools": [
{
"type": "a2a_preview",
"name": "<AGENT_NAME>",
"description": "<What this agent does>",
"base_url": "<AGENT_BASE_URL>",
"project_connection_id": "<CONNECTION_NAME>"
}
]
}
from azure.ai.projects.models import A2APreviewTool
tools = [
A2APreviewTool(
name="<AGENT_NAME>",
description="<What this agent does>",
base_url="<AGENT_BASE_URL>",
project_connection_id="<CONNECTION_NAME>",
)
]
ProjectsAgentTool tool = new A2APreviewTool()
{
ProjectConnectionId = "<CONNECTION_NAME>",
};
ToolboxVersion toolboxVersion = await toolboxClient.CreateToolboxVersionAsync(
toolboxName: "my-toolbox",
tools: [tool],
description: "Delegate tasks to a specialist agent"
);
const tools = [
{
type: "a2a_preview",
name: "<AGENT_NAME>",
description: "<What this agent does>",
base_url: "<AGENT_BASE_URL>",
project_connection_id: "<CONNECTION_NAME>",
},
];
为远程代理创建一个 remote-a2a 连接,然后在一个最简工具箱 YAML 中引用该连接。
步骤 1。 创建连接
选择所需的身份验证变体:
# No auth
azd ai connection create my-a2a-conn \
--kind remote-a2a \
--target https://your-remote-agent.azurecontainerapps.io \
--auth-type none
# Custom-keys header
azd ai connection create my-a2a-conn \
--kind remote-a2a \
--target https://your-remote-agent.azurecontainerapps.io \
--auth-type custom-keys \
--custom-key "Authorization=Bearer <token>"
# OAuth — bring your own app registration
azd ai connection create my-a2a-conn \
--kind remote-a2a \
--target https://your-remote-agent.azurecontainerapps.io \
--auth-type oauth2 \
--authorization-url https://auth.example.com/authorize \
--token-url https://auth.example.com/token \
--client-id <oauth-client-id> \
--client-secret <oauth-client-secret> \
--scopes "<scope1> <scope2>"
# User Entra token (managed user identity passthrough)
azd ai connection create my-a2a-conn \
--kind remote-a2a \
--target https://your-remote-agent.azurecontainerapps.io \
--auth-type user-entra-token \
--audience "<entra-audience>"
# Project managed identity
azd ai connection create my-a2a-conn \
--kind remote-a2a \
--target https://your-remote-agent.azurecontainerapps.io \
--auth-type project-managed-identity \
--audience "<entra-audience>"
# Agentic identity
azd ai connection create my-a2a-conn \
--kind remote-a2a \
--target https://your-remote-agent.azurecontainerapps.io \
--auth-type agentic-identity \
--audience "<entra-audience>"
--auth-type |
其他标志 |
|---|---|
none |
— |
custom-keys |
--custom-key "Header=Value" (可重复) |
oauth2 |
--authorization-url、--token-url、--client-id、--client-secret、--scopes |
user-entra-token |
--audience <entra-audience> |
project-managed-identity |
--audience <entra-audience>(可选) |
agentic-identity |
--audience <entra-audience> |
步骤 2。 定义工具箱
# my-toolbox.yaml
description: Agent-to-Agent toolbox
connections:
- name: my-a2a-conn
步骤 3。 创建工具箱
azd ai toolbox create my-toolbox --from-file my-toolbox.yaml
Fabric IQ
使用此模式,通过 Fabric IQ 使代理能够访问 Microsoft Fabric 数据资源,包括本体、数据代理和 Power BI 语义模型。 提供目标Fabric项的项目连接、MCP 服务器 URL 和服务器标签。
{
"description": "Fabric IQ for enterprise Fabric data access",
"tools": [
{
"type": "fabric_iq_preview",
"project_connection_id": "<CONNECTION_NAME>",
"server_label": "<SERVER_LABEL>",
"server_url": "<SERVER_URL>"
}
]
}
tools = [
{
"type": "fabric_iq_preview",
"project_connection_id": "<CONNECTION_NAME>",
"server_label": "<SERVER_LABEL>",
"server_url": "<SERVER_URL>",
}
]
Fabric IQ 充当 MCP 终结点。 使用 remote-tool 创建与 Fabric IQ 服务器的 user-entra-token 连接(推荐;调用方的标识被转发给 Fabric),然后从最小工具箱 YAML 中引用它。
# Step 1. Create the Fabric IQ connection
azd ai connection create my-fabric-conn \
--kind remote-tool \
--target https://api.fabric.microsoft.com/v1/mcp/fabricaihub/integrations/m365 \
--auth-type user-entra-token \
--audience https://analysis.windows.net/powerbi/api
remote-tool 连接也接受 --auth-type oauth2。 有关完整的标志集,请参阅上面的 MCP 部分。
# Step 2. Define the toolbox (my-toolbox.yaml)
description: Fabric IQ (semantic model)
tools:
- type: fabric_iq_preview
project_connection_id: my-fabric-conn
# Step 3. Create the toolbox
azd ai toolbox create my-toolbox --from-file my-toolbox.yaml
有关server_url按 Fabric 项类型划分的模式,请参阅查找 Fabric IQ 服务器详细信息。
批注块会在 result.structuredContent.documents[] 中返回。 每个文档都包含 title 和 url 字段,您可以在应用程序中使用这些字段生成引文详情。
工具搜索
使用此模式启用基于意向的工具路由。 工具箱中包括时 toolbox_search_preview ,平台会为每个请求选择最相关的工具,而不是一次性向模型公开所有工具。 这种方式无需任何其他配置。
{
"description": "Toolbox with intent-based tool routing",
"tools": [
{
"type": "toolbox_search_preview"
}
]
}
tools = [
{"type": "toolbox_search_preview"}
]
工具搜索是无连接的。 直接在 tools: 下声明它。
# my-toolbox.yaml
description: Toolbox with intent-based tool routing
tools:
- type: toolbox_search_preview
azd ai toolbox create my-toolbox --from-file my-toolbox.yaml
注意
toolbox_search_preview 是激活工具搜索的配置指令。 它不会出现在 tools/list 的响应中,也不计入“每种类型的未命名工具”的限制。
启用工具搜索后,Foundry 会将两个元工具与工具箱工具一起注入: tool_search 和 call_tool。
call_tool 元工具充当代理层,使代理框架能够通过单个已声明的入口点,按名称调用任何已发现的工具。 这可以避免在框架尝试调用初始 tools/list中不存在的工具时发生的架构验证错误。 如果框架支持没有架构预验证的直接工具调用,则还可以在找到已发现的工具后直接调用该工具 tool_search。
在 foundry Toolkit for Visual Studio Code 中,在创建或编辑工具箱时,在 Build a Custom Toolbox 选项卡上选择 Tool search。 有关详细信息,请参阅 工具箱中的“启用工具搜索”。
工作 IQ
使用此模式可以通过工作 IQ 向代理授予对用户Microsoft 365工作上下文(电子邮件、会议、文件和聊天)的访问权限。 为您的 Work IQ 终结点提供项目连接。
{
"description": "Work IQ for Microsoft 365 data access",
"tools": [
{
"type": "work_iq_preview",
"project_connection_id": "<CONNECTION_NAME>"
}
]
}
tools = [
{
"type": "work_iq_preview",
"project_connection_id": "<CONNECTION_NAME>",
}
]
Work IQ 作为 A2A 终结点提供。 使用 remote-a2a 创建与 Work IQ 服务器的 oauth2 连接,然后从最小工具箱 YAML 中引用它。
# Step 1. Create the Work IQ connection
azd ai connection create my-workiq-conn \
--kind remote-a2a \
--target https://agent365.svc.cloud.microsoft/agents/agents/workiq \
--auth-type oauth2 \
--authorization-url https://login.microsoftonline.com/common/oauth2/v2.0/authorize \
--token-url https://login.microsoftonline.com/common/oauth2/v2.0/token \
--client-id <oauth-client-id> \
--client-secret <oauth-client-secret> \
--scopes "<scope1> <scope2>"
# Step 2. Define the toolbox (my-toolbox.yaml)
description: Work IQ toolbox
tools:
- type: work_iq_preview
project_connection_id: my-workiq-conn
# Step 3. Create the toolbox
azd ai toolbox create my-toolbox --from-file my-toolbox.yaml
浏览器自动化
{
"description": "Perform actions using a real web browser",
"tools": [
{
"type": "browser_automation_preview",
"name": "<OPTIONAL_TOOL_NAME>",
"description": "<Optional description for the model>",
"browser_automation_preview": {
"connection": {
"project_connection_id": "<BROWSER_AUTOMATION_PROJECT_CONNECTION_ID>"
}
}
}
]
}
from azure.ai.projects.models import (
BrowserAutomationPreviewTool,
BrowserAutomationToolParameters,
BrowserAutomationToolConnectionParameters,
)
tools = [
BrowserAutomationPreviewTool(
browser_automation_preview=BrowserAutomationToolParameters(
connection=BrowserAutomationToolConnectionParameters(
project_connection_id="<BROWSER_AUTOMATION_PROJECT_CONNECTION_ID>",
)
)
)
]
ProjectsAgentTool tool = new BrowserAutomationPreviewTool(
new BrowserAutomationToolOptions(
new BrowserAutomationToolConnectionParameters("<BROWSER_AUTOMATION_PROJECT_CONNECTION_ID>")
)
);
const tools = [
{
type: "browser_automation_preview",
name: "<OPTIONAL_TOOL_NAME>",
description: "<Optional description for the model>",
browser_automation_preview: {
connection: {
project_connection_id: "<BROWSER_AUTOMATION_PROJECT_CONNECTION_ID>"
}
}
},
];
# Step 1. Create the Playwright Workspace connection
azd ai connection create my-browser-conn \
--kind PlaywrightWorkspace \
--target wss://your-browser-endpoint.api.playwright.microsoft.com/playwrightworkspaces/browsers \
--auth-type api-key \
--key "<playwright-workspaces-access-token>"
--kind PlaywrightWorkspace 必须严格使用 PascalCase。
# Step 2. Define the toolbox (my-toolbox.yaml)
description: Browser Automation toolbox
tools:
- type: browser_automation_preview
project_connection_id: my-browser-conn
# Step 3. Create the toolbox
azd ai toolbox create my-toolbox --from-file my-toolbox.yaml
疑难解答
| 症状 | 可能的原因 | 修复 |
|---|---|---|
tools/list 对于 MCP 或 A2A 工具返回零个工具。 |
远程 MCP 服务器或 A2A 代理的连接凭据无效或缺失。 工具箱无法在没有有效身份验证的情况下从远程终结点检索工具清单。 | 请验证 project_connection_id 是否存在于您的 Foundry 项目中,并确认凭据是否正确。 尝试直接连接到 MCP 服务器以测试身份验证设置。 如果使用托管标识(PMI、代理标识或 MI),请验证目标资源上调用方的正确 RBAC 角色分配。 |
tools/list 返回 OpenAPI 工具的零工具 |
OpenAPI 规范无效。工具箱从规范构造工具清单,如果规范格式不正确,该工具清单将失败。 | 验证 OpenAPI 规范内容。 检查它是否符合 OpenAPI 3.0 或 3.1,并包括有效 paths、 operationId 值和参数架构。 如果使用托管身份验证,请同时验证目标服务上的 RBAC 角色分配。 |
tools/list 返回的工具少于预期 |
筛选器 allowed_tools 包含错误或拼写错误的工具名称。 工具名称区分大小写,必须遵循 MCP 规范的工具名称 (无空格或特殊字符)。 |
暂时删除 allowed_tools 并调用 tools/list 以获取完整工具列表。 使用响应中的确切名称为 allowed_tools 设置值。 |
tools/list 返回零工具(其他工具类型) |
未完全预配的工具箱或区域中不支持的工具类型。 对于内置工具(Web 搜索、AI 搜索、代码解释器、文件搜索),工具清单是服务器端构造的,并且不需要身份验证 - 如果他们返回空,则工具箱版本可能尚未预配。 | 等待 10 秒,然后重试。 |
400 Multiple tools without identifiers |
一个工具箱中的两种未命名工具类型 | 最多保留一个未命名的类型;将 server_label 添加到所有 MCP 工具。 |
CONSENT_REQUIRED (代码 -32006) |
OAuth 连接需要用户同意 | 在浏览器中打开许可 URL 并完成 OAuth 流,然后重试。 |
401 在 MCP 呼叫中 |
令牌过期或作用域错误 | 使用作用域 https://ai.azure.com/.default 并刷新令牌。 |
| 工具名称不匹配 | MCP 工具名称的前缀为 server_label |
使用 {server_label}.{tool_name} 格式(例如, myserver.get_info)。 |
500 在 send_ping() 上 |
工具箱 MCP 服务器不实现 MCP ping 方法。 |
不要调用 send_ping()。 如果框架自动调用它(例如,Microsoft Agent Framework 的 MCPStreamableHTTPTool._ensure_connected()),请禁用 ping 检查或使用无操作替代该方法。 |
500 在 prompts/list 上 |
Foundry MCP 服务器未实现 prompts/list。 |
将 load_prompts=False(或其等效项)传递给 MCP 客户端构造函数。 |
500 使用非流式处理 tools/call |
工具包 MCP 终结点不支持非流式模式 (stream=False)。 |
始终在调用工具箱 MCP 工具时使用 stream=True 。 |
500 在 tools/list 上 |
暂时性服务器错误 | 几秒钟后重试。 |
| 在运行时覆盖的环境变量 | 平台会保留前缀 FOUNDRY_ 的所有环境变量,并且可能会以无提示方式覆盖用户定义的值。 |
重命名自定义环境变量以避免前缀 FOUNDRY_ (例如,使用 TOOLBOX_MCP_ENDPOINT 而不是 FOUNDRY_TOOLBOX_ENDPOINT)。 |
配置护栏
将命名 防护策略 应用于工具箱版本,以对工具输入和输出强制实施负责任的 AI 内容筛选。 护栏机制位于工具箱层,独立于任何模型级内容筛选器。
护栏通过其策略名称来引用,该名称可在 Foundry 门户的护栏下进行配置。 在创建工具箱版本时,将 policies.rai_config.rai_policy_name 设置为策略的名称。
from azure.identity import DefaultAzureCredential
from azure.ai.projects import AIProjectClient
from azure.ai.projects.models import WebSearchTool
endpoint = "https://<your-foundry-account>.services.ai.azure.com/api/projects/<your-project>"
project = AIProjectClient(endpoint=endpoint, credential=DefaultAzureCredential())
toolbox_version = project.beta.toolboxes.create_version(
name="my-toolbox",
description="Toolbox with guardrail",
tools=[WebSearchTool()],
policies={
"rai_config": {
"rai_policy_name": "/subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.CognitiveServices/accounts/<account-name>/raiPolicies/<policy-name>"
}
},
)
print(f"Created version: {toolbox_version.version}")
POST {endpoint}/toolboxes/{toolbox_name}/versions?api-version=v1
Authorization: Bearer {token}
Content-Type: application/json
{
"description": "Toolbox with guardrail",
"tools": [{ "type": "web_search" }],
"policies": {
"rai_config": {
"rai_policy_name": "/subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.CognitiveServices/accounts/<account-name>/raiPolicies/<policy-name>"
}
}
}
#pragma warning disable AAIP001
using Azure.AI.Projects;
using Azure.AI.Projects.Agents;
using Azure.Identity;
var projectEndpoint = Environment.GetEnvironmentVariable("FOUNDRY_PROJECT_ENDPOINT");
DefaultAzureCredential credential = new();
AIProjectClient projectClient = new(endpoint: new Uri(projectEndpoint), tokenProvider: credential);
AgentToolboxes toolboxClient = projectClient.AgentAdministrationClient.GetAgentToolboxes();
var toolboxVersion = toolboxClient.CreateToolboxVersion(
toolboxName: "my-toolbox",
description: "Toolbox with guardrail",
tools: [new WebSearchTool()],
policies: new ToolboxPolicies
{
RaiConfig = new RaiConfig { RaiPolicyName = "/subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.CognitiveServices/accounts/<account-name>/raiPolicies/<policy-name>" }
});
Console.WriteLine($"Created version: {toolboxVersion.Version}");
const toolboxVersion = await project.beta.toolboxes.createVersion(
"my-toolbox",
[{ type: "web_search" }],
{
description: "Toolbox with guardrail",
policies: {
rai_config: {
rai_policy_name: "/subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.CognitiveServices/accounts/<account-name>/raiPolicies/<policy-name>",
},
},
},
);
console.log(`Created version: ${toolboxVersion.version}`);
name: my-toolbox
description: Toolbox with guardrail
policies:
rai_config:
rai_policy_name: /subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.CognitiveServices/accounts/<account-name>/raiPolicies/<policy-name>
tools:
- type: web_search
VS Code 扩展中尚不提供护栏配置。 使用 REST API、SDK 或 azd 配置防护措施。
将技能添加到工具箱
将 技能 附加到工具箱版本,使其通过工具箱 MCP 终结点提供给代理。 每个技能引用指定技能名称和可选版本。 省略 version 以使用技能的 default_version;固定 version 字符串以使用不可变快照。
工具箱版本可以包含工具、技能或两者。 以下示例创建包含单个技能引用的工具箱版本。 若要向已包含工具的工具箱中添加技能,请加入与在tools中使用的相同的,以及skills数组。
重要
附加到工具箱的技能必须存在于同一 Foundry 项目中。 不支持跨项目引用。
当代理或 MCP 客户端连接到工具箱终结点时,技能将公开为 MCP 资源。 MCP 客户端或代理框架必须支持 MCP 资源协议才能自动发现和加载技能。 若要验证技能是否可被发现,请调用工具箱 MCP 端点上的 resources/list,并确认响应中显示了您的技能名称。
POST {endpoint}/toolboxes/{toolbox_name}/versions?api-version=v1
Authorization: Bearer {token}
Content-Type: application/json
Accept: application/json
Foundry-Features: Skills=V1Preview
{
"description": "Toolbox with a skill reference",
"tools": [],
"skills": [
{
"type": "skill_reference",
"name": "greeting"
}
]
}
要固定特定版本,请执行以下操作:
{
"skills": [
{
"type": "skill_reference",
"name": "greeting",
"version": "v1"
}
]
}
from azure.ai.projects.models import ToolboxSkillReference
toolbox_version = project.beta.toolboxes.create_version(
name="my-toolbox",
description="Toolbox with a skill reference",
tools=[],
skills=[
ToolboxSkillReference(name="greeting"), # use default version
# ToolboxSkillReference(name="greeting", version="v1"), # pin to v1
],
)
print(f"Created toolbox version: {toolbox_version.id}")
#pragma warning disable AAIP001
// Reuse the AgentToolboxes client (toolboxClient) from Step 1.
ToolboxSkillReference skillRef = new("greeting");
// To pin a version: new ToolboxSkillReference("greeting") { Version = "v1" }
ToolboxVersion toolboxVersion = toolboxClient.CreateToolboxVersion(
name: "my-toolbox",
tools: [],
skills: [skillRef],
description: "Toolbox with a skill reference"
);
Console.WriteLine($"Created toolbox version: {toolboxVersion.Id}");
const toolboxVersion = await project.beta.toolboxes.createVersion(
"my-toolbox",
[],
{
description: "Toolbox with a skill reference",
skills: [
{ type: "skill_reference", name: "greeting" },
// { type: "skill_reference", name: "greeting", version: "v1" }, // pin to v1
],
},
);
console.log(`Created toolbox version: ${toolboxVersion.id}`);
Azure Developer CLI 在两个位置支持技能引用:声明性地作为 skills: YAML 中的顶级 azd ai toolbox create --from-file 块,以及命令式地与 azd ai toolbox skill add/list/remove 动词一起使用。 每个引用采用一个 name (必需)和一个可选 version (字符串)。 省略 version 以遵循技能的 default_version;固定版本字符串以将工具箱锁定到不可变快照。
创建工具箱时声明技能
# my-toolbox.yaml
description: Toolbox with skill references
connections:
- name: my-gh-conn
skills:
- name: greeting # follows the skill's default version
- name: review-checklist
version: "2" # pin to skill version 2
azd ai toolbox create my-toolbox --from-file ./my-toolbox.yaml --no-prompt
在现有工具箱上添加、列出和删除技能
# Add a skill (follows default version)
azd ai toolbox skill add my-toolbox greeting
# Add a skill pinned to a specific version
azd ai toolbox skill add my-toolbox review-checklist@2
# Add multiple skills from a file (same shape as the create YAML's skills block)
azd ai toolbox skill add my-toolbox --from-file ./skills.yaml
# List skill references on the current default version
azd ai toolbox skill list my-toolbox --output table
# Remove a skill (--force skips the confirmation prompt; multiple names allowed)
azd ai toolbox skill remove my-toolbox greeting --force
skill list 仅显示默认版本。 已固定的技能显示其版本号;未固定的技能显示 (default)。 若要查看待定版本中的技能,请运行 azd ai toolbox show <toolbox> --version <n> --output json 并读取 skills 数组。
重要
skill add 和 skill remove 都会创建一个新的工具箱版本,该版本会沿用之前附加的所有连接和技能,并应用所请求的更改。
它们不会将新版本提升为默认值,因此在运行 azd ai toolbox publish <toolbox> <version>之前,MCP 客户端不会看到更改。 若要更改已附加技能的固定版本(例如,从 v1 升级到 greeting v2),请按顺序运行三个命令: skill removepublish新版本,然后skill add <name>@<new-version>(skill add针对当前默认版本进行检查时阻止重复)。
技能名称必须匹配 ^[a-z0-9]([a-z0-9\-]*[a-z0-9])?$ (小写字母、数字和连字符;最大 64 个字符;无前导或尾随连字符)。 在 @ 中尾随的 <name>@<version>(即空版本)会被拒绝。
技能引用当前无法通过 VS Code 扩展进行配置。 使用 REST API 或 SDK 配置技能。
验证技能发现
将技能附加到工具箱版本后,使用 MCP Python SDK 验证它们是否可通过工具箱 MCP 终结点发现:
import asyncio
from azure.identity import DefaultAzureCredential
from mcp import ClientSession
from mcp.client.streamable_http import streamablehttp_client
async def list_skills():
credential = DefaultAzureCredential()
token = credential.get_token("https://ai.azure.com/.default").token
toolbox_url = "{endpoint}/toolboxes/my-toolbox/mcp?api-version=v1"
headers = {
"Authorization": f"Bearer {token}",
}
async with streamablehttp_client(toolbox_url, headers=headers) as (read, write, _):
async with ClientSession(read, write) as session:
await session.initialize()
resources = await session.list_resources()
for resource in resources.resources:
print(f"Skill: {resource.uri} - {resource.name}")
asyncio.run(list_skills())
技能以 MCP 资源的形式出现,URI 格式为 skill://{name}。
调用来自智能体(Microsoft Agent Framework 和 .NET)的技能
在 .NET 中,使用 Microsoft Agent Framework SDK 中的 AgentSkillsProviderBuilder().UseMcpSkills(mcpClient) 从工具箱端点发现基于 MCP 的技能,并将其作为 AIContextProviders 注入代理中。 然后,当模型决定相关时,代理会在运行时加载每个技能的说明。 下面的 Program.cs 代理承载了响应托管层(AddFoundryResponses 和 MapFoundryResponses)。
using System.Net.Http.Headers;
using Azure.AI.Projects;
using Azure.Core;
using Azure.Identity;
using DotNetEnv;
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.Foundry.Hosting;
using Microsoft.Extensions.AI;
using ModelContextProtocol.Client;
// Load .env file if present (for local development).
Env.TraversePath().Load();
string projectEndpoint = Environment.GetEnvironmentVariable("FOUNDRY_PROJECT_ENDPOINT")
?? throw new InvalidOperationException("FOUNDRY_PROJECT_ENDPOINT environment variable is not set.");
string deployment = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLOYMENT_NAME")
?? throw new InvalidOperationException("AZURE_AI_MODEL_DEPLOYMENT_NAME environment variable is not set.");
string toolboxName = Environment.GetEnvironmentVariable("TOOLBOX_NAME")
?? throw new InvalidOperationException("TOOLBOX_NAME environment variable is not set.");
// Build the Foundry Toolbox MCP URL from the project endpoint and toolbox name.
string toolboxMcpServerUrl = $"{projectEndpoint.TrimEnd('/')}/toolboxes/{toolboxName}/mcp?api-version=v1";
TokenCredential credential = new DefaultAzureCredential();
// HttpClient that attaches a fresh Foundry bearer token to every request.
// CheckCertificateRevocationList = true satisfies CA5399.
using var httpClient = new HttpClient(
new BearerTokenHandler(credential, "https://ai.azure.com/.default")
{
CheckCertificateRevocationList = true,
});
Console.WriteLine($"Connecting to Foundry Toolbox '{toolboxName}' MCP server...");
// Connect to the Foundry Toolbox MCP endpoint.
await using var mcpClient = await McpClient.CreateAsync(
new HttpClientTransport(
new HttpClientTransportOptions
{
Endpoint = new Uri(toolboxMcpServerUrl),
Name = toolboxName,
TransportMode = HttpTransportMode.StreamableHttp,
},
httpClient));
// AgentSkillsProvider implements progressive disclosure over the MCP-discovered skills:
// names and descriptions are advertised in the system prompt, and the full skill body
// (and any supplementary resources) is loaded on demand when the model decides it is
// relevant.
var skillsProvider = new AgentSkillsProviderBuilder()
.UseMcpSkills(mcpClient)
.Build();
AIAgent agent = new AIProjectClient(new Uri(projectEndpoint), credential)
.AsAIAgent(new ChatClientAgentOptions
{
Name = "foundry-toolbox-mcp-skills",
Description = "Agent that discovers MCP-based skills from a Foundry Toolbox and exposes them via AgentSkillsProvider.",
ChatOptions = new ChatOptions
{
ModelId = deployment,
Instructions = "You are a helpful assistant.",
},
AIContextProviders = [skillsProvider],
});
var builder = AgentHost.CreateBuilder(args);
builder.Services.AddFoundryResponses(agent);
builder.RegisterProtocol("responses", endpoints => endpoints.MapFoundryResponses());
var app = builder.Build();
app.Run();
// HttpClientHandler that attaches a fresh Foundry bearer token to every outgoing request.
internal sealed class BearerTokenHandler(TokenCredential credential, string scope) : HttpClientHandler
{
private readonly TokenRequestContext _tokenContext = new([scope]);
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
AccessToken token = await credential.GetTokenAsync(this._tokenContext, cancellationToken).ConfigureAwait(false);
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token.Token);
return await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
}
}
有关完整的示例,包括项目文件和部署步骤,请参阅 工具箱中的 Skills 示例。
虚拟网络支持
当 Foundry 项目使用 网络隔离(专用链接)时,并非所有工具箱工具类型都受支持。 下表显示了每种工具类型的支持状态以及流量在网络隔离环境中流动的方式。
| 工具类型 | VNet 支持 | 流量流 |
|---|---|---|
| Mcp | ✅ 支持 | 通过您的 VNet 子网 |
| Azure AI 搜索 | ✅ 支持 | 通过专用终结点 |
| 代码解释器 | ✅ 支持 | Microsoft主干网络 |
| Web 搜索 | ✅ 支持 | 公共终结点 |
| OpenAPI | ✅ 支持 | 取决于目标 API 网络配置 |
| 文件搜索 | ❌ 不支持 | 尚不可用 |
| 代理到代理 (A2A) | ✅ 支持 | 通过专用终结点 |
| Fabric IQ | ❌ 不支持 | 尚不可用 |
| 工作 IQ | ❌ 不支持 | 尚不可用 |
| 浏览器自动化 | ❌ 不支持 | 尚不可用 |
有关完整的网络隔离设置说明(包括代理客户端的 VNet 注入、DNS 配置和专用终结点要求),请参阅 配置 Microsoft Foundry 的网络隔离。
区域和模型兼容性
工具箱可用性取决于项目区域以外的两个因素:
- 区域:某些工具类型在支持代理服务的每个区域中都不可用。 例如,支持工具箱终结点的区域可能不支持所有内置工具类型。
在部署工具箱之前,请验证目标区域是否支持计划使用的工具类型。 有关完整的兼容性表,请参阅 按区域和模型提供的工具支持。