Foundry 托管代理

Microsoft Foundry 代理服务中的 托管代理允许将 Agent Framework 代理部署为容器化应用程序,在 Microsoft 托管的基础设施上。 平台处理缩放、会话状态持久性、安全性和生命周期管理,以便你可以专注于代理的逻辑。 Microsoft Foundry 托管代理现已正式发布。

借助 Agent Framework 托管集成,只需极少量代码即可通过 Foundry Responses 或 Invocations 协议公开提供一个 Agent,包括用 Workflow.as_agent() 包装的工作流。

何时使用托管代理

如果需要,请选择 Foundry 托管代理:

  • 托管基础结构 - 无需自行配置容器、Web 服务器或缩放规则。
  • 内置会话管理 —— 平台跨轮次和空闲时段保留 $HOME 和上传文件。
  • 专用代理标识 - 每个已部署的代理获取其自己的 Entra 标识,以便安全访问模型、工具和下游服务。
  • 与 OpenAI 兼容的终结点 - 客户端可以通过响应协议使用任何与 OpenAI 兼容的 SDK 与代理交互。

注释

Python agent-framework-foundry-hosting 集成目前为预发布版本。 Microsoft Foundry 托管代理(托管托管服务)已正式发布。

先决条件

对于本地测试,还需要:

安装托管 NuGet 包:

dotnet add package Microsoft.Agents.AI.Foundry.Hosting --prerelease
dotnet add package Azure.AI.Projects --prerelease
  • Python 3.10 或更高版本

安装预发行版托管包、Foundry 客户端和Azure身份验证包:

pip install --pre agent-framework-foundry agent-framework-foundry-hosting azure-identity

在 Foundry 中,平台提供调用方的用户上下文和调用上下文;托管基础结构使用它们来隔离每个用户的状态,并将请求上下文转发到 Foundry 服务。 本地运行时不会获得该平台的上下文信息,因此应用程序必须在需要时自行提供身份和状态控制机制。

响应协议

对于大多数代理,推荐以Responses协议为起点。 它公开与 OpenAI 兼容的 /responses 终结点,平台会自动管理会话历史记录、流式处理和会话生命周期。

using Azure.AI.AgentServer.Core;
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";

AIAgent agent = new AIProjectClient(projectEndpoint, new DefaultAzureCredential())
    .AsAIAgent(
        model: deployment,
        instructions: "You are a helpful AI assistant.",
        name: "my-agent");

var builder = AgentHost.CreateBuilder(args);
builder.Services.AddFoundryResponses(agent);
builder.RegisterProtocol("responses", endpoints => endpoints.MapFoundryResponses());

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

生成 AgentHost.CreateBuilder 来创建专为 Foundry 托管环境预配置的应用程序主机。 AddFoundryResponses 将代理注册到响应协议处理程序,并 MapFoundryResponses 映射 /responses HTTP 终结点。

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

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 helpful AI assistant.",
    default_options={"store": False},
)

server = ResponsesHostServer(agent)
server.run()

包装ResponsesHostServer以包裹您的代理,并通过 Foundry Responses 协议将其公开。 store False设置为default_options避免复制会话历史记录,因为托管基础结构会自动管理历史记录。

调用协议

调用协议可让你完全控制 HTTP 请求和响应。 如果您需要自定义负载、非会话处理或不兼容 OpenAI 的流式处理协议,请使用它。

使用 C# 中的调用协议,可以实现用于处理传入请求的自定义 InvocationHandler

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

var builder = AgentHost.CreateBuilder(args);

builder.Services.AddSingleton<AIAgent, MyAgent>();
builder.Services.AddInvocationsServer();
builder.Services.AddScoped<InvocationHandler, MyInvocationHandler>();

builder.RegisterProtocol("invocations", endpoints => endpoints.MapInvocationsServer());

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

该方法 AddInvocationsServer 注册调用协议服务。 实现 InvocationHandler 以定义代理处理每个请求的方式。

