你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

将代理连接到 OpenAPI 工具

使用 OpenAPI 3.0 和 3.1 规范将 Microsoft Foundry 代理连接到外部 API。 支持代理的 Foundry 模型可以调用外部服务、检索实时数据,并将其功能扩展到内置函数之外。

OpenAPI 规范 定义了描述 HTTP API 的标准方法,以便可以将现有服务与代理集成。 Microsoft Foundry 支持三种身份验证方法:anonymousAPI keymanaged identity。 有关选择身份验证方法的帮助,请参阅 “选择身份验证方法”。

提示

请考虑使用 工具箱添加此工具。 通过使用工具箱,可以跨代理和运行时重复使用该工具,并通过托管 MCP 终结点集中凭据管理、版本管理和策略强制实施。 请参阅 工具箱快速入门

使用支持

下表显示了 SDK 和设置支持。

Microsoft Foundry 支持 Python SDK C# SDK JavaScript SDK Java SDK REST API 基本代理设置 标准代理设置
✔️ ✔️ ✔️ ✔️ ✔️ ✔️ ✔️ ✔️

注意

对于 Java,请使用 openAPI 代理工具的 com.azure:azure-ai-agents 包。 该 com.azure:azure-ai-projects 包当前不公开 OpenAPI 代理工具类型。

先决条件

在开始之前,请确保具备:

  • 具有适当权限的Azure订阅。
  • Azure RBAC 角色:Foundry 项目的参与者或所有者。
  • 已创建配置了终结点的 Foundry 项目。
  • 在项目中部署的 AI 模型。
  • 基本或标准代理环境
  • 为首选语言安装的 SDK:
    • Python:azure-ai-projects
    • C#:Azure.AI.Extensions.OpenAI
    • TypeScript/JavaScript: @azure/ai-projects
    • Java:com.azure:azure-ai-agents

环境变量

变量 描述
FOUNDRY_PROJECT_ENDPOINT 你的 Foundry 项目端点 URL(不是外部 OpenAPI 服务端点)。
FOUNDRY_MODEL_DEPLOYMENT_NAME 您已部署的模型名称。
OPENAPI_PROJECT_CONNECTION_NAME (对于 API 密钥身份验证)OpenAPI 服务的项目连接名称。
  • 满足以下要求的 OpenAPI 3.0 或 3.1 规范文件:
    • 每个函数都必须有一个 operationId(这是 OpenAPI 工具所需的)。
    • operationId应仅包含字母和 -_
    • 使用描述性名称帮助模型有效地确定要使用的函数。
    • 支持的请求正文内容类型: application/jsonapplication/json-patch+json
  • 对于托管标识身份验证:在目标服务资源上需要读者角色或更高权限。
  • 对于 API 密钥/令牌身份验证:使用你的 API 密钥或令牌配置的项目连接。 请参阅 向项目添加新连接

注意

FOUNDRY_PROJECT_ENDPOINT 值是指 Microsoft Foundry 项目终结点,而不是外部 OpenAPI 服务终结点。 可以在项目的“概述”页下的 Microsoft Foundry 门户中找到此终结点。 此终结点需要对代理服务进行身份验证,并且独立于规范文件中定义的任何 OpenAPI 终结点。

了解限制

  • OpenAPI 规范的每个操作都必须包含 operationId,且 operationId 只能包含字母、-_
  • 支持的请求正文内容类型: application/jsonapplication/json-patch+json
  • 对于 API 密钥身份验证,请使用每个 OpenAPI 工具的一个 API 密钥安全方案。 如果需要多个安全方案,请创建多个 OpenAPI 工具。

将 OpenAPI 工具添加到工具箱

使用此模式公开 OpenAPI 规范描述的任何 REST API。 auth.type 选择与 API 的安全模型匹配的项。

重要

使用托管标识进行身份验证时,必须在目标服务上为 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",
      },
    },
  },
];

使用 Azure 开发人员 CLI 创建 OpenAPI 工具箱

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=******"

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

运行代码示例之前

注意

  • 需要最新的 SDK 包。 .NET SDK 目前为预览版。 有关详细信息,请参阅 快速入门
  • 如果使用 API 密钥进行身份验证,则连接 ID 的格式应为 /subscriptions/{{subscriptionID}}/resourceGroups/{{resourceGroupName}}/providers/Microsoft.CognitiveServices/accounts/{{foundryAccountName}}/projects/{{foundryProjectName}}/connections/{{foundryConnectionName}}

重要

若要使 API 密钥身份验证正常工作,OpenAPI 规范文件必须包括:

  1. 包含你的 API 密钥配置(如标头名称和参数名称)的 securitySchemes 部分。
  2. security 部分引用安全方案。
  3. 使用匹配的密钥名称和值配置的项目连接。

如果没有这些配置,API 密钥不会包含在请求中。 有关详细的设置说明,请参阅“ 使用 API 密钥进行身份验证 ”部分。

还可以通过将令牌存储在项目连接中来使用基于令牌的身份验证(例如持有者令牌)。 对于 Bearer 令牌身份验证,请创建一个 自定义密钥 连接,并将密钥设置为 Authorization,值设置为 Bearer <token>(将 <token> 替换为您的实际令牌)。 后跟空格的单词 Bearer 必须包含在值中。 有关详细信息,请参阅 设置持有者令牌连接

将代理与 OpenAPI 工具配合使用的示例

此示例演示如何通过代理使用由 OpenAPI 规范 描述的服务。 它使用 wttr.in 服务获取天气及其规范文件weather_openapi.json。 选择 Prompt Agents以使用 Azure AI Projects SDK 创建服务器端提示代理,或托管代理使用 Microsoft Agent Framework 生成临时进程内代理。

import os
import jsonref
from typing import Any, cast
from azure.identity import DefaultAzureCredential
from azure.ai.projects import AIProjectClient
from azure.ai.projects.models import (
    PromptAgentDefinition,
    OpenApiTool,
    OpenApiFunctionDefinition,
    OpenApiAnonymousAuthDetails,
)

# Format: "https://resource_name.ai.azure.com/api/projects/project_name"
PROJECT_ENDPOINT = "your_project_endpoint"
OPENAPI_CONNECTION_NAME = "my-openapi-connection"

# Create clients to call Foundry API
project = AIProjectClient(
    endpoint=PROJECT_ENDPOINT,
    credential=DefaultAzureCredential(),
)
openai = project.get_openai_client()

weather_asset_file_path = os.path.abspath(
    os.path.join(os.path.dirname(__file__), "../assets/weather_openapi.json")
)

