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

将 Microsoft Agent Framework 智能体托管为 Foundry 托管智能体

使用 Microsoft Agent Framework 托管包,使 Agent Framework 代理能够通过适用于 Foundry 托管代理的协议进行公开。 托管套餐让你能够将代理逻辑保留在代码中,而由 Foundry 负责管理托管运行时、会话、扩缩容、身份管理和协议端点。

在本文中,你将创建一个最小的 Agent Framework 代理,通过响应或调用协议公开它,通过 HTTP 对其进行测试,并使用Azure开发人员 CLI 将其部署到 Foundry。

Microsoft Foundry 技能可帮助实现适配器、测试协议,并借助azd进行部署。

先决条件

  • 一份 Azure 订阅。 免费创建一个。
  • Foundry 项目。
  • 已部署的聊天模型,例如 gpt-4.1 或 gpt-4o。
  • 项目上的 Foundry 项目经理角色,用于部署托管智能体。 有关详细信息,请参阅 部署托管代理。
  • Azure CLI登录(az login),以便DefaultAzureCredential进行身份验证。
  • Python 3.10 或更高版本。
  • .NET 10 SDK 或更高版本。

安装软件包

安装 Agent Framework 和 Foundry 托管包:

pip install -U agent-framework agent-framework-foundry-hosting azure-identity python-dotenv

该 agent_framework_foundry_hosting 包为 Foundry 协议提供主机服务器:

  • ResponsesHostServer 用于与 OpenAI 兼容的 /responses 端点。
  • InvocationsHostServer 用于通用 /invocations 端点。

将 Agent Framework 和 Foundry 托管包添加到项目:

dotnet add package Microsoft.Agents.AI
dotnet add package Microsoft.Agents.AI.Foundry.Hosting
dotnet add package Azure.AI.Projects
dotnet add package Azure.Identity

对于 Invocations 协议,还需添加 Invocations 服务器包:

dotnet add package Azure.AI.AgentServer.Invocations

这些包为 Foundry 协议提供主机扩展:

  • AddFoundryResponses 以及 MapFoundryResponses 用于 OpenAI 兼容的 /responses 终结点。
  • AddInvocationsServer 以及 MapInvocationsServer 用于泛型 /invocations 终结点。

选择托管协议

托管代理可以公开一个或多个协议。 从大多数会话代理的响应开始。

Protocol Endpoint 何时使用
Responses /responses 你需要兼容 OpenAI 的聊天、流式输出、响应历史和对话线程功能。
调用 /invocations 需要自定义 JSON 形状、Webhook 样式的终结点或非对话处理。

有关协议行为和会话的背景信息,请参阅 托管代理 和管理 托管代理会话。

配置环境变量

设置用于本地开发的项目终结点和模型部署名称:

export FOUNDRY_PROJECT_ENDPOINT="https://<resource>.services.ai.azure.com/api/projects/<project>"
export AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4.1"

在 PowerShell 中:

$env:FOUNDRY_PROJECT_ENDPOINT="https://<resource>.services.ai.azure.com/api/projects/<project>"
$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4.1"

当同一代码在 Foundry 中作为托管代理运行时,平台会在运行时注入 FOUNDRY_PROJECT_ENDPOINT 和 AZURE_AI_MODEL_DEPLOYMENT_NAME。

响应协议

当你需要一个与 OpenAI 兼容的聊天端点,并且支持流式传输、响应历史记录和对话线程时,请使用 Responses 协议。

创建响应主机

创建一个名为 main.py 的文件,其中包含一个使用 Foundry 模型的最简 Agent Framework 代理。

import os

from agent_framework import Agent
from agent_framework.foundry import FoundryChatClient
from agent_framework_foundry_hosting import ResponsesHostServer
from azure.identity import DefaultAzureCredential
from dotenv import load_dotenv

# Load environment variables from a .env file when present.
load_dotenv()


def main() -> None:
    client = FoundryChatClient(
        project_endpoint=os.environ["FOUNDRY_PROJECT_ENDPOINT"],
        model=os.environ["AZURE_AI_MODEL_DEPLOYMENT_NAME"],
        credential=DefaultAzureCredential(),
    )

    agent = Agent(
        client=client,
        instructions="You are a friendly assistant. Keep your answers brief.",
        # The hosting infrastructure manages conversation history, so the
        # service doesn't need to store it.
        default_options={"store": False},
    )

    server = ResponsesHostServer(agent)
    server.run()


if __name__ == "__main__":
    main()

此代码片段的作用: 通过 FoundryChatClient 创建一个以 Foundry 模型为后端的 Agent Framework 代理,然后将该代理传递给 ResponsesHostServer。 主机启动 HTTP 服务器,并通过 POST /responses公开该代理。 默认情况下,服务器绑定到端口 8088。

