連接代理與 OpenAPI 工具

利用 OpenAPI 3.0 和 3.1 規範,將您的 Microsoft Foundry 代理程式連接到外部 API。 驅動代理的 Foundry 模型能呼叫外部服務、即時資料擷取,並將功能擴展至內建功能之外。

OpenAPI 規範 定義了描述 HTTP API 的標準方式,讓你能將現有服務與代理整合。 Microsoft Foundry 支援三種認證方法:anonymous、API key 以及 managed identity。 如需協助選擇認證方法,請參閱 選擇認證方法。

提示

考慮用 工具箱來新增這個工具。 透過使用工具箱,你可以在代理與執行環境間重複使用該工具,並透過受管理的 MCP 端點集中管理憑證管理、版本管理與政策執行。 請參閱 工具箱快速入門。

先決條件

開始前,請確保你具備:

  • 一個擁有正確權限的 Azure 訂閱。

  • Foundry 專案中的使用者 角色,負責建立與執行代理程式。

    重要

    Foundry RBAC 角色最近已重新命名。 Foundry 用戶、Foundry 擁有者、Foundry Account Owner 以及 Foundry Project Manager 先前分別被稱為 Azure AI 使用者、Azure AI 擁有者、Azure AI 帳戶擁有者及 Azure AI Project 管理者。 在更名期間,你可能還會在某些地方看到之前的名字。角色 ID 與核心權限不會因命名而改變。

  • 如果您建立供 API 金鑰或權杖驗證使用的專案連線,則會在 Foundry 專案中具有 Foundry 專案管理者角色。

  • 已建立且已設定端點的 Foundry 專案。

  • 一個在你的專案中部署的 AI 模型。 確認模型與專案區域均支援 OpenAPI 工具,並依 區域與模型提供工具支援。

  • 基本 或標準代理環境。

  • 安裝了你偏好語言的 SDK:

    • Python:pip install azure-ai-projects jsonref
    • 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/json, application/json-patch+json
  • 對於受控識別驗證:在目標資源範圍內,指派給 Foundry 專案受控識別、且允許執行所需 API 作業的最低權限目標服務角色。
  • 使用 API 金鑰/權杖進行認證:使用你的 API 金鑰或權杖來配置專案連接。 請參見 為您的專案新增連結。

註

FOUNDRY_PROJECT_ENDPOINT 值指的是你的 Microsoft Foundry 專案端點,而非外部 OpenAPI 服務端點。 您可以在 Microsoft Foundry 入口網站的專案概覽頁面中找到此端點。 這個端點是驗證代理服務所必需的,並且與你規格檔案中定義的任何 OpenAPI 端點是分開的。

使用支援

下表顯示 SDK 與設定支援。

Microsoft Foundry 支援 Python SDK C# SDK JavaScript SDK Java 開發套件 REST API 基本代理設定 標準代理設定
✔️ ✔️ ✔️ ✔️ ✔️ ✔️ ✔️ ✔️

註

對於 Java,請使用 OpenAPI 代理工具的 com.azure:azure-ai-agents 套件。 該 com.azure:azure-ai-projects 套件目前並未公開 OpenAPI 代理工具類型。

執行匿名首次成功流程

先從匿名天氣 API 開始,驗證你的代理程式是否能載入 OpenAPI 規範並呼叫操作。 這條路徑不需要外部 API 憑證或 Foundry 專案連線。

  1. 從 Prerequisites 安裝你選擇語言的 SDK 套件。
  2. 下載 weather_openapi.json,並儲存到 assets 取樣路徑。
  3. 設定你的 Foundry 專案端點並建模部署值。
  4. 請在你選擇的語言區塊中執行匿名樣本。
  5. 確認回應中包含西雅圖的最新天氣,然後刪除樣本所建立的代理版本。

匿名呼叫成功後,設定目標 API 所需的認證。 將 API 金鑰認證、 持有權杖認證與 管理身份認證 視為不同的變體。