with open(weather_asset_file_path, "r") as f:
    openapi_weather = cast(dict[str, Any], jsonref.loads(f.read()))

# Initialize agent OpenAPI tool using the read in OpenAPI spec
weather_tool = OpenApiTool(
    openapi=OpenApiFunctionDefinition(
        name="get_weather",
        spec=openapi_weather,
        description="Retrieve weather information for a location.",
        auth=OpenApiAnonymousAuthDetails(),
    )
)

# If you want to use key-based authentication
# IMPORTANT: Your OpenAPI spec must include securitySchemes and security sections
# Example spec structure for API key auth:
# {
#   "components": {
#     "securitySchemes": {
#       "apiKeyHeader": {
#         "type": "apiKey",
#         "name": "x-api-key",  # This must match the key name in your project connection
#         "in": "header"
#       }
#     }
#   },
#   "security": [{"apiKeyHeader": []}]
# }
#
# For ****** authentication, use this securitySchemes structure instead:
# {
#   "components": {
#     "securitySchemes": {
#       "bearerAuth": {
#         "type": "apiKey",
#         "name": "Authorization",
#         "in": "header"
#       }
#     }
#   },
#   "security": [{"bearerAuth": []}]
# }
# Then set connection key = "Authorization" and value = "******"
# The word "Bearer" followed by a space MUST be included in the value.

openapi_connection = project.connections.get(OPENAPI_CONNECTION_NAME)
connection_id = openapi_connection.id

openapi_key_auth_tool = {
    "type": "openapi",
    "openapi": {
        "name": "get_weather",
        "spec": openapi_weather,  # Must include securitySchemes and security sections
        "auth": {
            "type": "project_connection",
            "security_scheme": {
                "project_connection_id": connection_id
            }
        },
    }
}

# If you want to use Managed Identity authentication
openapi_mi_auth_tool = {
    "type": "openapi",
    "openapi": {
        "name": "get_weather",
        "description": "Retrieve weather information for a location.",
        "spec": openapi_weather,
        "auth": {
            "type": "managed_identity",
            "security_scheme": {
                "audience": "https://storage.azure.com"  # Resource identifier of the target service
            }
        },
    }
}

agent = project.agents.create_version(
    agent_name="MyAgent",
    definition=PromptAgentDefinition(
        model="gpt-4.1-mini",
        instructions="You are a helpful assistant.",
        tools=[weather_tool],
    ),
)
response = openai.responses.create(
    input="What's the weather in Seattle?",
    extra_body={"agent_reference": {"name": agent.name, "type": "agent_reference"}},
)
print(response.output_text)

# Clean up resources
project.agents.delete_version(agent_name=agent.name, agent_version=agent.version)

此示例使用 OpenAPI 工具创建一个提示代理,该工具使用匿名身份验证调用 wttr.in 天气 API。 该工具直接附加到代理定义。 运行代码时:

  1. 它从本地 JSON 文件加载天气 OpenAPI 规范。
  2. 使用配置为匿名访问的天气工具创建提示代理。
  3. 发送询问西雅图天气的查询。
  4. 代理使用 OpenAPI 工具调用天气 API 并返回格式化的结果。
  5. 通过删除代理软件版本进行清理。

将代理与 OpenAPI 工具配合使用的示例

此示例演示如何通过代理使用由 OpenAPI 规范 描述的服务。 它使用 wttr.in 服务获取天气及其规范文件weather_openapi.json。 选择 Prompt Agents以使用 Azure AI Projects SDK 创建服务器端提示代理,或托管代理使用 Microsoft Agent Framework 生成临时进程内代理。

此示例使用 Azure AI Projects 客户端库的同步方法。 有关使用异步方法的示例,请参阅GitHub上.NET存储库Azure SDK中的 sample

using System;
using System.IO;
using System.Runtime.CompilerServices;
using Azure.AI.Projects;
using Azure.AI.Extensions.OpenAI;
using Azure.Identity;

class OpenAPIDemo
{
    // Utility method to get the OpenAPI specification file from the Assets folder.
    private static string GetFile([CallerFilePath] string pth = "")
    {
        var dirName = Path.GetDirectoryName(pth) ?? "";
        return Path.Combine(dirName, "Assets", "weather_openapi.json");
    }

    public static void Main()
    {
        // Format: "https://resource_name.ai.azure.com/api/projects/project_name"
        var projectEndpoint = "your_project_endpoint";

        // Create project client to call Foundry API
        AIProjectClient projectClient = new(
            endpoint: new Uri(projectEndpoint),
            tokenProvider: new DefaultAzureCredential());

        // Create an Agent with `OpenAPIAgentTool` and anonymous authentication.
        string filePath = GetFile();
        OpenAPIFunctionDefinition toolDefinition = new(
            name: "get_weather",
            spec: BinaryData.FromBytes(File.ReadAllBytes(filePath)),
            auth: new OpenAPIAnonymousAuthenticationDetails()
        );
        toolDefinition.Description = "Retrieve weather information for a location.";
        OpenAPITool openapiTool = new(toolDefinition);

        // Create the agent definition and the agent version.
        DeclarativeAgentDefinition agentDefinition = new(model: "gpt-4.1-mini")
        {
            Instructions = "You are a helpful assistant.",
            Tools = { openapiTool }
        };
        AgentVersion agentVersion = projectClient.AgentAdministrationClient.CreateAgentVersion(
            agentName: "myAgent",
            options: new(agentDefinition));

        // Create a response object and ask the question about the weather in Seattle, WA.
        ProjectResponsesClient responseClient = projectClient.ProjectOpenAIClient.GetProjectResponsesClientForAgent(agentVersion.Name);
        ResponseResult response = responseClient.CreateResponse(
                userInputText: "Use the OpenAPI tool to print out, what is the weather in Seattle, WA today."
            );
        Console.WriteLine(response.GetOutputText());

        // Finally, delete all the resources created in this sample.
        projectClient.AgentAdministrationClient.DeleteAgentVersion(agentName: agentVersion.Name, agentVersion: agentVersion.Version);
    }
}

此代码的作用

此 C# 示例使用 OpenAPI 工具创建代理,该工具使用匿名身份验证从 wttr.in 检索天气信息。 运行代码时:

  1. 它从本地 JSON 文件读取天气 OpenAPI 规范。
  2. 使用配置的天气工具创建智能体。
  3. 使用 OpenAPI 工具发送询问西雅图天气的请求。
  4. 代理调用天气 API 并返回结果。
  5. 删除智能体以进行清理。

所需的输入

  • 内联字符串值:projectEndpoint(您的 Foundry 项目端点)
  • 本地文件: Assets/weather_openapi.json (OpenAPI 规范)

