Agenti Host LangGraph come agenti ospitati da Foundry

Usare il pacchetto langchain_azure_ai.agents.hosting per esporre un grafico LangGraph compilato tramite i protocolli per Microsoft Foundry hosted agents. Il pacchetto di hosting consente di mantenere la logica dell'agente LangChain e LangGraph nel codice, mentre Foundry gestisce il runtime ospitato, le sessioni, la scalabilità, l'identità e gli endpoint del protocollo.

In questo articolo viene creato un agente LangGraph minimo, che viene esposto tramite il protocollo Responses o Invocations, testarlo tramite HTTP e distribuirlo in Foundry con l'interfaccia della riga di comando di Azure Developer o l'estensione Foundry Toolkit Visual Studio Code.

Prerequisiti

  • Una sottoscrizione di Azure. Creane uno gratis.
  • Progetto Foundry.
  • Modello di chat distribuito, ad esempio gpt-4.1 o gpt-5-mini.
  • Python 3.10 o versione successiva.
  • Interfaccia della riga di comando di Azure connessa (az login) in modo che DefaultAzureCredential possa eseguire l'autenticazione.

Installare il pacchetto

Installa langchain-azure-ai 1.2.4 o versione successiva con l'extra di hosting:

pip install -U "langchain-azure-ai[hosting]>=1.2.4" azure-identity

Il hosting componente aggiuntivo installa le librerie di protocolli Foundry usate dai server host:

  • azure-ai-agentserver-responses per l'endpoint compatibile con OpenAI /responses.
  • azure-ai-agentserver-invocations per l'endpoint generico /invocations .

Scegliere un protocollo di hosting

Gli agenti ospitati possono esporre uno o più protocolli. Inizia con Responses per la maggior parte degli agenti conversazionali.

Protocollo Classe host Punto finale Usa quando
Responses ResponsesHostServer /responses Vuoi chat, streaming, cronologia delle risposte e thread di conversazione compatibili con OpenAI.
Invocazioni InvocationsHostServer /invocations Si desidera una forma JSON personalizzata, un endpoint in stile webhook o un'elaborazione non conversazionale.

Per informazioni generali sul comportamento e le sessioni del protocollo, vedere Agenti ospitati e Gestire sessioni dell'agente ospitato.

Configurare le variabili di ambiente

Impostare l'endpoint del progetto e il nome della distribuzione del modello per lo sviluppo locale:

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

Quando lo stesso codice viene eseguito come agente ospitato in Foundry, la piattaforma inserisce FOUNDRY_PROJECT_ENDPOINT. Se si usa azd ai agent init con un esempio azure.yaml, il progetto generato usa FOUNDRY_MODEL_NAME anche per la distribuzione del modello selezionata.

Protocollo di risposte

Usa il protocollo Responses quando vuoi un endpoint di chat compatibile con OpenAI con streaming, cronologia delle risposte e threading delle conversazioni.

Crea un host di Responses

Creare un file denominato main.py con un agente LangGraph minimo che usa un modello Foundry. Questo modello corrisponde all'esempio di risposte di base nel langchain-azure-ai repository di origine.

import os

from azure.ai.projects import AIProjectClient
from azure.identity import DefaultAzureCredential, get_bearer_token_provider
from langchain.agents import create_agent
from langchain_openai import ChatOpenAI

from langchain_azure_ai.agents.hosting import ResponsesHostServer

_AZURE_AI_SCOPE = "https://ai.azure.com/.default"


def build_chat_model() -> ChatOpenAI:
    project_endpoint = os.environ["FOUNDRY_PROJECT_ENDPOINT"].rstrip("/")
    deployment = os.environ.get("FOUNDRY_MODEL_NAME", "gpt-4.1")
    credential = DefaultAzureCredential()
    project = AIProjectClient(endpoint=project_endpoint, credential=credential)
    openai_client = project.get_openai_client()
    token_provider = get_bearer_token_provider(credential, _AZURE_AI_SCOPE)

    return ChatOpenAI(
        model=deployment,
        base_url=str(openai_client.base_url),
        api_key=token_provider,
    )