了解限制

  • 你的 OpenAPI 規範必須在每個操作中包含operationId,而operationId只能包含字母、-和_。
  • 支援的請求內容類型: application/json, application/json-patch+json。
  • API 金鑰認證時,每個 OpenAPI 工具使用一種 API 金鑰安全方案。 如果你需要多種安全方案,就建立多個 OpenAPI 工具。
  • 在懷疑暴露後,定期且立即輪換 API 金鑰與持有憑證。 當憑證變更時更新專案連線;不要把憑證放在 OpenAPI 規範或原始碼裡。

將 OpenAPI 工具加入工具箱

使用此模式公開所有由 OpenAPI 規範描述的 REST API。選擇符合 API 安全模型的 auth.type。

重要

使用受控識別驗證時,僅指派允許所需 API 作業的最低權限 RBAC 角色給目標服務上 Foundry 專案的受控識別。 例如,只有當 API 需要唯讀 Azure Resource Manager 存取時,才在目標 Azure 資源上指派 Reader。 若沒有所需的指派,代理在呼叫 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 Developer CLI 建立 OpenAPI 工具箱

OpenAPI 工具會直接將規範嵌入於 tools:。 基於連線的認證(connection_auth)會參考專案連線;匿名的 OpenAPI 工具則不需要連線。

步驟 1. (可選)建立認證連線

對於匿名 OpenAPI 工具,請跳過此步驟。

# API-key auth (passed by the platform on every call)
# Set OPENAPI_AUTHORIZATION_HEADER in your shell without committing its value.
azd ai connection create my-api-conn \
  --kind remote-tool \
  --target https://api.example.com \
  --auth-type custom-keys \
  --custom-key "Authorization=$OPENAPI_AUTHORIZATION_HEADER"

OpenAPI 工具也接受 --auth-type oauth2 連線。 完整旗標集合 azd ai connection create 請參見 Toolbox 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. securitySchemes 區塊中包含您的 API 金鑰設定,例如標頭名稱和參數名稱。
  2. 一個 security 提及安全方案的章節。
  3. 一個以匹配金鑰名稱和值配置的專案連線。

沒有這些設定,API 金鑰就不會包含在請求中。 如需詳細設定說明,請參閱 「使用 API 金鑰認證 」章節。

你也可以使用基於憑證的認證(例如持有憑證),將憑證儲存在專案連線中。 對於持有人令牌授權,建立一個 自訂金鑰 連線,將金鑰設為 , Authorization 值設為 Bearer <token> (替換 <token> 成你的真實令牌)。 Bearer 及後面的空格必須被包含在值中。 詳情請參見 設置持有人令牌連線。

使用 OpenAPI 工具使用代理程式的範例

此範例示範如何透過代理使用 OpenAPI規範 所描述的服務。 它使用 wttr.in 服務來取得天氣及其規格檔 weather_openapi.json。 選擇 Prompt Agents 以使用 Azure AI Projects SDK 建立伺服器端提示代理,或選擇 Hosted Agents 使用 Microsoft 代理框架建立一個短暫且進行中的代理。

提示詞 Agent

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"

# 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(),
    )
)

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 weather API。 該工具直接連接到代理定義。 當你執行程式碼時:

  1. 它會從本地的 JSON 檔案載入 weather OpenAPI 規範。
  2. 建立一個提示代理,並設定天氣工具以支援匿名存取。
  3. 傳送詢問西雅圖天氣的查詢。
  4. 代理程式使用 OpenAPI 工具呼叫天氣 API,並回傳格式化的結果。
  5. 透過刪除代理程式版本來清理。

託管代理

此範例使用 FoundryChatClient Microsoft 代理框架,並透過 FoundryToolbox連接工具箱 MCP 端點。 安裝與 pip install "agent-framework-foundry==1.10.4" "azure-ai-projects>=2.3.0,<2.4.0" azure-identity jsonref 相容的套件版本,設定 FOUNDRY_PROJECT_ENDPOINT 環境變數,並使用 az login 登入。 OpenApiToolboxTool 是工具箱專用模型;僅在直接將工具連接到提示代理時使用 OpenApiTool 。

import asyncio
import os
import jsonref
from typing import Any, cast