预期输出

The weather in Seattle, WA today is cloudy with temperatures around 52°F...

常见错误

  • FileNotFoundException:在 Assets 文件夹中找不到 OpenAPI 规范文件
  • UnauthorizedAccessException:凭据无效或 RBAC 权限不足
  • 未注入 API 密钥:验证 OpenAPI 规范是否同时包含 securitySchemes(位于 components)和 security 部分,并且方案名称一致

在 Web 服务上使用具有 OpenAPI 工具的代理的示例,需要身份验证

在此示例中,将经过身份验证的 OpenAPI 工具添加到工具箱,将工具箱附加为 MCP 工具,并在需要身份验证的方案中使用代理。 您使用 TripAdvisor 的规范。

TripAdvisor 服务需要基于密钥的身份验证。 若要在 Azure 门户中创建连接,请打开 Microsoft Foundry,并在左侧面板中选择 Management center,然后选择 Connected resources。 最后,创建新的 自定义密钥 类型连接。 为其 tripadvisor 命名并添加键值对。 先添加一个名为 key 的键,并输入您的 TripAdvisor 密钥对应的值。

class OpenAPIConnectedDemo
{
    // Utility method to get the OpenAPI specification file from the Assets folder.
    private static string GetFile([CallerFilePath] string pth = "")
    {
        var dirName = Path.GetDirectoryName(pth) ?? "";
        return Path.Combine(dirName, "Assets", "tripadvisor_openapi.json");
    }

    public static void Main()
    {
        // Format: "https://resource_name.ai.azure.com/api/projects/project_name"
        var projectEndpoint = "your_project_endpoint";

        // Create project client to call Foundry API
        AIProjectClient projectClient = new(
            endpoint: new Uri(projectEndpoint),
            tokenProvider: new DefaultAzureCredential());

        // Create an OpenAPI tool with authentication by project connection security scheme.
        string filePath = GetFile();
        AIProjectConnection tripadvisorConnection = projectClient.Connections.GetConnection("tripadvisor");
        OpenAPIFunctionDefinition toolDefinition = new(
            name: "tripadvisor",
            spec: BinaryData.FromBytes(File.ReadAllBytes(filePath)),
            auth: new OpenAPIProjectConnectionAuthenticationDetails(new OpenAPIProjectConnectionSecurityScheme(
                projectConnectionId: tripadvisorConnection.Id
            ))
        );
        toolDefinition.Description = "Trip Advisor API to get travel information.";
        ProjectsAgentTool openapiTool = new OpenAPITool(toolDefinition);

        // 1. Add the authenticated OpenAPI tool to a toolbox. Using a toolbox is the
        //    recommended way to give agents tools. See /azure/foundry/agents/concepts/toolbox-overview
        AgentToolboxes toolboxClient = projectClient.AgentAdministrationClient.GetAgentToolboxes();

        ToolboxVersion toolboxVersion = projectClient.AgentAdministrationClient
            .GetAgentToolboxes().CreateToolboxVersion(
                toolboxName: "openapi-toolbox",
                tools: [openapiTool],
                description: "Toolbox with the authenticated TripAdvisor OpenAPI tool");

        // 2. The toolbox exposes an MCP-compatible endpoint.
        var toolboxMcpUrl = new Uri(
            $"{projectEndpoint}/toolboxes/{toolboxVersion.Name}" +
            $"/versions/{toolboxVersion.Version}/mcp?api-version=v1");

        // 3. Create a remote-tool project connection that points at the toolbox endpoint.
        //    Use a user Entra token so the caller's identity is passed through
        //    (audience https://ai.azure.com). Create the connection once, for example
        //    with the Azure Developer CLI:
        //
        //    azd ai connection create openapi-toolbox-conn \
        //      --kind remote-tool \
        //      --target "<toolboxMcpUrl>" \
        //      --auth-type user-entra-token \
        //      --audience https://ai.azure.com
        var toolboxConnectionName = "openapi-toolbox-conn";

        // 4. Attach the toolbox to a prompt agent as an MCP tool.
        McpTool toolboxTool = ResponseTool.CreateMcpTool(
            serverLabel: "toolbox",
            serverUri: toolboxMcpUrl,
            toolCallApprovalPolicy: new McpToolCallApprovalPolicy(
                GlobalMcpToolCallApprovalPolicy.NeverRequireApproval));
        toolboxTool.ProjectConnectionId = toolboxConnectionName;

        // Create the agent definition and the agent version.
        DeclarativeAgentDefinition agentDefinition = new(model: "gpt-4.1-mini")
        {
            Instructions = "You are a helpful assistant.",
            Tools = { toolboxTool }
        };
        AgentVersion agentVersion = projectClient.AgentAdministrationClient.CreateAgentVersion(
            agentName: "myAgent",
            options: new(agentDefinition));

        // Create a response object and ask the question about the hotels in France.
        // Test the Web service access before you run production scenarios.
        // It can be done by setting:
        // ToolChoice = ResponseToolChoice.CreateRequiredChoice()`
        // in the ResponseCreationOptions. This setting will
        // force Agent to use tool and will trigger the error if it is not accessible.
        ProjectResponsesClient responseClient = projectClient.ProjectOpenAIClient.GetProjectResponsesClientForAgent(agentVersion.Name);
        CreateResponseOptions responseOptions = new()
        {
            ToolChoice = ResponseToolChoice.CreateRequiredChoice(),
            InputItems =
            {
                ResponseItem.CreateUserMessageItem("Recommend me 5 top hotels in paris, France."),
            }
        };
        ResponseResult response = responseClient.CreateResponse(
            options: responseOptions
        );
        Console.WriteLine(response.GetOutputText());

        // Finally, delete all the resources we have created in this sample.
        projectClient.AgentAdministrationClient.DeleteAgentVersion(agentName: agentVersion.Name, agentVersion: agentVersion.Version);
    }
}

此代码的作用

此 C# 示例演示如何通过工具箱和项目连接通过 API 密钥身份验证使用 OpenAPI 工具。 运行代码时:

  1. 它从本地文件加载 TripAdvisor OpenAPI 规范。
  2. 检索包含您的 API 密钥的tripadvisor项目连接。
  3. 创建一个工具箱版本,其中包含配置为使用连接进行身份验证的 TripAdvisor 工具。
  4. 将工具箱作为 MCP 工具附加到代理。
  5. 发送巴黎酒店推荐请求。
  6. 代理使用存储的 API 密钥调用 TripAdvisor API,并返回结果。
  7. 删除智能体以进行清理。

