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

快速入门:使用响应 API 生成代理

在本快速入门中,你将从自己的代码调用 Foundry 项目终结点上的 响应 API ,以生成 临时代理 (其定义(说明、工具、模型)位于应用程序代码中,而不是作为 Foundry 代理服务中的持久资源。 每次调用都会在您的进程中构建该代理,并调用 Responses API 进行模型推理和工具编排。

这种模式适合开发人员、ISV 和数字原生企业;他们希望代理定义能与应用程序代码的其他部分一起发布并进行版本管理,而不是作为一种独立于应用之外、还需要由他人手动保持同步的带外资源。 与 提示代理不同,Foundry 中没有用于创建、更新或删除的代理资源 — 生命周期管理是通过直接调用响应 API 来替换的。

响应 API 是 Foundry 的单一模型和工具入口点。 可以在两个不同的终结点上调用它:

  • Foundry 项目端点(本快速入门中推荐使用)— 提供完整的 Foundry 支持。 通过单个项目级 API 接口(可通过 {project_endpoint}/openai/v1/responses 访问)提供目录中的 Foundry 模型和平台工具(文件搜索、代码解释器、记忆、网页搜索、MCP、SharePoint、WorkIQ、Fabric IQ 等)。
  • Azure OpenAI 终结点 — 与现有 OpenAI 客户端的最佳延迟和最大兼容性。 如果只需要 OpenAI 模型和标准 OpenAI 工具,并且不需要特定于 Foundry 的功能,请使用此功能。

建议的路径是 代理框架,它为你处理身份验证、工具连接和消息业务流程。 在 Python 中,这是 FoundryChatClient;在 .NET 中,这是 AIProjectClient.AsAIAgent(...)。 OpenAI SDK 也可用于此端点,并在 直接使用 OpenAI SDK 中作为一种替代方案进行了介绍。

如果没有 Azure 订阅,可以创建一个免费帐户

何时使用临时代理模式

在 Foundry 外部托管代理代码(可能嵌入在自己的应用程序中)但想要访问 Foundry 代理功能(如模型和平台工具)时,请使用此模式。

临时模式和 托管代理累加的,而不是替代方法。 同一代理框架代理代码也可以打包为托管代理并通过 Foundry 代理 API 公开,这在需要其他应用、服务或代理可以调用的 Foundry 托管终结点时很有用。 你可以通过一个代码库同时做到这两点:在进程内运行代理,使其随应用一同交付;并在其他调用方需要时,将同一定义发布为托管代理。

Foundry 项目终结点在 OpenAI Responses API 之上新增了什么

Foundry 项目终结点上的响应 API 与 OpenAI 响应 API 兼容,因此,现有的 OpenAI 客户端可对其进行最少的更改。 Foundry 项目终结点还会额外添加以下内容:

  • 项目范围内的数据:文件、向量存储和其他数据都存储在 project 级别,而不是资源级别,这样可以实现按项目进行的数据隔离,并允许通过标准代理配置使用自带资源。
  • 除了 OpenAI 之外的 Foundry 模型:由 Azure 直接销售的 Foundry 模型(不只是 OpenAI 模型)也可通过同一 API 使用。
  • Foundry 专属工具:SharePoint、WorkIQ 和 Fabric IQ 等平台工具可与标准 OpenAI 工具一同使用。
  • 代理 (OBO) 身份验证:工具可以调用下游服务作为登录用户,而不仅仅是应用程序标识。
  • 项目级可观测性和治理:通过项目终结点发起的调用会经过项目的跟踪、监视、内容筛选和身份配置,无需额外配置(请参阅 可观测性和企业功能)。

调用 项目端点——而非资源级 OpenAI 端点——才能启用这些项目范围内的功能。

先决条件

  • 已安装 Python 3.10 或更高版本。

设置环境变量。

项目终结点 和部署的模型名称存储为环境变量。 以下示例从环境中读取这些值。

FOUNDRY_PROJECT_ENDPOINT=<endpoint copied from welcome screen>
FOUNDRY_MODEL=<your deployed model name>

安装软件包

使用 Foundry 提供程序安装 Agent Framework 包:

pip install agent-framework-foundry aiohttp
dotnet add package Microsoft.Agents.AI.Foundry --prerelease
dotnet add package Azure.AI.Projects --prerelease
dotnet add package Azure.Identity

Microsoft.Agents.AI.FoundryAsAIAgent(...) 上提供 AIProjectClient 扩展方法,并传递引入 Microsoft.Agents.AI

创建代理

创建一个在您的进程内本地运行的临时代理,并调用 Responses API 进行模型推理和工具编排。

使用 FoundryChatClientAgent 类。

import asyncio
import os

from agent_framework import Agent
from agent_framework.foundry import FoundryChatClient
from azure.identity import AzureCliCredential

async def main() -> None:
    agent = Agent(
        client=FoundryChatClient(
            project_endpoint=os.environ["FOUNDRY_PROJECT_ENDPOINT"],
            model=os.environ["FOUNDRY_MODEL"],
            credential=AzureCliCredential(),
        ),
        instructions="You are a helpful assistant.",
    )

    result = await agent.run("What is the capital of France?")
    print(f"Agent: {result}")

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

输出会打印代理的响应。 由于代理是临时的,因此不会将定义保存到服务中, 它仅在Python进程的生存期内存在。

使用 Microsoft Agent Framework 中的 AIProjectClient.AsAIAgent(...)将 Foundry 项目终结点包装为 AIAgent

using Azure.AI.Projects;
using Azure.Identity;
using Microsoft.Agents.AI;

string endpoint = Environment.GetEnvironmentVariable("FOUNDRY_PROJECT_ENDPOINT")
    ?? throw new InvalidOperationException("FOUNDRY_PROJECT_ENDPOINT is not set.");
string deploymentName = Environment.GetEnvironmentVariable("FOUNDRY_MODEL")
    ?? throw new InvalidOperationException("FOUNDRY_MODEL is not set.");

AIAgent agent =
    new AIProjectClient(new Uri(endpoint), new DefaultAzureCredential())
    .AsAIAgent(
        model: deploymentName,
        instructions: "You are a helpful assistant.",
        name: "Assistant");

Console.WriteLine($"Agent: {await agent.RunAsync("What is the capital of France?")}");

输出会打印代理的响应。 由于代理是临时的,因此不会将定义保存到服务中,因此它仅在进程的生存期内存在。

添加函数工具

定义本地函数工具并将其传递给代理。 在聊天期间,代理会在需要时自动调用这些工具。

使用 @tool 修饰器定义本地函数工具。

import asyncio
import os
from random import randint
from typing import Annotated

from agent_framework import Agent, tool
from agent_framework.foundry import FoundryChatClient
from azure.identity import AzureCliCredential
from pydantic import Field

@tool(approval_mode="never_require")
def get_weather(
    location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
    """Get the weather for a given location."""
    conditions = ["sunny", "cloudy", "rainy", "stormy"]
    return f"The weather in {location} is {conditions[randint(0, 3)]} with a high of {randint(10, 30)}°C."

async def main() -> None:
    agent = Agent(
        client=FoundryChatClient(
            project_endpoint=os.environ["FOUNDRY_PROJECT_ENDPOINT"],
            model=os.environ["FOUNDRY_MODEL"],
            credential=AzureCliCredential(),
        ),
        instructions="You are a helpful weather agent.",
        tools=get_weather,
    )

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

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

代理使用响应 API 来确定何时调用 get_weather 函数、在本地执行函数,并使用自然语言返回结果。

定义一个本地方法,用 [Description] 属性对其进行修饰,并用 AIFunctionFactory.Create(...) 将其包装起来。

using System.ComponentModel;
using Azure.AI.Projects;
using Azure.Identity;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;

[Description("Get the weather for a given location.")]
static string GetWeather(
    [Description("The location to get the weather for.")] string location)
{
    string[] conditions = ["sunny", "cloudy", "rainy", "stormy"];
    Random rng = Random.Shared;
    return $"The weather in {location} is {conditions[rng.Next(conditions.Length)]} with a high of {rng.Next(10, 31)}°C.";
}

AITool weatherTool = AIFunctionFactory.Create(GetWeather);

string endpoint = Environment.GetEnvironmentVariable("FOUNDRY_PROJECT_ENDPOINT")
    ?? throw new InvalidOperationException("FOUNDRY_PROJECT_ENDPOINT is not set.");
string deploymentName = Environment.GetEnvironmentVariable("FOUNDRY_MODEL")
    ?? throw new InvalidOperationException("FOUNDRY_MODEL is not set.");

AIAgent agent =
    new AIProjectClient(new Uri(endpoint), new DefaultAzureCredential())
    .AsAIAgent(
        model: deploymentName,
        instructions: "You are a helpful weather agent.",
        name: "WeatherAssistant",
        tools: [weatherTool]);

Console.WriteLine($"Agent: {await agent.RunAsync("What's the weather like in Seattle?")}");

代理使用响应 API 来确定何时调用 GetWeather、在本地执行响应 API,并使用自然语言返回结果。

使用 Web 搜索工具

Foundry 项目终结点上的响应 API 提供内置的托管工具,如 Web 搜索。 无需任何本地实现即可授予代理对 Web 搜索的访问权限。

使用 FoundryChatClient.get_web_search_tool()

import asyncio
import os

from agent_framework import Agent
from agent_framework.foundry import FoundryChatClient
from azure.identity import AzureCliCredential

async def main() -> None:
    agent = Agent(
        client=FoundryChatClient(
            project_endpoint=os.environ["FOUNDRY_PROJECT_ENDPOINT"],
            model=os.environ["FOUNDRY_MODEL"],
            credential=AzureCliCredential(),
        ),
        instructions="You are a research assistant. Use web search to find current information.",
        tools=[
            FoundryChatClient.get_web_search_tool(),
        ],
    )

    result = await agent.run("What are the latest updates to Microsoft Foundry?")
    print(f"Agent: {result}")

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

网络搜索工具通过 Foundry 项目的 Responses API 在服务器端执行。 可以将它与本地函数工具相结合,为代理提供 Web 访问和自定义代码功能:

agent = Agent(
    client=FoundryChatClient(
        project_endpoint=os.environ["FOUNDRY_PROJECT_ENDPOINT"],
        model=os.environ["FOUNDRY_MODEL"],
        credential=AzureCliCredential(),
    ),
    instructions="You are a helpful assistant with web and weather capabilities.",
    tools=[
        FoundryChatClient.get_web_search_tool(),
        get_weather,  # Local function tool defined with @tool
    ],
)

new HostedWebSearchTool()列表中传入tools

using Azure.AI.Projects;
using Azure.Identity;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;

string endpoint = Environment.GetEnvironmentVariable("FOUNDRY_PROJECT_ENDPOINT")
    ?? throw new InvalidOperationException("FOUNDRY_PROJECT_ENDPOINT is not set.");
string deploymentName = Environment.GetEnvironmentVariable("FOUNDRY_MODEL")
    ?? throw new InvalidOperationException("FOUNDRY_MODEL is not set.");

AIAgent agent =
    new AIProjectClient(new Uri(endpoint), new DefaultAzureCredential())
    .AsAIAgent(
        model: deploymentName,
        instructions: "You are a research assistant. Use web search to find current information.",
        name: "ResearchAssistant",
        tools: [new HostedWebSearchTool()]);

Console.WriteLine($"Agent: {await agent.RunAsync("What are the latest updates to Microsoft Foundry?")}");

网络搜索工具通过 Foundry 项目的 Responses API 在服务器端执行。 可以将它与本地函数工具相结合,为代理提供 Web 访问和自定义代码功能:

AIAgent agent =
    new AIProjectClient(new Uri(endpoint), new DefaultAzureCredential())
    .AsAIAgent(
        model: deploymentName,
        instructions: "You are a helpful assistant with web and weather capabilities.",
        name: "Assistant",
        tools: [new HostedWebSearchTool(), weatherTool]);

流响应

在响应生成过程中接收响应,而不是等待整个消息生成完毕。

使用 stream=True 参数:

import asyncio
import os

from agent_framework import Agent
from agent_framework.foundry import FoundryChatClient
from azure.identity import AzureCliCredential

async def main() -> None:
    agent = Agent(
        client=FoundryChatClient(
            project_endpoint=os.environ["FOUNDRY_PROJECT_ENDPOINT"],
            model=os.environ["FOUNDRY_MODEL"],
            credential=AzureCliCredential(),
        ),
        instructions="You are a helpful assistant.",
    )

    print("Agent: ", end="", flush=True)
    async for chunk in agent.run("Tell me a fun fact.", stream=True):
        if chunk.text:
            print(chunk.text, end="", flush=True)
    print()

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

调用 RunStreamingAsync 并迭代 AgentResponseUpdate 流:

using Azure.AI.Projects;
using Azure.Identity;
using Microsoft.Agents.AI;

string endpoint = Environment.GetEnvironmentVariable("FOUNDRY_PROJECT_ENDPOINT")
    ?? throw new InvalidOperationException("FOUNDRY_PROJECT_ENDPOINT is not set.");
string deploymentName = Environment.GetEnvironmentVariable("FOUNDRY_MODEL")
    ?? throw new InvalidOperationException("FOUNDRY_MODEL is not set.");

AIAgent agent =
    new AIProjectClient(new Uri(endpoint), new DefaultAzureCredential())
    .AsAIAgent(
        model: deploymentName,
        instructions: "You are a helpful assistant.",
        name: "Assistant");

Console.Write("Agent: ");
await foreach (AgentResponseUpdate update in agent.RunStreamingAsync("Tell me a fun fact."))
{
    Console.Write(update);
}
Console.WriteLine();

随着模型生成每个令牌,流式输出会在控制台中逐步显示。

可观测性和企业功能

临时并不意味着非托管。 由于调用通过项目终结点,因此它们会继承项目的企业配置,而无需额外的连接:

  • 跟踪和监控:项目中的请求、工具调用和令牌使用情况会流入 Foundry 可观测性功能。
  • 内容筛选器和治理:项目级内容筛选器和负责任的 AI 策略适用于每个请求。
  • 身份和访问:调用会根据项目的身份配置进行身份验证;启用 OBO 的工具可以以已登录用户的身份运行。

临时模式不是一个缩减功能层 — 无论是在进程内运行代理还是 打包与托管代理相同的代码,都可获得相同的 Foundry 模型、工具、可观测性和治理。 选择与部署形状有关,而不是功能集。

直接使用 OpenAI SDK

由于 Foundry 项目响应 API 与 OpenAI 兼容,因此也可以通过将客户端指向项目终结点({project_endpoint}/openai/v1/responses)直接从 OpenAI SDK 调用它。 仅当已有 OpenAI SDK 代码或需要对请求和响应形状进行较低级别的控制时,才使用此路径。 新代码应首选代理框架,它为你处理身份验证、工具连接和业务流程。

有关 SDK 示例,请参阅:

清理资源

由于此处创建的代理框架代理是临时代理,因此不需要服务端清理。 代理仅在本地进程中存在。 如果创建了不再需要的 Foundry 资源,请在 Foundry 门户中将其删除。

更深入地探讨此模式

打包与托管代理相同的代理代码