from agent_framework import Agent
from agent_framework.foundry import FoundryChatClient, FoundryToolbox
from azure.identity import AzureCliCredential
from azure.ai.projects import AIProjectClient
from azure.ai.projects.models import (
    OpenApiToolboxTool,
    OpenApiFunctionDefinition,
    OpenApiAnonymousAuthDetails,
)

PROJECT_ENDPOINT = "https://<account>.services.ai.azure.com/api/projects/<project>"


async def main() -> None:
    credential = AzureCliCredential()

    # 1. Create the OpenAPI tool and add it to a toolbox. Using a toolbox is the
    #    recommended way to give agents tools: curate tools once and reuse the
    #    toolbox across agents. See /azure/foundry/agents/concepts/toolbox-overview
    project = AIProjectClient(endpoint=PROJECT_ENDPOINT, credential=credential)

    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()))

    weather_tool = OpenApiToolboxTool(
        openapi=OpenApiFunctionDefinition(
            name="get_weather",
            spec=openapi_weather,
            description="Retrieve weather information for a location.",
            auth=OpenApiAnonymousAuthDetails(),
        )
    )

    toolbox = project.toolboxes.create_version(
        name="openapi-toolbox",
        description="Toolbox with the OpenAPI weather tool",
        tools=[weather_tool],
    )

    # 2. The toolbox exposes an MCP-compatible endpoint.
    TOOLBOX_MCP_URL = (
        f"{PROJECT_ENDPOINT}/toolboxes/{toolbox.name}"
        f"/versions/{toolbox.version}/mcp?api-version=v1"
    )

    # 3. Attach the toolbox to the hosted agent as an MCP tool.
, timeout=120.0)
    toolbox_tool = FoundryToolbox(credential, url=TOOLBOX_MCP_URL)

agent = Agent(
        client=FoundryChatClient(credential=credential),
        instructions="You are a helpful assistant. Use the OpenAPI weather tool to answer questions.",
        tools=[toolbox_tool],
    )

    result = await agent.run("What's the weather in Seattle?")
    print(f"Agent: {result.text}")


if __name__ == "__main__":
    asyncio.run(main())

預期產出

Agent: The weather in Seattle is currently cloudy with a temperature of 52°F (11°C)...

使用 OpenAPI 工具使用代理程式的範例

此範例示範如何透過代理使用 OpenAPI規範 所描述的服務。 它使用 wttr.in 服務來取得天氣及其規格檔 weather_openapi.json。 選擇 Prompt Agents 以使用 Azure AI Projects SDK 建立伺服器端提示代理,或選擇 Hosted Agents 使用 Microsoft 代理框架建立一個短暫且進行中的代理。

提示詞 Agent

此範例使用了 Azure AI Projects 客戶端函式庫的同步方法。 關於使用非同步方法的範例,請參見 Azure SDK for .NET 儲存庫中的sample,GitHub上。

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: OpenAPI 規格檔在 Assets 資料夾中找不到
  • UnauthorizedAccessException:憑證無效或 RBAC 權限不足
  • API 金鑰未插入:請確認您的 OpenAPI 規格中同時包含securitySchemes (位於 components 中) 與 security 區段,且兩者使用相符的方案名稱。

託管代理

此範例包含 Azure AI 專案 SDK 建立 OpenAPI 工具箱,並使用 Microsoft Agent Framework AddFoundryToolboxes 整合,讓該工具可供託管代理使用。 安裝 Agent Framework 套件、設定 AZURE_AI_PROJECT_ENDPOINT 專案端點和 AZURE_AI_MODEL_DEPLOYMENT_NAME 環境變數,並以 az login 登入。

using System.IO;
using System.Runtime.CompilerServices;
using Azure.AI.AgentServer.Responses;
using Azure.AI.AgentServer.Responses.Models;
using Azure.AI.OpenAI;
using Azure.AI.Projects;
using Azure.AI.Extensions.OpenAI;
using Azure.Identity;
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.Foundry.Hosting;
using Microsoft.Extensions.DependencyInjection;
using OpenAI.Chat;

string GetFile([CallerFilePath] string pth = "")
{
    var dirName = Path.GetDirectoryName(pth) ?? "";
    return Path.Combine(dirName, "Assets", "weather_openapi.json");
}

string projectEndpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT")
    ?? "https://<account>.services.ai.azure.com/api/projects/<project>";