所需的输入

  • 内联字符串值:projectEndpoint(您的 Foundry 项目端点)
  • 本地文件: Assets/tripadvisor_openapi.json
  • 项目连接:配置了有效的 API 密钥的 tripadvisor

预期输出

Here are 5 top hotels in Paris, France:
1. Hotel Name - Rating: 4.5/5, Location: ...
2. Hotel Name - Rating: 4.4/5, Location: ...
...

常见错误

  • ConnectionNotFoundException:未找到名为 tripadvisor 的项目连接。
  • AuthenticationException:项目连接中的 API 密钥无效,或 OpenAPI 规范中缺少/不正确的 securitySchemes 配置。
  • 未使用的工具:验证 ToolChoice = ResponseToolChoice.CreateRequiredChoice() 会强制使用该工具。
  • 未将 API 密钥传递到 API:确保 OpenAPI 规范已正确配置了securitySchemessecurity部分。

使用 OpenAPI 工具功能创建Java代理

此Java设置可以引用 MCP 工具,但Java SDK 尚未公开工具箱创建 API。

提示

推荐: 对于大多数代理,通过 工具箱 添加 OpenAPI 工具,并将工具箱作为 MCP 工具附加到代理。 使用 PythonREST APIC#TypeScript 示例或 Foundry 门户创建工具箱,然后从Java代理引用其 MCP 终结点作为一个McpTool

以下示例演示如何使用 REST API 调用 OpenAPI 工具。

获取访问令牌:

export AGENT_TOKEN=$(az account get-access-token --scope "https://ai.azure.com/.default" --query accessToken -o tsv)

匿名身份验证

通过工具箱添加 OpenAPI 工具,然后将工具箱作为 MCP 工具附加到代理。 有关详细信息,请参阅 什么是工具箱?

  1. 创建包含 OpenAPI 天气工具的工具箱:
curl --request POST \
  --url "$FOUNDRY_PROJECT_ENDPOINT/toolboxes/openapi-toolbox/versions?api-version=v1" \
  -H "Content-Type: application/json" \
  --data '{
    "description": "Toolbox with the OpenAPI weather tool",
    "tools": [
      {
        "type": "openapi",
        "openapi": {
          "name": "weather",
          "description": "Tool to get weather data",
          "auth": { "type": "anonymous" },
          "spec": {
            "openapi": "3.1.0",
            "info": {
              "title": "get weather data",
              "description": "Retrieves current weather data for a location.",
              "version": "v1.0.0"
            },
            "servers": [{ "url": "https://wttr.in" }],
            "paths": {
              "/{location}": {
                "get": {
                  "description": "Get weather information for a specific location",
                  "operationId": "GetCurrentWeather",
                  "parameters": [
                    {
                      "name": "location",
                      "in": "path",
                      "description": "City or location to retrieve the weather for",
                      "required": true,
                      "schema": { "type": "string" }
                    },
                    {
                      "name": "format",
                      "in": "query",
                      "description": "Format in which to return data. Always use 3.",
                      "required": true,
                      "schema": { "type": "integer", "default": 3 }
                    }
                  ],
                  "responses": {
                    "200": {
                      "description": "Successful response",
                      "content": {
                        "text/plain": {
                          "schema": { "type": "string" }
                        }
                      }
                    },
                    "404": { "description": "Location not found" }
                  }
                }
              }
            }
          }
        }
      }
    ]
  }'

工具箱公开了 MCP 兼容的终结点,该终结点 $FOUNDRY_PROJECT_ENDPOINT/toolboxes/openapi-toolbox/versions/<version>/mcp?api-version=v1<version> 上一次调用返回的版本。

  1. 使用用户 Entra 令牌创建指向工具箱终结点的远程工具项目连接,以便调用方的身份通过(受众 https://ai.azure.com) 传递。
azd ai connection create openapi-toolbox-conn \
  --kind remote-tool \
  --target "$FOUNDRY_PROJECT_ENDPOINT/toolboxes/openapi-toolbox/versions/<version>/mcp?api-version=v1" \
  --auth-type user-entra-token \
  --audience https://ai.azure.com
  1. 通过附加工具箱作为 MCP 工具创建使用工具箱的响应。
curl --request POST \
  --url "$FOUNDRY_PROJECT_ENDPOINT/openai/v1/responses" \
  --header "Authorization: Bearer $AGENT_TOKEN" \
  --header "Content-Type: application/json" \
  --data '{
    "model": "'$FOUNDRY_MODEL_DEPLOYMENT_NAME'",
    "input": "Use the OpenAPI tool to get the weather in Seattle, WA today.",
    "tool_choice": "required",
    "tools": [
      {
        "type": "mcp",
        "server_label": "toolbox",
        "server_url": "'$FOUNDRY_PROJECT_ENDPOINT'/toolboxes/openapi-toolbox/versions/<version>/mcp?api-version=v1",
        "require_approval": "never",
        "project_connection_id": "openapi-toolbox-conn"
      }
    ]
  }'

API 密钥身份验证(项目连接)

curl --request POST \
  --url "$FOUNDRY_PROJECT_ENDPOINT/openai/v1/responses" \
  --header "Authorization: Bearer $AGENT_TOKEN" \
  --header "Content-Type: application/json" \
  --data '{
    "model": "'$FOUNDRY_MODEL_DEPLOYMENT_NAME'",
    "input": "Use the OpenAPI tool to get the weather in Seattle, WA today.",
    "tools": [
      {
        "type": "openapi",
        "openapi": {
          "name": "weather",
          "description": "Tool to get weather data",
          "auth": {
            "type": "project_connection",
            "security_scheme": {
              "project_connection_id": "'$WEATHER_APP_PROJECT_CONNECTION_ID'"
            }
          },
          "spec": {
            "openapi": "3.1.0",
            "info": {
              "title": "get weather data",
              "description": "Retrieves current weather data for a location.",
              "version": "v1.0.0"
            },
            "servers": [{ "url": "https://wttr.in" }],
            "paths": {
              "/{location}": {
                "get": {
                  "description": "Get weather information for a specific location",
                  "operationId": "GetCurrentWeather",
                  "parameters": [
                    {
                      "name": "location",
                      "in": "path",
                      "description": "City or location to retrieve the weather for",
                      "required": true,
                      "schema": { "type": "string" }
                    },
                    {
                      "name": "format",
                      "in": "query",
                      "description": "Format in which to return data. Always use 3.",
                      "required": true,
                      "schema": { "type": "integer", "default": 3 }
                    }
                  ],
                  "responses": {
                    "200": {
                      "description": "Successful response",
                      "content": {
                        "text/plain": {
                          "schema": { "type": "string" }
                        }
                      }
                    },
                    "404": { "description": "Location not found" }
                  }
                }
              }
            },
            "components": {
              "securitySchemes": {
                "apiKeyHeader": {
                  "type": "apiKey",
                  "name": "x-api-key",
                  "in": "header"
                }
              }
            },
            "security": [
              { "apiKeyHeader": [] }
            ]
          }
        }
      }
    ]
  }'