参考:Microsoft Agent Framework 文档

在本地运行应用:

python main.py

创建一个 Program.cs 文件,其中包含一个最小化的 Agent Framework 代理,该代理通过 Responses 协议使用 Foundry 模型。

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

var projectEndpoint = new Uri(
    Environment.GetEnvironmentVariable("FOUNDRY_PROJECT_ENDPOINT")
    ?? throw new InvalidOperationException("FOUNDRY_PROJECT_ENDPOINT is not set."));

var deployment =
    Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLOYMENT_NAME")
    ?? "gpt-4o";

// Create the agent via the AI project client using the Responses API.
AIAgent agent = new AIProjectClient(projectEndpoint, new DefaultAzureCredential())
    .AsAIAgent(
        model: deployment,
        instructions: "You are a friendly assistant. Keep your answers brief.",
        name: "assistant",
        description: "A simple general-purpose AI assistant");

// Host the agent as a Foundry hosted agent using the Responses API.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddFoundryResponses(agent);

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

此代码片段的作用:从 Foundry 项目客户端创建AIAgent,使用AddFoundryResponses将其注册为 Foundry Responses 主机,并使用POST /responses映射MapFoundryResponses终结点。 默认情况下,主机在端口 8088上提供服务。

参考: AIProjectClient | DefaultAzureCredential

在本地运行应用:

dotnet run

测试响应终结点

将非流式处理响应请求发送到本地服务器。

Bash:

curl -sS -H "Content-Type: application/json" \
  -X POST http://localhost:8088/responses \
  -d '{"input":"Give me one practical tip for testing hosted agents.","stream":false}'

PowerShell:

$body = @{
  input  = "Give me one practical tip for testing hosted agents."
  stream = $false
} | ConvertTo-Json

Invoke-RestMethod `
    -Uri http://localhost:8088/responses `
    -Method Post `
    -Body $body `
    -ContentType "application/json"

服务器使用包含响应文本和响应 ID 的 JSON 对象进行响应。 对于流式响应,将 stream 设置为 true。 主机发出响应 API 服务器发送的事件,例如 response.created, response.output_text.delta和 response.completed。

多轮次对话

若要继续对话,请在下一个请求的 previous_response_id 字段中传入上一个响应 ID:

curl -sS -H "Content-Type: application/json" \
  -X POST http://localhost:8088/responses \
  -d '{"input":"Can you make that more concise?","previous_response_id":"<previous-response-id>","stream":false}'

在 Foundry 中运行代理时,同一模式通过托管代理响应终结点工作。 如果后续轮次也需要相同的托管沙盒文件系统,请包含 agent_session_id 或使用 conversation ID。 有关详细信息,请参阅 管理托管代理会话。

调用协议

当调用方无法使用 Responses API 的请求格式,或者你的场景不是聊天对话时,请使用 Invocations 协议。 调用主机通过 agent_session_id 查询参数和响应标头管理会话状态。

创建 Invocations 主机

使用与 Responses 示例相同的代理设置,但启动 InvocationsHostServer 而不是 ResponsesHostServer。

import os

from agent_framework import Agent
from agent_framework.foundry import FoundryChatClient
from agent_framework_foundry_hosting import InvocationsHostServer
from azure.identity import DefaultAzureCredential
from dotenv import load_dotenv

# Load environment variables from a .env file when present.
load_dotenv()


def main() -> None:
    client = FoundryChatClient(
        project_endpoint=os.environ["FOUNDRY_PROJECT_ENDPOINT"],
        model=os.environ["AZURE_AI_MODEL_DEPLOYMENT_NAME"],
        credential=DefaultAzureCredential(),
    )

    agent = Agent(
        client=client,
        instructions="You are a friendly assistant. Keep your answers brief.",
        default_options={"store": False},
    )

    server = InvocationsHostServer(agent)
    server.run()


if __name__ == "__main__":
    main()

此代码片段的作用: 通过 POST /invocations. 承载 Agent Framework 代理。 主机通过 agent_session_id 查询参数和响应标头管理每会话状态。

参考:Microsoft Agent Framework 文档

Invocations 协议使用由你实现的 InvocationHandler 来处理每个请求。 注册调用服务器和处理程序,然后映射终结点。

using Azure.AI.AgentServer.Invocations;
using Microsoft.Agents.AI;

var builder = WebApplication.CreateBuilder(args);

// Register your agent and the Invocations server services.
builder.Services.AddInvocationsServer();
builder.Services.AddScoped<InvocationHandler, MyInvocationHandler>();

var app = builder.Build();