对于轻量级配置,请使用InvocationsHostServer中的agent_framework_foundry_hosting包。 它像 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

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

若要完全控制请求处理,请直接从InvocationAgentServerHost包使用azure.ai.agentserver.invocations并实现自己的调用处理程序:

import os
from collections.abc import AsyncGenerator

from agent_framework import Agent, AgentSession
from agent_framework.foundry import FoundryChatClient
from azure.ai.agentserver.invocations import InvocationAgentServerHost
from azure.identity import DefaultAzureCredential
from starlette.requests import Request
from starlette.responses import JSONResponse, Response, StreamingResponse

_sessions: dict[str, AgentSession] = {}

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},
)

app = InvocationAgentServerHost()


@app.invoke_handler
async def handle_invoke(request: Request):
    """Handle streaming multi-turn chat."""
    data = await request.json()
    session_id = request.state.session_id
    stream = data.get("stream", False)
    user_message = data.get("message", None)

    if user_message is None:
        return Response(content="Missing 'message' in request", status_code=400)

    session = _sessions.setdefault(session_id, AgentSession(session_id=session_id))

    if stream:

        async def stream_response() -> AsyncGenerator[str]:
            async for update in agent.run(user_message, session=session, stream=True):
                yield update.text

        return StreamingResponse(
            stream_response(),
            media_type="text/event-stream",
            headers={"Cache-Control": "no-cache", "Connection": "keep-alive"},
        )

    response = await agent.run([user_message], session=session, stream=stream)
    return JSONResponse({"response": response.text})


if __name__ == "__main__":
    app.run()

警告

自定义处理程序示例中的内存中会话存储在重启时丢失。 在生产中使用持久存储(例如 Cosmos DB)。

注释

即将推出对 Foundry 托管代理的 Go 支持。 有关最新状态,请参阅 Agent Framework Go 存储库

小窍门

有关托管代理项目的示例,请参阅 Python 示例C# 示例azd ai agent init或使用该命令从头开始搭建新的托管代理项目。 有关分步说明,请参阅本 快速入门指南

在本地运行

Azure开发人员 CLI(azd)提供了在本地运行和测试托管代理的最简单方法。

初始化项目

从示例清单创建新文件夹并初始化:

mkdir my-hosted-agent && cd my-hosted-agent
azd ai agent init -m <path-to-agent.manifest.yaml>

小窍门

清单可以是本地 YAML 文件的路径,也可以是远程清单的 URL。

设置环境变量。

export FOUNDRY_PROJECT_ENDPOINT="https://<account>.services.ai.azure.com/api/projects/<project>"
export AZURE_AI_MODEL_DEPLOYMENT_NAME="<your-model-deployment>"

运行代理主机

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!"}'

或在 PowerShell 中:

(Invoke-WebRequest -Uri http://localhost:8088/responses -Method POST -ContentType "application/json" -Body '{"input": "Hello!"}').Content

部署到“Foundry”

在本地验证代理后,将其部署到 Microsoft Foundry:

  1. 预配资源(如果您还没有 Foundry 项目):

    azd provision
    

    这会创建一个资源组,其中包含 Foundry 实例、项目、模型部署、Application Insights 和容器注册表。

  2. 部署代理:

    azd deploy
    

    这会将代理打包为容器映像,将其推送到Azure 容器注册表,并将其部署到 Foundry 代理服务。

Foundry 托管基础结构会在运行时自动将以下环境变量注入代理容器:

可变 Description
FOUNDRY_PROJECT_ENDPOINT Foundry 项目的端点 URL。
AZURE_AI_MODEL_DEPLOYMENT_NAME 模型部署名称(在azd ai agent init期间配置)。
APPLICATIONINSIGHTS_CONNECTION_STRING 用于遥测的 Application Insights 连接字符串。

部署后,代理可通过其专用 Foundry 终结点进行访问,也可以从 Foundry 门户进行测试。

后续步骤