托管标识身份验证

curl --request POST \
  --url "$FOUNDRY_PROJECT_ENDPOINT/openai/v1/responses" \
  --header "Authorization: Bearer $AGENT_TOKEN" \
  --header "Content-Type: application/json" \
  --data '{
    "model": "'$FOUNDRY_MODEL_DEPLOYMENT_NAME'",
    "input": "Use the OpenAPI tool to get the weather in Seattle, WA today.",
    "tools": [
      {
        "type": "openapi",
        "openapi": {
          "name": "weather",
          "description": "Tool to get weather data",
          "auth": {
            "type": "managed_identity",
            "security_scheme": {
              "audience": "'$MANAGED_IDENTITY_AUDIENCE'"
            }
          },
          "spec": {
            "openapi": "3.1.0",
            "info": {
              "title": "get weather data",
              "description": "Retrieves current weather data for a location.",
              "version": "v1.0.0"
            },
            "servers": [{ "url": "https://wttr.in" }],
            "paths": {
              "/{location}": {
                "get": {
                  "description": "Get weather information for a specific location",
                  "operationId": "GetCurrentWeather",
                  "parameters": [
                    {
                      "name": "location",
                      "in": "path",
                      "description": "City or location to retrieve the weather for",
                      "required": true,
                      "schema": { "type": "string" }
                    },
                    {
                      "name": "format",
                      "in": "query",
                      "description": "Format in which to return data. Always use 3.",
                      "required": true,
                      "schema": { "type": "integer", "default": 3 }
                    }
                  ],
                  "responses": {
                    "200": {
                      "description": "Successful response",
                      "content": {
                        "text/plain": {
                          "schema": { "type": "string" }
                        }
                      }
                    },
                    "404": { "description": "Location not found" }
                  }
                }
              }
            }
          }
        }
      }
    ]
  }'

此代码的作用

此 REST API 示例演示如何使用不同的身份验证方法调用 OpenAPI 工具。 请求:

  1. 对于匿名身份验证,请创建一个工具箱,其中包含 OpenAPI 工具定义和天气 API 规范。
  2. 创建一个响应,该响应将工具箱附加为 MCP 工具,并询问西雅图的天气。
  3. 通过项目连接和托管标识身份验证显示 API 密钥的其他直接 REST 工具定义。
  4. 代理使用该工具调用天气 API 并返回格式化结果。

所需的输入

  • 环境变量:FOUNDRY_PROJECT_ENDPOINT、、AGENT_TOKENFOUNDRY_MODEL_DEPLOYMENT_NAME.
  • 对于 API 密钥身份验证: WEATHER_APP_PROJECT_CONNECTION_ID.
  • 对于托管标识身份验证: MANAGED_IDENTITY_AUDIENCE.
  • 请求正文中的内联 OpenAPI 规范。

预期输出

{
  "id": "resp_abc123",
  "object": "response",
  "output": [
    {
      "type": "message",
      "content": [
        {
          "type": "text",
          "text": "The weather in Seattle, WA today is cloudy with a temperature of 52°F (11°C)..."
        }
      ]
    }
  ]
}

常见错误

  • 401 Unauthorized:无效或缺失AGENT_TOKEN,或因为在您的 OpenAPI 规范中缺少securitySchemessecurity,API 密钥未嵌入
  • 404 Not Found:终结点或模型部署名称不正确
  • 400 Bad Request:格式不正确的 OpenAPI 规范或无效的身份验证配置
  • API 密钥未随请求一起发送:请检查 OpenAPI 规范中的components.securitySchemes部分是否已正确配置(且不为空),并且与项目的连接密钥名称一致。

使用 OpenAPI 工具功能创建代理

以下 TypeScript 代码示例演示如何通过将 OpenAPI 工具添加到工具箱并将工具箱附加为 MCP 工具来创建具有 OpenAPI 工具功能的 AI 代理。 代理可以调用 OpenAPI 规范定义的外部 API。 有关此示例的 JavaScript 版本,请参阅 GitHub 上的 javaScript 存储库Azure SDK中的 sample

import { DefaultAzureCredential } from "@azure/identity";
import {
  AIProjectClient,
  OpenApiTool,
  OpenApiFunctionDefinition,
  OpenApiAnonymousAuthDetails,
} from "@azure/ai-projects";
import * as fs from "fs";
import * as path from "path";

// Format: "https://resource_name.ai.azure.com/api/projects/project_name"
const PROJECT_ENDPOINT = "your_project_endpoint";
const weatherSpecPath = path.resolve(__dirname, "../assets", "weather_openapi.json");

function loadOpenApiSpec(specPath: string): unknown {
  if (!fs.existsSync(specPath)) {
    throw new Error(`OpenAPI specification not found at: ${specPath}`);
  }

  try {
    const data = fs.readFileSync(specPath, "utf-8");
    return JSON.parse(data);
  } catch (error) {
    throw new Error(`Failed to read or parse OpenAPI specification at ${specPath}: ${error}`);
  }
}

function createWeatherTool(spec: unknown): OpenApiTool {
  const auth: OpenApiAnonymousAuthDetails = { type: "anonymous" };
  const definition: OpenApiFunctionDefinition = {
    name: "get_weather",
    description: "Retrieve weather information for a location using wttr.in",
    spec,
    auth,
  };

  return {
    type: "openapi",
    openapi: definition,
  };
}