def main() -> None:
    graph = create_agent(build_chat_model(), tools=[])
    port = int(os.environ.get("PORT", "8088"))
    ResponsesHostServer(graph).run(port=port)


if __name__ == "__main__":
    main()

Cosa fa questo frammento di codice: Crea un agente LangGraph con LangChain create_agent, lo connette all'endpoint del modello compatibile con OpenAI del progetto Foundry e passa il grafico compilato a ResponsesHostServer. L'host avvia un server HTTP ed espone il grafico tramite POST /responses. Per impostazione predefinita, il server viene associato alla porta 8088o al valore della variabile di PORT ambiente quando ne viene impostata una.

Esegui l'app in locale:

python main.py

Testare l'endpoint delle risposte

Inviare una richiesta di risposte non in streaming al server locale.

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"

Per le risposte in streaming, impostare stream su true. L'host emette eventi inviati dal server dell'API Responses, come response.created, response.output_text.delta e response.completed.

Conversazioni

ResponsesHostServer supporta due modelli di stato della conversazione. Lo schema che utilizza dipende dal fatto che il grafico compilato includa un checkpointer di LangGraph.

Configurazione di Graph Fonte della conversazione Ciò che l'host invia al grafo nei turni successivi
Grafico senza gestore dei checkpoint Cronologia delle risposte dal runtime del protocollo Cronologia delle risposte precedenti più l'input della richiesta corrente
Grafico compilato con un gestore dei checkpoint Stato del checkpoint di LangGraph identificato dal thread di conversazione o di risposta Solo l’input della richiesta corrente

Usare un gestore dei checkpoint quando il tuo grafico richiede lo stato di runtime di LangGraph, gli interrupt o lo stato locale del nodo tra turni. Per i test in locale, è possibile usare un gestore di checkpoint in memoria:

from langgraph.checkpoint.memory import MemorySaver

graph = create_agent(
    build_chat_model(),
    tools=[],
    checkpointer=MemorySaver(),
)

Per gli agenti Hosted di produzione, utilizzare un checkpointer persistente anziché un checkpointer in memoria, in modo che lo stato del grafico persista anche dopo il riavvio del contenitore.

I client proseguono una conversazione Responses passando previous_response_id o un ID conversation. Per i test locali, concatenare l'ID risposta precedente nella richiesta successiva:

POST http://localhost:8088/responses
Content-Type: application/json

{
  "input": "Can you make that more concise?",
  "previous_response_id": "<previous-response-id>",
  "stream": false
}

Quando l'agente viene eseguito in Foundry, lo stesso schema funziona tramite l'endpoint Responses dell'agente ospitato. Se anche le interazioni successive richiedono lo stesso filesystem della sandbox ospitata, includere agent_session_id o usare un ID conversation. Per informazioni dettagliate, vedere Gestire le sessioni dell'agente ospitato.

Human-in-the-Loop

Se il tuo grafico usa chiamate interrupt() LangGraph, ResponsesHostServer mostra le interruzioni in sospeso tramite gli elementi di output standard delle API Responses:

  • Elemento function_call denominato __hosted_agent_adapter_interrupt__.
  • Elemento mcp_approval_request con server_label impostato su langgraph.

I client possono riprendere il grafico inviando un elemento function_call_output il cui call_id corrisponde all'ID di interrupt oppure un elemento mcp_approval_response il cui approval_request_id corrisponde all'ID di interrupt. Usare function_call_output quando è necessario inviare un payload LangGraph avanzato Command con campi resume, update o goto. Usare mcp_approval_response per un semplice flusso di approvazione o rifiuto.

Protocollo di Invocazioni

Usare InvocationsHostServer quando i chiamanti non possono usare la forma della richiesta API Risposte o quando lo scenario non è una conversazione di chat. L'host predefinito per le chiamate accetta una stringa message e un flag facoltativo stream.

Creare un host di invocazioni

