Agentes hospedados da Foundry

Os agentes hospedados no serviço Microsoft Foundry Agent permitem implantar aplicativos de agente em contêineres na infraestrutura gerenciada por Microsoft. A plataforma lida com dimensionamento, persistência de estado de sessão, segurança e gerenciamento de ciclo de vida para que você possa se concentrar na lógica do agente. Microsoft Foundry Hosted Agents está em disponibilidade geral e oferece suporte a agentes criados com seu próprio código ou com o framework de agente de sua preferência. Este artigo aborda especificamente a integração de hospedagem do Agent Framework.

Com a integração de hospedagem do Agent Framework, você pode expor um Agent, incluindo um fluxo de trabalho encapsulado com Workflow.as_agent(), por meio do protocolo Foundry Responses ou Invocations com um mínimo de código.

Note

Você também pode implantar código de agente criado com outros frameworks nos agentes hospedados no Foundry usando fluxos de trabalho da Azure Developer CLI (azd). Para obter conceitos independentes de estrutura e diretrizes de implantação, consulte O que são agentes hospedados? O restante deste artigo se concentra na integração do Agent Framework.

Quando usar agentes hospedados

Escolha os agentes hospedados do Foundry quando quiser.

  • Infraestrutura gerenciada – não é necessário configurar contêineres, servidores Web ou regras de dimensionamento por conta própria.
  • Gerenciamento de sessão integrado — a plataforma persiste $HOME e os arquivos enviados entre turnos e períodos de inatividade.
  • Identidade do agente dedicado – cada agente implantado obtém sua própria identidade de Entra para acesso seguro a modelos, ferramentas e serviços downstream.
  • Endpoints compatíveis com OpenAI – os clientes podem interagir com seu agente usando qualquer SDK compatível com OpenAI através do protocolo Responses.
  • Para agentes de áudio em tempo real, use agentes hospedados com Azure Speech in Foundry Tools (Voice Live) para detecção de atividade de voz do servidor, cancelamento de eco e redução de ruído. Para obter detalhes, consulte Usar o Voice Live com agentes hospedados.

Note

A integração com agent-framework-foundry-hosting Python está em versão preliminar. Microsoft Foundry Hosted Agents, o serviço de hospedagem gerenciada, está disponível em geral.

Prerequisites

Para testes locais, você também precisa:

Instale o pacote NuGet de hospedagem:

dotnet add package Microsoft.Agents.AI.Foundry.Hosting --prerelease
  • Python 3.10 ou posterior

Instale o pacote de hospedagem de pré-lançamento, o cliente Foundry e o pacote de autenticação do Azure:

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

No Foundry, a plataforma fornece o contexto de usuário do chamador e o contexto de chamada; a infraestrutura de hospedagem os usa para isolar o estado por usuário e encaminhar o contexto de solicitação para os serviços do Foundry. As execuções locais não recebem esse contexto de plataforma, portanto, os aplicativos devem fornecer sua própria identidade e controles de estado quando necessário.

Protocolo de respostas

O protocolo Respostas é o ponto de partida recomendado para a maioria dos agentes. Ela expõe um ponto de extremidade/responses compatível com OpenAI e a plataforma gerencia o histórico de conversas, streaming e ciclo de vida da sessão automaticamente.

Para agentes hospedados do Python, uma resposta que termina prematuramente tem status incomplete. Os clientes de streaming recebem um evento terminal response.incomplete, enquanto os clientes sem streaming recebem status definido como incomplete. Uma razão de término content_filter corresponde a incomplete_details.reason definido como content_filter, e length corresponde a max_output_tokens. Qualquer saída gerada ou conteúdo de recusa permanece disponível na resposta.

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

O AgentHost.CreateBuilder cria um host de aplicativo pré-configurado para o ambiente de hospedagem do Foundry. AddFoundryResponses registra seu agente com o manipulador de protocolo Responses e MapFoundryResponses mapeia o /responses endpoint 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.",
)

server = ResponsesHostServer(agent)
server.run()

O ResponsesHostServer encapsula seu agente e o expõe por meio do protocolo Foundry Responses. Para um agente sem fluxo de trabalho, por padrão, history_source="agent_server" usa o provedor de resposta do Agent Server configurado como fonte do histórico do modelo. O host impede que o serviço de modelo downstream mantenha uma segunda cópia quando o cliente armazena o histórico por padrão.

Não combine a fonte de histórico padrão com uma HistoryProvider que tenha load_messages=True. Além disso, não defina as opções conversation_id, conversation ou previous_response_id de continuação do serviço downstream. O host rejeita essas configurações para impedir o histórico duplicado.