export async function main(): Promise<void> {
  const weatherSpec = loadOpenApiSpec(weatherSpecPath);

  // Create clients to call Foundry API
  const project = new AIProjectClient(PROJECT_ENDPOINT, new DefaultAzureCredential());
  const openai = project.getOpenAIClient();

  const weatherTool = createWeatherTool(weatherSpec);

  console.log("Creating a toolbox with the OpenAPI weather tool...");

  // 1. Add the OpenAPI tool to a toolbox. Using a toolbox is the recommended
  //    way to give agents tools. See /azure/foundry/agents/concepts/toolbox-overview
  const toolbox = await project.toolboxes.createVersion(
    "openapi-toolbox",
    [weatherTool],
    { description: "Toolbox with the OpenAPI weather tool" },
  );

  // 2. The toolbox exposes an MCP-compatible endpoint.
  const toolboxMcpUrl =
    `${PROJECT_ENDPOINT}/toolboxes/${toolbox.name}` +
    `/versions/${toolbox.version}/mcp?api-version=v1`;

  // 3. Create a remote-tool project connection that points at the toolbox endpoint.
  //    Use a user Entra token so the caller's identity is passed through
  //    (audience https://ai.azure.com). Create the connection once, for example
  //    with the Azure Developer CLI:
  //
  //    azd ai connection create openapi-toolbox-conn \
  //      --kind remote-tool \
  //      --target "<toolboxMcpUrl>" \
  //      --auth-type user-entra-token \
  //      --audience https://ai.azure.com
  const toolboxConnectionName = "openapi-toolbox-conn";

  // 4. Attach the toolbox to a prompt agent as an MCP tool.
  const agent = await project.agents.createVersion("MyOpenApiAgent", {
    kind: "prompt",
    model: "gpt-4.1-mini",
    instructions:
      "You are a helpful assistant that can call external APIs defined by OpenAPI specs to answer user questions.",
    tools: [
      {
        type: "mcp",
        server_label: "toolbox",
        server_url: toolboxMcpUrl,
        require_approval: "never",
        project_connection_id: toolboxConnectionName,
      },
    ],
  });

  // Send a request and stream the response
  const streamResponse = await openai.responses.create(
    {
      input:
        "What's the weather in Seattle and how should I plan my outfit for the day based on the forecast?",
      stream: true,
    },
    {
      body: {
        agent: { name: agent.name, type: "agent_reference" },
        tool_choice: "required",
      },
    },
  );

  // Process the streaming response
  for await (const event of streamResponse) {
    if (event.type === "response.output_text.delta") {
      process.stdout.write(event.delta);
    } else if (event.type === "response.output_text.done") {
      console.log("\n");
    }
  }

  // Clean up resources
  await project.agents.deleteVersion(agent.name, agent.version);
}

main().catch((err) => {
  console.error("The sample encountered an error:", err);
});

此代码的作用

此 TypeScript 示例使用 OpenAPI 工具通过匿名身份验证创建一个代理,用于天气数据。 运行代码时:

  1. 它从本地 JSON 文件加载天气 OpenAPI 规范。
  2. 创建包含天气工具的工具箱版本。
  3. 将工具箱作为 MCP 工具附加到代理,然后发送一个流式处理请求,询问西雅图的天气和服装规划。
  4. 处理流式响应,并在增量到达时显示增量。
  5. 它强制使用 tool_choice: "required" 工具,以确保调用 API。
  6. 删除智能体以进行清理。

所需的输入

  • 内联字符串值:PROJECT_ENDPOINT(您的 Foundry 项目端点)
  • 本地文件: ../assets/weather_openapi.json (OpenAPI 规范)

预期输出

Loading OpenAPI specifications from assets directory...
Creating agent with OpenAPI tool...
Agent created (id: asst_abc123, name: MyOpenApiAgent, version: 1)

Sending request to OpenAPI-enabled agent with streaming...
Follow-up response created with ID: resp_xyz789
The weather in Seattle is currently...
Tool call completed: get_weather

Follow-up completed!

Cleaning up resources...
Agent deleted

OpenAPI agent sample completed!

常见错误

  • Error: OpenAPI specification not found:文件路径不正确或文件缺失
  • AuthenticationError:凭据 Azure无效
  • API 密钥不起作用:如果从匿名切换到 API 密钥身份验证,请确保 OpenAPI 规范已securitySchemessecurity正确配置

创建使用通过项目连接进行身份验证的 OpenAPI 工具的代理

以下 TypeScript 代码示例演示如何创建使用通过项目连接进行身份验证的 OpenAPI 工具的 AI 代理。 代理从本地资产加载 TripAdvisor OpenAPI 规范,并通过配置的项目连接调用 API。 有关此示例的 JavaScript 版本,请参阅 GitHub 上的 javaScript 存储库Azure SDK中的 sample

import { DefaultAzureCredential } from "@azure/identity";
import {
  AIProjectClient,
  OpenApiTool,
  OpenApiFunctionDefinition,
  OpenApiProjectConnectionAuthDetails,
} from "@azure/ai-projects";
import * as fs from "fs";
import * as path from "path";

// Format: "https://resource_name.ai.azure.com/api/projects/project_name"
const PROJECT_ENDPOINT = "your_project_endpoint";
const TRIPADVISOR_CONNECTION_ID = "your-tripadvisor-connection-id";
const tripAdvisorSpecPath = path.resolve(__dirname, "../assets", "tripadvisor_openapi.json");

function loadOpenApiSpec(specPath: string): unknown {
  if (!fs.existsSync(specPath)) {
    throw new Error(`OpenAPI specification not found at: ${specPath}`);
  }

  try {
    const data = fs.readFileSync(specPath, "utf-8");
    return JSON.parse(data);
  } catch (error) {
    throw new Error(`Failed to read or parse OpenAPI specification at ${specPath}: ${error}`);
  }
}

function createTripAdvisorTool(spec: unknown): OpenApiTool {
  const auth: OpenApiProjectConnectionAuthDetails = {
    type: "project_connection",
    security_scheme: {
      project_connection_id: TRIPADVISOR_CONNECTION_ID,
    },
  };

  const definition: OpenApiFunctionDefinition = {
    name: "get_tripadvisor_location_details",
    description:
      "Fetch TripAdvisor location details, reviews, or photos using the Content API via project connection auth.",
    spec,
    auth,
  };

  return {
    type: "openapi",
    openapi: definition,
  };
}

export async function main(): Promise<void> {
  const tripAdvisorSpec = loadOpenApiSpec(tripAdvisorSpecPath);

  // Create clients to call Foundry API
  const project = new AIProjectClient(PROJECT_ENDPOINT, new DefaultAzureCredential());
  const openai = project.getOpenAIClient();

  // Create an agent with the OpenAPI project-connection tool
  const agent = await project.agents.createVersion("MyOpenApiConnectionAgent", {
    kind: "prompt",
    model: "gpt-4.1-mini",
    instructions:
      "You are a travel assistant that consults the TripAdvisor Content API via project connection to answer user questions about locations.",
    tools: [createTripAdvisorTool(tripAdvisorSpec)],
  });

  // Send a request and stream the response
  const streamResponse = await openai.responses.create(
    {
      input:
        "Provide a quick overview of the TripAdvisor location 293919 including its name, rating, and review count.",
      stream: true,
    },
    {
      body: {
        agent: { name: agent.name, type: "agent_reference" },
        tool_choice: "required",
      },
    },
  );

  // Process the streaming response
  for await (const event of streamResponse) {
    if (event.type === "response.output_text.delta") {
      process.stdout.write(event.delta);
    } else if (event.type === "response.output_text.done") {
      console.log("\n");
    }
  }

  // Clean up resources
  await project.agents.deleteVersion(agent.name, agent.version);
}