// Map the Invocations protocol endpoints:
//   POST /invocations              - invoke the agent
//   GET  /invocations/{id}         - get result
//   POST /invocations/{id}/cancel  - cancel
app.MapInvocationsServer();
app.Run();

此代码片段的作用: 注册调用服务器服务和 InvocationHandler 实现,然后映射 /invocations 终结点。 你可以实现MyInvocationHandler,以定义如何处理每个请求。 有关完整的处理程序示例,请参阅.NET调用示例。

参考: AddInvocationsServer

测试调用端点

将请求发送到本地服务器:

curl -sS -X POST http://localhost:8088/invocations \
  -H "Content-Type: application/json" \
  -d '{"message":"My name is Alice.","stream":false}'

对于多轮次对话,请在下一个请求中重复使用 agent_session_id 响应标头中的值作为 agent_session_id 查询参数:

curl -sS -X POST "http://localhost:8088/invocations?agent_session_id=<session-id>" \
  -H "Content-Type: application/json" \
  -d '{"message":"What is my name?"}'

平台不会存储调用协议的对话历史记录。 使用 agent_session_id 查询参数将后续调用路由至同一个托管沙盒。

部署

使用Azure开发人员 CLI (azd) 进行部署。 该流使用示例清单和 Docker 生成代理容器映像,并将其推出到 Foundry 托管的代理运行时。

托管智能体部署需要在项目上具有 Foundry 项目管理员角色。 有关详细信息,请参阅 部署托管代理。

安装 Azure Developer CLI 扩展

在初始化示例之前安装 AI 代理扩展并登录:

azd ext install azure.ai.agents
azd auth login

Docker 必须在本地运行,因为 azd ai agent run 生成在示例的 Dockerfile 中声明的容器映像。 有关命令详细信息,请参阅 Azure 开发人员 CLI 参考。

从示例清单初始化

创建新文件夹,并从示例清单初始化它。 将清单 URL 替换为要使用的示例。

mkdir my-agent-framework-agent
cd my-agent-framework-agent

azd ai agent init -m https://github.com/microsoft/agent-framework/blob/main/python/samples/04-hosting/foundry-hosted-agents/responses/basic/agent.manifest.yaml
mkdir my-agent-framework-agent
cd my-agent-framework-agent

azd ai agent init -m https://github.com/microsoft/agent-framework/blob/main/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ChatClientAgent/agent.manifest.yaml

按照 azd ai agent init 的提示操作。 如果还没有 Foundry 项目和模型部署,初始化流可以指导你创建它们。

预配 Azure 资源

如果初始化的项目使用新的 Foundry 项目和模型部署,请先预配Azure资源:

azd provision

此命令将创建一个资源组,其中包含其他资源:Foundry 实例、具有模型部署的 Foundry 项目、Application Insights 实例和托管代理映像的容器注册表。

在本地运行容器

通过 azd以下方法在本地运行代理主机:

azd ai agent run

主机在 http://localhost:8088 上提供服务。 在另一个终端中,调用本地协议终结点:

azd ai agent invoke --local "Hello!"

您还可以使用 curl 直接调用该端点:

curl -X POST http://localhost:8088/responses \
  -H "Content-Type: application/json" \
  -d '{"input": "Hello!"}'

部署到 Foundry

部署代理:

azd deploy

部署将代理打包到容器映像中,将其推送到预配的容器注册表,并将其推出到 Foundry 托管代理运行时。

Foundry 托管基础结构将运行时环境变量注入代理,包括:

  • FOUNDRY_PROJECT_ENDPOINT:部署代理的 Foundry 项目的终结点 URL。
  • AZURE_AI_MODEL_DEPLOYMENT_NAME:在azd ai agent init过程中选择的模型部署名称。
  • APPLICATIONINSIGHTS_CONNECTION_STRING:项目的 Application Insights 实例的连接字符串。

有关完整的部署概念、权限和管理详细信息,请参阅 部署托管代理 和管理 托管代理生命周期。

Troubleshooting

使用此清单诊断使用 Agent Framework 开发托管代理时的常见问题。

无法在托管容器中访问模型

确认托管代理版本包括 AZURE_AI_MODEL_DEPLOYMENT_NAME,并且代理标识有权调用 Foundry 项目。 平台设置 FOUNDRY_PROJECT_ENDPOINT;代码应在 Foundry 中运行时读取该变量。

对话状态不延续。

对于 Responses 协议,在后续轮次中传入 previous_response_id 或 conversation ID。

对于调用协议,平台不会存储对话历史记录。 使用 agent_session_id 查询参数将后续调用路由到同一个托管沙盒。

协议版本不匹配

如果在升级后请求失败,请确认清单和托管包都使用协议版本 2.0.0。 不再支持协议版本 1.0.0。

后续步骤