Use ResponsesHostServer(agent, history_source="agent") quando o provedor de histórico do agente ou o serviço de modelo downstream precisar gerenciar o histórico de conversas. Esse modo passa apenas a entrada de solicitação atual do Servidor do Agente e preserva o histórico do agente e o comportamento de armazenamento do serviço. Implementações personalizadas SupportsAgentRun devem usar esse modo. O parâmetro store permanece separado: ele seleciona o provedor de respostas que armazena de forma persistente as entradas e saídas da API de Respostas em ambos os modos.

O host é proprietário do agente fornecido e pode adicionar provedores de contexto específicos de hospedagem. Não reutilize o agente com outro host ou invoque-o diretamente após a construção do host.

Escolha uma instância ou fábrica de agentes

Tanto InvocationsHostServer quanto ResponsesHostServer aceitam uma instância de agente ou um callable síncrono ou assíncrono sem argumentos por meio do parâmetro agent. O host reutiliza uma instância durante todo o seu ciclo de vida. Um callable é executado uma vez por requisição, e o agente retornado pertence a essa requisição.

Use um callable quando o agente mantém estado mutável fora de AgentSession. Em particular, crie um WorkflowAgent usando uma fábrica que constrói um novo fluxo de trabalho, executores e agentes encapsulados:

def create_workflow_agent():
    return build_workflow().as_agent(name="support-workflow")


server = ResponsesHostServer(agent=create_workflow_agent)

Mantenha o nome do fluxo de trabalho e as IDs do executor estáveis para que as solicitações de respostas posteriores possam localizar pontos de verificação salvos. ResponsesHostServer mantém o estado com suporte por meio de seus armazenamentos de sessão, pontos de verificação e aprovação de funções; não persiste campos arbitrários em um agente com escopo de solicitação. Consulte os exemplos de fluxo de trabalho e de fluxo de trabalho resiliente de longa duração.

Manter o estado e lidar com conversas de longa execução

ResponsesHostServer e InvocationsHostServer configure repositórios de sessão persistentes por padrão. AgentSessionStoreProvider fornece um FoundryAgentSessionStore; as sessões de resposta usam o repositório lógico agent_sessions, enquanto as sessões de invocação usam o repositório separado invocation_sessions. Esses repositórios usam o Repositório de Estado do Foundry quando hospedados e o armazenamento com suporte de arquivo do SDK quando você é executado localmente.

Para agentes de fluxo de trabalho do Responses, CheckpointStoreProvider fornece um FoundryCheckpointStore. FunctionApprovalStoreProvider fornece um FoundryFunctionApprovalStore para aprovações pendentes.

Com history_source="agent", o repositório de sessão configurado persiste o estado do provedor transportado por AgentSession, incluindo mensagens de InMemoryHistoryProvider.

Ambos os hosts aceitam de StoreProvider[SessionStore] a agent_session_store_provider. O estado da sessão deve dar suporte à AgentSession serialização. Registre codecs para tipos de estado personalizados com register_state_type(); o estado restaurado não preserva a identidade do objeto em Python. Novos repositórios padrão expiram sessões 30 dias após a última gravação. Os provedores personalizados controlam sua própria retenção.

Para armazenamento específico para Responses, passe um StoreProvider para function_approval_store_provider ou um ContextScopedStoreProvider para checkpoint_store_provider.

Importe ResponsesServerOptions de azure.ai.agentserver.responses e passe-o para options por meio do parâmetro ResponsesHostServer. As opções disponíveis de conversa de longa duração dependem do tipo de agente:

Capacidade Tipo de agente Requisitos e comportamento
Respostas resilientes em segundo plano Somente fluxo de trabalho Defina ResponsesServerOptions(resilient_background=True). Enviar a solicitação respostas com store=true e background=true. Após uma reinicialização, o host retomará o ponto de verificação de fluxo de trabalho durável mais recente ou repetirá a entrada original se nenhum ponto de verificação existir. Não configure o armazenamento de ponto de verificação no fluxo de trabalho, pois o host o gerencia. Torne os efeitos colaterais externos idempotentes porque o trabalho após o último ponto de verificação durável pode se repetir.
Conversas direcionáveis Apenas itens fora de fluxo de trabalho Definir ResponsesServerOptions(steerable_conversations=True) e enviar solicitações de respostas com store=true. Mantenha as curvas em uma única cadeia linear reutilizando o mesmo valor conversation. Como alternativa, envie o previous_response_id imediatamente anterior e preserve o agent_session_id resolvido. O host rejeita predecessores obsoletos que criariam uma bifurcação.

ResponsesHostServer gera RuntimeError se você habilitar respostas em segundo plano resilientes para um agente sem fluxo de trabalho ou conversas direcionáveis ​​para um agente com fluxo de trabalho. Para implementações completas, consulte o armazenamento personalizado, o fluxo de trabalho de execução longa resiliente e os exemplos de agente de execução longa direcionável .