main().catch((err) => {
  console.error("The sample encountered an error:", err);
});

此代码的作用

此 TypeScript 示例演示如何通过项目连接通过 API 密钥身份验证使用 OpenAPI 工具。 运行代码时:

  1. 它从本地文件加载 TripAdvisor OpenAPI 规范。
  2. 它使用 TRIPADVISOR_CONNECTION_ID 常量配置身份验证。
  3. 它使用 TripAdvisor 工具创建一个代理,该工具使用项目连接进行 API 密钥身份验证。
  4. 它会发送获取TripAdvisor位置详细信息的流式请求。
  5. 它强制使用 tool_choice: "required" 工具,以确保调用 API。
  6. 它处理并显示流式响应。
  7. 通过删除智能体进行清理。

所需的输入

  • 内联字符串值: PROJECT_ENDPOINTTRIPADVISOR_CONNECTION_ID
  • 本地文件: ../assets/tripadvisor_openapi.json
  • 使用 TripAdvisor API 密钥配置的项目连接

预期输出

Loading TripAdvisor OpenAPI specification from assets directory...
Creating agent with OpenAPI project-connection tool...
Agent created (id: asst_abc123, name: MyOpenApiConnectionAgent, version: 1)

Sending request to TripAdvisor OpenAPI agent with streaming...
Follow-up response created with ID: resp_xyz789
Location 293919 is the Eiffel Tower in Paris, France. It has a rating of 4.5 stars with over 140,000 reviews...
Tool call completed: get_tripadvisor_location_details

Follow-up completed!

Cleaning up resources...
Agent deleted

TripAdvisor OpenAPI agent sample completed!

常见错误

  • Error: OpenAPI specification not found:检查文件路径。
  • 找不到连接:验证 TRIPADVISOR_CONNECTION_ID 是否正确并存在连接。
  • AuthenticationException:项目连接中的 API 密钥无效。
  • 请求中未注入 API 密钥:你的 OpenAPI 规范必须包含正确的 securitySchemes(位于 components)和 security 部分。 中的 securitySchemes 密钥名称必须与项目连接中的密钥匹配。
  • Content type is not supported:目前,仅支持这两种请求正文内容类型: application/jsonapplication/json-patch+json。 响应内容类型不受限制。

安全性和数据注意事项

将代理连接到 OpenAPI 工具时,代理可以将派生自用户输入的请求参数发送到目标 API。

  • 使用项目连接来管理机密(API 密钥和令牌)。 避免将机密放入 OpenAPI 规范文件或源代码中。
  • 在生产环境中使用该工具之前,请查看 API 接收的数据及其返回的数据。
  • 使用最小权限进行访问。 对于托管标识,仅分配目标服务所需的角色。

使用 API 密钥进行身份验证

通过使用 API 密钥身份验证,可以使用各种方法(如 API 密钥或持有者令牌)对 OpenAPI 规范进行身份验证。 每个 OpenAPI 规范只能使用一个 API 密钥安全架构。如果需要多个安全架构,请创建多个 OpenAPI 规范工具。

  1. 更新 OpenAPI 规范安全架构。 它包含一个securitySchemes部分和一个apiKey类型的方案。 例如:

     "securitySchemes": {
         "apiKeyHeader": {
                 "type": "apiKey",
                 "name": "x-api-key",
                 "in": "header"
             }
     }
    

    通常只需更新 name 字段,该字段与连接中的名称 key 相对应。 如果安全方案包含多个方案,则只保留其中一个方案。

  2. 更新 OpenAPI 规范以包括一个 security 部分:

    "security": [
         {  
         "apiKeyHeader": []  
         }  
     ]
    
  3. 删除 OpenAPI 规范中需要 API 密钥的任何参数,因为 API 密钥是通过连接存储和传递的,如本文稍后所述。

  4. 创建用于存储 API 密钥的连接。

  5. 转到 Foundry 门户 并打开您的项目。

  6. 创建或选择存储机密的连接。 请参阅 向项目添加新连接

    注意

    如果稍后重新生成 API 密钥,则需要使用新密钥更新连接。

  7. 输入以下信息

    • 键:安全架构的 name 字段。 在此示例中,它应为 x-api-key

             "securitySchemes": {
                "apiKeyHeader": {
                          "type": "apiKey",
                          "name": "x-api-key",
                          "in": "header"
                      }
              }
      
    • 值:YOUR_API_KEY

  8. 创建连接后,可以通过 SDK 或 REST API 使用它。 使用本文顶部的选项卡查看代码示例。

设置持有者令牌连接

可以使用基于令牌的身份验证(例如持有者令牌),该身份验证类型与用于 API 密钥的身份验证类型相同 project_connection 。 主要区别在于如何配置 OpenAPI 规范和项目连接。

OpenAPI 规格如下所示:

  BearerAuth:
    type: http
    scheme: bearer
    bearerFormat: JWT

您需要:

  1. 更新您的 OpenAPI 规范 securitySchemes,以使用 Authorization 作为标头名称。

    "securitySchemes": {
        "bearerAuth": {
            "type": "apiKey",
            "name": "Authorization",
            "in": "header"
        }
    }
    
  2. 添加引用方案的 security 部分:

    "security": [
        {
            "bearerAuth": []
        }
    ]
    
  3. 在 Foundry 项目中创建自定义 密钥 连接:

    1. 转到 Foundry 门户 并打开您的项目。
    2. 创建或选择存储机密的连接。 请参阅 向项目添加新连接
    3. 输入以下值:
      • Authorization (必须与name中的securitySchemes字段匹配)
      • Bearer <token> (替换为 <token> 实际令牌)

    重要

    该值必须包括单词Bearer,并在该单词后跟一个空格,然后是标记。 例如: Bearer eyJhbGciOiJSUzI1NiIs.... 如果省略 Bearer ,API 将接收没有所需授权方案前缀的原始令牌,并且请求失败。

  4. 创建连接后,请将其与 project_connection 代码中的身份验证类型一起使用,就像进行 API 密钥身份验证一样。 连接 ID 使用相同的格式:/subscriptions/{{subscriptionID}}/resourceGroups/{{resourceGroupName}}/providers/Microsoft.CognitiveServices/accounts/{{foundryAccountName}}/projects/{{foundryProjectName}}/connections/{{foundryConnectionName}}