Usare la stessa funzione di compilazione del modello dell'esempio Risposte, ma iniziare InvocationsHostServer invece di ResponsesHostServer.

import os

from langchain.agents import create_agent
from langgraph.checkpoint.memory import MemorySaver

from langchain_azure_ai.agents.hosting import InvocationsHostServer


def main() -> None:
    graph = create_agent(
        build_chat_model(),
        tools=[],
        checkpointer=MemorySaver(),
    )
    port = int(os.environ.get("PORT", "8088"))
    InvocationsHostServer(graph).run(port=port)


if __name__ == "__main__":
    main()

Cosa fa questo frammento di codice: Ospita l'agente LangGraph tramite POST /invocations. Il gestore dei checkpoint MemorySaver fornisce continuità locale tra più turni per un determinato ID di sessione. Per la produzione, utilizzare un gestore dei checkpoint persistente in modo che lo stato venga mantenuto anche dopo il riavvio dei container.

Testare l'endpoint delle invocazioni

Inviare una richiesta non di streaming:

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

Le richieste non di streaming restituiscono JSON in questa forma:

{
  "response": "Assistant text"
}

Per le conversazioni a più turni, riutilizzare l'intestazione della x-agent-session-id risposta agent_session_id come parametro di query nella richiesta successiva:

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

Le richieste di streaming restituiscono eventi text/event-stream con payload di token:

curl -N -X POST http://localhost:8088/invocations \
  -H "Content-Type: application/json" \
  -d '{"message":"Count to 5.","stream":true}'

Il flusso contiene eventi di token seguiti da un evento del terminale done :

data: {"token": "..."}

event: done
data: {}

Personalizzare lo schema della richiesta

Per personalizzare il corpo della richiesta, crea una sottoclasse di InvocationsHostServer e sovrascrivi parse_request. È anche possibile eseguire l'override build_input per eseguire il mapping dei dati analizzati a uno stato del grafico personalizzato.

from starlette.requests import Request

from langchain_azure_ai.agents.hosting import InvocationsHostServer


class TicketHostServer(InvocationsHostServer):
    async def parse_request(self, request: Request) -> tuple[str, bool]:
        data = await request.json()
        ticket_id = data["ticket_id"]
        description = data["description"]
        stream = bool(data.get("stream", False))
        return f"Summarize ticket {ticket_id}: {description}", stream


if __name__ == "__main__":
    TicketHostServer(graph).run()

Cosa fa questo frammento di codice: Accetta un payload di ticket personalizzato e lo converte in un singolo messaggio utente prima che l'host richiami il grafico. Per uno stato del grafo più complesso, eseguire l'override build_input anziché appiattire la richiesta al testo.

Deploy

È possibile eseguire la distribuzione usando l'interfaccia della riga di comando di Azure Developer o l'estensione Foundry Toolkit Visual Studio Code. Il flusso dell'interfaccia della riga di comando per sviluppatori Azure usa file di esempio azure.yaml e Docker. Il flusso di estensione offre un'esperienza di distribuzione guidata in Visual Studio Code.

La distribuzione dell'agente ospitato richiede il ruolo Project Manager Foundry nel progetto. Per informazioni dettagliate, vedere Distribuire un agente ospitato.

Distribuire con Azure Developer CLI

Il langchain-azure-ai repository sorgente include esempi di agenti ospitati che puoi eseguire e distribuire usando Azure Developer CLI. Il flusso usa azure.yaml, Dockerfile e main.py di ogni esempio. Per informazioni dettagliate sulla configurazione dell'agente ospitato in azure.yaml, vedere Creare azure.yaml per gli agenti ospitati.

Installare l'estensione dell'agente di intelligenza artificiale e accedere prima di inizializzare un esempio:

azd ext install azure.ai.agents
azd auth login

Docker deve essere in esecuzione in locale perché azd ai agent run compila l'immagine del contenitore dichiarata nel Dockerfile dell'esempio. Per informazioni dettagliate sul comando, vedere il riferimento Azure Developer CLI.