Quando uma ferramenta MCP hospedada pela Foundry requer consentimento do usuário, ResponsesHostServer retorna uma resposta incompleta com um oauth_consent_request item de saída. Apresente seu consent_link ao usuário e, em seguida, continue com a ID da resposta incompleta como previous_response_id depois que o usuário fornecer seu consentimento. O host preserva a sessão do agente para essa repetição e expõe apenas links de consentimento HTTPS absolutos.

Protocolo de invocações

O protocolo Invocações fornece controle total sobre a solicitação HTTP e a resposta. Use-o quando precisar de cargas personalizadas, processamento não conversacional ou protocolos de streaming que não sejam compatíveis com OpenAI.

Com o protocolo Invocações em C#, você implementa uma classe personalizada InvocationHandler para processar solicitações de entrada:

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

O método AddInvocationsServer registra os serviços do Protocolo de Invocações. Você implementa InvocationHandler para definir como seu agente processa cada solicitação.

Para uma configuração leve, use InvocationsHostServer do pacote agent_framework_foundry_hosting. Ele encapsula seu agente da mesma forma ResponsesHostServer e manipula o gerenciamento de sessão automaticamente:

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

InvocationsHostServer aceita as mesmas formas de instância ou de fábrica com escopo de solicitação descritas para o host Responses. Ele restaura sessões serializadas do repositório configurado, para que as conversas concluídas possam continuar após a reinicialização do host. Para obter informações sobre comportamento de armazenamento, retenção e personalização, consulte Persistir o estado e lidar com conversas de longa duração.

Quando hospedada, a ID da sessão da plataforma e a ID do usuário juntas identificam a sessão salva. Trate AgentSession.session_id como um valor opaco; não analise ou dependa de sua representação interna. As execuções locais usam o ID da sessão da plataforma sem alteração. Os aplicativos devem coordenar solicitações sobrepostas para a mesma sessão porque o repositório não fornece transações ou execução exatamente uma vez.

O protocolo Invocações não retoma as execuções de fluxo de trabalho pendentes ou interrompidas. Use o padrão de manipulador personalizado na seção a seguir quando precisar de um comportamento de continuação de fluxo de trabalho diferente.

Para obter controle total sobre o tratamento de solicitações, use InvocationAgentServerHost diretamente do azure.ai.agentserver.invocations pacote e implemente seu próprio manipulador de invocação:

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

Aviso

O repositório de sessão na memória no exemplo do manipulador personalizado é perdido na reinicialização. Use o armazenamento durável (por exemplo, Cosmos DB) em produção.

Para obter uma implantação completa de Invocações, consulte o exemplo do Telegram hospedado pela Foundry. Posiciona o API Management à frente do webhook do agente hospedado e usa identidades gerenciadas, Key Vault e Cosmos DB para um histórico de conversas persistente.

Note

O suporte do Go para agentes hospedados no Foundry estará disponível em breve. Consulte o repositório Agent Framework Go para obter o status mais recente.

Tip

Consulte os exemplos Python ou os exemplos C# para obter exemplos de um projeto de agente hospedado. Ou use o azd ai agent init comando para estruturar um novo projeto de agente hospedado do zero. Consulte este guia de início rápido para obter instruções passo a passo.

Execução local

A CLI do desenvolvedor Azure (azd) fornece a maneira mais fácil de executar e testar seu agente hospedado localmente.

Inicializar um projeto

Crie uma nova pasta e inicialize a partir de um manifesto de exemplo:

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

Tip

O manifesto pode ser um caminho para um arquivo YAML local ou uma URL para um manifesto remoto.

Definir variáveis de ambiente

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

Executar o host do agente

azd ai agent run

O host do agente é iniciado em http://localhost:8088.

Invocar o agente

azd ai agent invoke --local "Hello!"

Ou use curl:

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

Ou no PowerShell:

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

Implantando na Foundry

Depois de verificar o agente localmente, implante-o no Microsoft Foundry:

  1. Provisionar recursos (se você ainda não tiver um projeto do Foundry):

    azd provision
    

    Isso cria um grupo de recursos com uma instância do Foundry, um projeto, uma implantação de modelo, o Application Insights e um registro de contêiner.

  2. Implante o agente:

    azd deploy
    

    Isso empacota seu agente como uma imagem de contêiner, envia-o por push para Registro de Contêiner do Azure e o implanta no Serviço do Foundry Agent.

A infraestrutura de hospedagem do Foundry injeta automaticamente as seguintes variáveis de ambiente no contêiner do agente em runtime:

Variable Description
FOUNDRY_PROJECT_ENDPOINT URL do endpoint do projeto Foundry.
AZURE_AI_MODEL_DEPLOYMENT_NAME O nome do modelo de implantação (configurado durante azd ai agent init).
APPLICATIONINSIGHTS_CONNECTION_STRING A cadeia de conexão do Application Insights para telemetria.

Após a implantação, seu agente fica acessível por meio de seu ponto de extremidade do Foundry dedicado e também pode ser testado no portal do Foundry.

Próximas Etapas