使用托管标识进行身份验证(Microsoft Entra ID)

Microsoft Entra ID是基于云的标识和访问管理服务,员工可以使用该服务访问外部资源。 通过使用 Microsoft Entra ID,可以向 API 添加额外的安全性,而无需使用 API 密钥。 设置托管身份验证时,代理会通过其使用的 Foundry 工具进行身份验证。

重要

只有当目标服务接受 Microsoft Entra ID 令牌时,托管身份验证才有效。 如果目标 API 使用不支持Microsoft Entra ID的自定义身份验证方案,请改用 API 密钥Bearer 令牌身份验证。

了解受众 URI

audience(有时称为资源标识符应用程序ID URI)用于告知 Microsoft Entra ID 该令牌是要访问哪个服务或 API。 受众值必须与目标服务预期的值匹配,否则身份验证失败并出现 401 错误。

注意

受众不是 Foundry 项目终结点。 它是 OpenAPI 工具调用的目标服务的资源标识符。

下表列出了常见Azure服务的受众 URI:

目标服务 受众 URI
Azure 存储 https://storage.azure.com
Azure 密钥保管库 https://vault.azure.net
Azure AI 搜索 https://search.azure.com
Azure 逻辑应用 https://logic.azure.com
Azure API 管理(管理平面) https://management.azure.com
受Microsoft Entra应用注册保护的 API(包括使用 OAuth 的 APIM) 应用注册中的 应用程序 ID URI (例如 api://<client-id>

提示

如果使用Azure API 管理通过 OAuth 2.0 验证策略保护自定义 API,则受众是保护 API 的应用注册中的 Application ID URI,而不是https://management.azure.com。 管理平面受众仅适用于 APIM 资源本身上的 Azure 资源管理器操作。

有关如何使用 Microsoft Entra ID 进行身份验证的详细信息,请参阅 Agent 标识和身份验证

查找并验证受众

使用以下步骤确定并验证正确的受众值:

  • For Azure services:请查找该服务文档中的 Microsoft Entra ID 资源标识符。 大多数Azure服务在其身份验证文档中列出访问群体 URI。
  • 对于由 Microsoft Entra 应用注册保护的 API:在 Azure 门户中,转到 Microsoft Entra ID>应用程序注册>,选择您的应用>公开 API。 页面顶部的应用程序 ID URI是您的受众值。
  • 若要验证令牌的受众:解码访问令牌 https://jwt.ms 并检查 aud 声明字段。 该值 aud 必须与目标服务期望的受众匹配。

设置托管身份认证

若要使用托管身份进行身份验证设置,请执行以下操作:

  1. 确保 Foundry 资源已启用系统分配的托管标识。

    一个屏幕截图,展示了 Azure 门户中的托管身份选择器。

  2. 为要通过 OpenAPI 规范连接到的服务创建资源。

  3. 分配对资源的适当访问权限。

    1. 为资源选择 访问控制

    2. 选择 “添加 ”,然后在屏幕顶部 添加角色分配

      一张屏幕截图,显示了 Azure 门户中的角色分配选择器。

    3. 选择所需的正确角色分配,通常至少需要 READER 角色。 然后选择“ 下一步”。

    4. 选择 托管标识,然后选择 选择成员

    5. 在托管标识下拉菜单中,搜索 Foundry 帐户 ,然后选择代理的 Foundry 帐户。

    6. 选择 “完成”。

  4. 完成设置后,可以通过 Foundry 门户、SDK 或 REST API 继续使用该工具。 使用本文顶部的选项卡查看代码示例。

排查常见错误

症状 可能的原因 分辨率
API 密钥不包括在请求中。 OpenAPI 规范缺少 securitySchemessecurity 部分。 请确保您的 OpenAPI 规范既包括 components.securitySchemes 又包括顶级 security 部分。 确保方案 name 与项目连接中的密钥名称匹配。
代理不调用 OpenAPI 工具。 工具选择未设置或operationId不具有描述性。 使用 tool_choice="required" 强制工具调用。 确保 operationId 值具有描述性,以便模型可以选择正确的操作。
托管标识的身份验证失败。 未启用托管标识或缺少角色分配。 在 Foundry 资源上启用系统分配的托管标识。 在目标服务上分配所需的角色(读取者或更高角色)。
即使分配了角色,托管标识也返回 401。 访问群体 URI 与目标服务期望的 URI 不匹配。 验证访问群体 URI 是否与目标服务的资源标识符匹配。 有关Azure服务,请查看服务文档。 对于受Microsoft Entra保护的 API,请使用应用注册中的应用程序 ID URI。 在 https://jwt.ms 处解码令牌,并确认 aud 声明匹配。 请参阅 “了解受众 URI”。
托管标识令牌被目标 API 拒绝。 目标服务不接受Microsoft Entra ID令牌。 确认目标服务支持Microsoft Entra ID身份验证。 否则,请改用 API 密钥或持有者令牌身份验证。
请求失败,出现 400 错误请求。 OpenAPI 规范与实际 API 不匹配。 根据实际 API 对照验证您的 OpenAPI 规范。 检查参数名称、类型和必填字段。
请求失败,出现 401 未授权。 API 密钥或令牌无效或已过期。 重新生成 API 密钥/令牌并更新项目连接。 验证连接 ID 是否正确。
工具返回意外的响应格式。 未在 OpenAPI 规范中定义的响应架构。 将响应架构添加到 OpenAPI 规范,以便更好地了解模型。
operationId 验证错误。 中的 operationId字符无效。 - 值中仅使用字母、_operationId。 删除数字和特殊字符。
未找到连接错误。 连接名称或 ID 不匹配。 验证 OPENAPI_PROJECT_CONNECTION_NAME 是否与 Foundry 项目中的连接名称匹配。
持有者令牌未正确发送。 连接值缺少 Bearer 前缀。 将连接值设置为 Bearer <token> (使用标记前的单词 Bearer 和空格)。 验证 OpenAPI 规范 securitySchemes 是否使用 "name": "Authorization"

选择身份验证方法

下表帮助你为 OpenAPI 工具选择正确的身份验证方法:

身份验证方法 最适合 配置复杂性
匿名 没有身份验证的公共 API
API 密钥 具有基于密钥的访问的非Microsoft API 中等
托管标识 Azure 服务和 Microsoft Entra ID 保护的 API。 要求目标服务接受Microsoft Entra ID令牌并支持 Azure RBAC 或基于Microsoft Entra的访问控制。 中高