Inizializza a partire da un file azure.yaml di esempio

Creare una nuova cartella e inizializzarla da un esempio azure.yaml. Sostituire l'URL azure.yaml con l'esempio da usare.

mkdir my-langchain-agent
cd my-langchain-agent

azd ai agent init -m https://github.com/langchain-ai/langchain-azure/blob/main/samples/hosting/langgraph-hosted-agents/responses/01_basic/azure.yaml

Seguire le istruzioni da azd ai agent init. Se non si dispone già di un progetto Foundry e di una distribuzione di modelli, il flusso di inizializzazione può essere utile per crearli.

Eseguire il contenitore in locale

Esegui l'host dell'agente localmente tramite azd:

azd ai agent run

L'host è in esecuzione su http://127.0.0.1:8088. In un altro terminale richiamare direttamente l'endpoint del protocollo locale:

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

Equivalente di PowerShell:

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

È anche possibile richiamare l'agente locale tramite azd:

azd ai agent invoke --local "Hello!"

Eseguire la distribuzione in Foundry

Se il progetto inizializzato usa un nuovo progetto Foundry e una distribuzione del modello, effettuare prima il provisioning delle risorse Azure:

azd provision

Distribuire l'agente:

azd deploy

La distribuzione racchiude l'agente in un'immagine container, la pubblica nel Registro Container di cui è stato eseguito il provisioning e la distribuisce nel runtime dell'agente ospitato di Foundry.

L'infrastruttura di hosting Foundry inserisce le variabili di ambiente di runtime nell'agente, tra cui:

  • FOUNDRY_PROJECT_ENDPOINT: URL dell'endpoint per il progetto Foundry in cui viene distribuito l'agente.
  • FOUNDRY_MODEL_NAME: nome della distribuzione del modello selezionato durante azd ai agent init.
  • APPLICATIONINSIGHTS_CONNECTION_STRING: La stringa di connessione dell'istanza di Application Insights del progetto.

Per informazioni complete sui concetti di distribuzione, sulle autorizzazioni e sulla gestione, vedere Distribuire un agente ospitato e Gestire il ciclo di vita dell'agente ospitato.

Distribuisci con l'estensione Foundry Toolkit di Visual Studio Code

Per la distribuzione basata su estensione, vedere Avvio rapido: Distribuire il primo agente ospitato.

Troubleshooting

Usare questo elenco di controllo per diagnosticare i problemi comuni durante lo sviluppo di agenti ospitati con langchain_azure_ai.agents.hosting.

La validazione dello schema del grafo non riesce

Gli host predefiniti prevedono un grafico LangGraph compilato il cui stato ha un messages campo, ad esempio MessagesState. Se il grafico usa uno schema di stato personalizzato, sottoclassare l'host ed eseguire l'override di build_input. Per Responses, eseguire l'override di handle_create quando c'è bisogno del pieno controllo sul parsing delle richieste, sull'esecuzione del grafico e sugli eventi Responses emessi.

Lo stato della conversazione non viene mantenuto

Per il protocollo Responses, fornire previous_response_id o un ID conversation nelle richieste successive. Se il grafico usa un gestore dei checkpoint, assicurarsi che sia configurato e persistente per l'ambiente in cui viene eseguito l'agente.

Per il protocollo Invocations, la piattaforma non archivia la cronologia delle conversazioni. Usare un parametro di query agent_session_id per instradare le chiamate successive alla stessa sandbox ospitata e usare il proprio archivio stato o il checkpoint LangGraph per lo stato della conversazione.

Non è possibile raggiungere il modello nel contenitore ospitato

Verificare che la versione dell'agente ospitato includa FOUNDRY_MODEL_NAMEe che l'identità dell'agente disponga dell'autorizzazione per chiamare il progetto Foundry. La piattaforma imposta FOUNDRY_PROJECT_ENDPOINT. Il codice deve leggere tale variabile durante l'esecuzione in Foundry.

Passo successivo