string deploymentName = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLOYMENT_NAME") ?? "gpt-5-mini";

var openAiEndpoint = new Uri(projectEndpoint).GetLeftPart(UriPartial.Authority);
DefaultAzureCredential credential = new();

// 1. Create the OpenAPI tool and add it to a toolbox. Using a toolbox is the
//    recommended way to give agents tools. See /azure/foundry/agents/concepts/toolbox-overview
AIProjectClient projectClient = new(endpoint: new Uri(projectEndpoint), tokenProvider: credential);
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.";
ProjectsAgentTool openapiTool = new OpenAPITool(toolDefinition);
ToolboxVersion toolboxVersion = projectClient.AgentAdministrationClient
    .GetAgentToolboxes().CreateToolboxVersion(
        toolboxName: "openapi-toolbox",
        tools: [openapiTool],
        description: "Toolbox with the OpenAPI weather tool");

// Create the hosted agent and register the toolbox integration.
AIAgent agent = projectClient.AsAIAgent(
    model: deploymentName,
    instructions: "You are a helpful assistant with access to the toolbox tools.",
    name: "hosted-toolbox-agent");

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddFoundryResponses(agent);
builder.Services.AddFoundryToolboxes(credential, toolboxVersion.Name);

var app = builder.Build();
app.MapFoundryResponses();
app.Run();

預期產出

代理程式透過 OpenAPI 工具呼叫天氣 API,並回傳該地點的當前條件:

The current weather in Seattle is <temperature> with <conditions>.

完整範例包括認證 API 模式,請參見 Agent_Step17_OpenAPITools。


在網路服務上使用 OpenAPI 工具的代理程式範例,需驗證

在這個例子中,你將一個已認證的 OpenAPI 工具加入工具箱,將工具箱附加為 MCP 工具,並在需要驗證的情況下使用該代理。 你用的是 TripAdvisor 的規範。

TripAdvisor 服務需要基於金鑰的認證。 要建立連線,打開 Microsoft Foundry,在右上角的導覽中選擇「管理」,選擇「Project details」,然後選擇「已連線資源」標籤。最後,建立自訂鍵型別的新連線。 將其命名為 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# 範例展示了使用 OpenAPI 工具,透過工具箱和專案連線進行 API 金鑰認證。 當你執行程式碼時:

  1. 它會從本地檔案載入 TripAdvisor OpenAPI 規範。
  2. 取得包含你 API 金鑰的 tripadvisor 專案連線。
  3. 建立一個工具箱版本,其中包含已設定為使用該連線進行驗證的 TripAdvisor 工具。
  4. 將工具箱作為 MCP 工具附加到代理上。
  5. 傳送建議巴黎飯店的要求。
  6. 代理會用你儲存的 API 金鑰呼叫 TripAdvisor API,並回傳結果。
  7. 透過刪除代理程式來進行清除。

所需輸入

  • 內嵌字串值:projectEndpoint(你的 Foundry 專案終端節點)
  • 本地檔案: Assets/tripadvisor_openapi.json
  • 專案連線:tripadvisor,已配置有效的 API 金鑰

預期產出

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 規格中已設定適當的 securitySchemes 和 security。

建立一個具備 OpenAPI 工具功能的 Java 代理

這個 Java 設定可以參考 MCP 工具,但 Java SDK 目前還沒有公開工具箱建立 API。

提示

建議: 對大多數代理程式而言,請透過 工具箱 新增 OpenAPI 工具,並將該工具箱作為 MCP 工具附加到您的代理程式。 使用Python、REST API、C#或TypeScript範例,或Foundry入口網站建立工具箱,然後從你的Java代理中引用其MCP端點作為 McpTool.

以下範例展示了如何利用 REST API 呼叫 OpenAPI 工具。

取得存取權憑證:

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 "Authorization: Bearer $AGENT_TOKEN" \
  -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 金鑰認證(專案連線)

僅在匿名流程成功後才使用此變體。 如 使用 API 金鑰驗證 所述,設定專案連線和 OpenAPI securitySchemes 項目。

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": [] }
            ]
          }
        }
      }
    ]
  }'

對於持有憑證 API,請保持相同的 project_connection 請求形狀,但使用如 「設定承載憑證連線」中所述的連線配置。 連線值必須以 Bearer 開頭,後面接一個空格。

管理式身份驗證

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_TOKEN, FOUNDRY_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,或因為securitySchemes和security在你的 OpenAPI 規範中缺少而未注入API金鑰
  • 404 Not Found: 端點或模型部署名稱錯誤
  • 400 Bad Request:OpenAPI 規範錯誤或認證設定無效
  • API 金鑰未隨請求傳送:確認components.securitySchemes你 OpenAPI 規範中的該區塊是否正確設定(非空),且符合你的專案連線金鑰名稱

建立具備 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_reference: { 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 檔案載入 weather 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_reference: { 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 工具,透過專案連線進行 API 金鑰認證。 當你執行程式碼時:

  1. 它會從本地檔案載入 TripAdvisor OpenAPI 規範。
  2. 它透過使用 TRIPADVISOR_CONNECTION_ID 常數來配置認證。
  3. 它會用 TripAdvisor 工具建立一個代理程式,利用專案連線來進行 API 金鑰驗證。
  4. 它會發送一個串流請求,以取得 TripAdvisor 的地點詳細資訊。
  5. 其透過使用 tool_choice: "required" 強制使用工具,以確保呼叫 API。
  6. 它會處理並顯示串流的回應。
  7. 它會透過刪除代理程式來完成清理。

所需輸入

  • 內嵌字串值: PROJECT_ENDPOINT, TRIPADVISOR_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/json 和 application/json-patch+json。 回應內容類型沒有限制。

安全性與資料考量

當你將代理連接到 OpenAPI 工具時,代理程式可以將使用者輸入衍生的請求參數傳送到目標 API。

  • 使用專案連線來管理秘密(API 金鑰和令牌)。 避免在 OpenAPI 規格檔或原始碼中放入秘密。
  • 在正式使用該工具前,先檢視 API 接收到的資料及其回傳。
  • 使用最低權限存取。 對於管理身份,只指派目標服務所需的角色。

使用 API 金鑰認證

對於要求在標頭或查詢參數中提供金鑰的 API,請使用此變體。 每個 OpenAPI 工具只能使用一種 API 金鑰安全方案。 如果 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 預期在Authorization標頭中使用持有人權杖,請使用此變體。 它使用與 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 會收到未附帶所需授權方案前綴的原始權杖字串,且請求會失敗。

  1. 建立連線後,在程式碼中用 auth 類型使用 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(有時稱為 resource identifier 或 Application ID URI)告訴Microsoft Entra ID該令牌預期存取哪項服務或 API。 受眾值必須符合目標服務的期望,否則認證將因 401 錯誤而失敗。

註

不是 你的 Foundry 專案的目標受眾。 它是你的 OpenAPI 工具呼叫的目標服務的資源識別碼。

下表列出常見 Azure 服務的受眾 URI:

目標服務 受眾 URI
Azure 儲存體 https://storage.azure.com
Azure Key Vault https://vault.azure.net
Azure AI 搜尋服務 https://search.azure.com
Azure Logic Apps https://logic.azure.com
Azure API 管理 (管理平台) https://management.azure.com
API 由 Microsoft Entra 應用程式註冊保護(包含帶有 OAuth 的 APIM) 應用程式註冊時的 應用程式 ID URI (例如, api://<client-id>)

提示

如果你用 Azure API 管理 保護一個自訂 API 並採用 OAuth 2.0 驗證政策,受眾是應用程式註冊後保護該 API 的 Application ID URI,而非 https://management.azure.com。 管理平面受眾只適用於 APIM 資源本身的 Azure Resource Manager 作業。

欲了解更多關於代理如何以Microsoft Entra ID驗證的資訊,請參見 Agent 身份與認證。

找到並驗證你的受眾

請依照以下步驟判斷並驗證正確的受眾價值:

  • 對於Azure服務:請查看服務文件中的Microsoft Entra ID資源識別碼。 大多數 Azure 服務會在認證文件中列出受眾 URI。
  • 針對受 Microsoft Entra 應用程式註冊保護的 API:在 Azure 入口網站中,前往 Microsoft Entra ID>應用程式註冊>,選取您的應用程式,然後進入>公開 API。 頁面頂端的 應用程式 ID URI 就是你的受眾值。
  • 若要驗證權杖的受眾:在 https://jwt.ms 解碼存取權杖,並檢查 aud 宣告。 價值 aud 必須與目標服務所期望的受眾相符。

設定管理身份驗證

要透過管理身分識別來配置身份驗證:

  1. 確保你的 Foundry 資源啟用了系統指派的管理身份。

Azure 入口網站的截圖,顯示系統指派的管理身份設定。

  1. 透過 OpenAPI 規範為你想連接的服務建立資源。

  2. 為該資源分配適當的存取權限。

    1. 選擇存取控制作為你的資源。

    2. 選擇 新增 ,然後在螢幕頂 端新增角色分配 。

      Azure 入口網站顯示新增角色指派動作的截圖。

  3. 選擇可授予 OpenAPI 規格中所定義作業所需權限的最低權限資料平面角色或應用程式角色。 Azure Resource Manager 的 Reader 存取權本身並不會授與資料平面存取權限。 然後選擇 「下一步」。

  4. 選擇 管理身份 ,然後選擇 選擇成員。

  5. 在管理身份下拉選單中,搜尋 Foundry 帳戶 ,然後選擇你代理人的 Foundry 帳戶。

  6. 選擇 完成。

  7. 完成設定後,你可以透過 Foundry 入口網站、SDK 或 REST API 繼續使用該工具。 請使用本文頂端的分頁查看程式碼範例。

排除常見錯誤

症狀 可能的原因 解決方法
API 金鑰不會包含在請求中。 OpenAPI 規範缺失 securitySchemes 或 security 部分內容。 請確認你的 OpenAPI 規範中同時包含 components.securitySchemes 和頂層 security 章節。 確保方案 name 與你專案關聯的關鍵名稱相符。
代理程式不會呼叫 OpenAPI 工具。 工具選擇未設定或 operationId 描述不完整。 用 tool_choice="required" 來強制召喚工具。 確保 operationId 數值具描述性,讓模型能選擇正確的操作。
受管理的身分驗證失敗。 受管理的身份未啟用或缺少角色分配。 在您的 Foundry 資源上啟用系統指派的管理身份。 在您的 OpenAPI 規範中,為其中的作業指派目標服務的最低權限資料平面或應用程式角色。
即使已指派角色,受控識別仍傳回 401。 受眾的 URI 與目標服務的預期不符。 驗證受眾 URI 是否與目標服務的資源識別碼相符。 關於 Azure 服務,請查看服務文件。 對於 Microsoft Entra 保護的 API,請使用應用程式註冊時的應用程式 ID URI。 在https://jwt.ms解碼權杖,並確認 aud 宣告相符。 請參閱了解受眾的 URI。
目標 API 拒絕了管理身份憑證。 Target 服務不接受 Microsoft Entra ID 令牌。 確認目標服務是否支援 Microsoft Entra ID 認證。 如果不行,就改用 API 金鑰或承載憑證驗證。
請求失敗,且有 400 個錯誤請求。 OpenAPI 規格和實際 API 不符。 將你的 OpenAPI 規範與實際 API 進行驗證比對。 檢查參數名稱、類型及所需欄位。
申請失敗,顯示 401 未授權。 API 金鑰或權杖無效或過期。 重新產生 API 金鑰/權杖並更新你的專案連線。 確認連線ID是否正確。
工具回傳意外的回應格式。 回應架構未在 OpenAPI 規範中定義。 在你的 OpenAPI 規範中加入回應架構,以更好理解模型。
operationId 驗證錯誤。 operationId中有無效字元。 僅使用字母、- 和 _ 在 operationId 值中。 去除數字和特殊字元。
找不到連線錯誤。 連線名稱或ID不符。 確認 OPENAPI_PROJECT_CONNECTION_NAME 是否與你在 Foundry 專案中的連線名稱相符。
未正確傳送 Bearer 權杖。 連線值缺少 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 的存取控制。 Medium-High