Hébergez des agents LangGraph en tant qu’agents hébergés dans Foundry

Utilisez le package langchain_azure_ai.agents.hosting pour exposer un graphique LangGraph compilé via les protocoles de Microsoft Foundry agents hébergés. Le package d’hébergement vous permet de conserver la logique de votre agent LangChain et LangGraph dans le code tandis que Foundry gère le runtime hébergé, les sessions, la mise à l’échelle, l’identité et les points de terminaison de protocole.

Dans cet article, vous allez créer un agent LangGraph minimal, l’exposer via le protocole Réponses ou Appels, le tester via HTTP et le déployer sur Foundry avec l’interface CLI développeur Azure ou l’extension Foundry Toolkit Visual Studio Code.

Vous allez également apprendre à migrer un projet LangGraph existant sans modifier son code ou sa configuration.

Prerequisites

  • Un abonnement Azure. Créez-en un gratuitement.
  • Un projet Foundry.
  • Un modèle de conversation déployé, tel que gpt-4.1 ou gpt-5-mini.
  • Python 3.10 ou version ultérieure.
  • Azure CLI connecté (az login) afin que DefaultAzureCredential puisse s’authentifier.

Installer le package

Installez langchain-azure-ai la version 1.2.9 ou ultérieure avec l’hébergement supplémentaire :

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

L’élément hosting supplémentaire installe les bibliothèques de protocole Foundry utilisées par les serveurs hôtes :

  • azure-ai-agentserver-responses pour l’endpoint compatible OpenAI /responses.
  • azure-ai-agentserver-invocations pour le point de terminaison générique /invocations .

Choisir un protocole d’hébergement

Les agents hébergés peuvent exposer un ou plusieurs protocoles. Commencez par Responses pour la majorité des agents conversationnels.

Protocol Classe d’hôte Point de terminaison À utiliser lorsque
Responses ResponsesHostServer /responses Vous souhaitez une conversation compatible OpenAI, la diffusion en continu, l’historique des réponses et le thread de conversation.
Appels InvocationsHostServer /invocations Vous souhaitez une forme JSON personnalisée, un point de terminaison de style webhook ou un traitement non conversationnel.

Pour plus d’informations sur le comportement et les sessions de protocole, consultez Agents hébergés et Gérer les sessions d’agent hébergé.

Configurer des variables d’environnement

Définissez le point de terminaison du projet et le nom de déploiement de modèle pour le développement local :

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

Lorsque le même code s’exécute en tant qu’agent hébergé dans Foundry, la plateforme injecte FOUNDRY_PROJECT_ENDPOINT. Si vous utilisez azd ai agent init avec un exemple azure.yaml, le projet généré utilise également FOUNDRY_MODEL_NAME pour le déploiement du modèle sélectionné.

Protocole des réponses

Utilisez le protocole Responses lorsque vous souhaitez un point de terminaison de chat compatible OpenAI avec la diffusion en continu, l’historique des réponses et les fils de conversation.

Créer un hôte de réponses

Créez un fichier nommé main.py avec un agent LangGraph minimal qui utilise un modèle Foundry. Ce schéma correspond à l’exemple de base de Responses dans le dépôt source langchain-azure-ai.

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

Ce que fait cet extrait de code : Crée un agent LangGraph avec LangChain, create_agentle connecte au point de terminaison de modèle compatible OpenAI du projet Foundry et transmet le graphique compilé à ResponsesHostServer. L’hôte démarre un serveur HTTP et expose le graphique via POST /responses. Par défaut, le serveur est lié au port 8088ou à la valeur de la PORT variable d’environnement lorsqu’un port est défini.

Note

Les agents profonds sont hébergés de la même façon que les autres agents LangGraph. Passez l’agent directement à ResponsesHostServer.

agent = create_deep_agent(...)
ResponsesHostServer(agent).run(port=port)

Exécutez l’application localement :

python main.py

Testez le point de terminaison Responses

Envoyez une demande de réponses sans diffusion en continu au serveur local.

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"

Pour les réponses diffusées en continu, définissez stream sur true. L’hôte émet des événements envoyés par le serveur d’API Réponses, tels que response.created, response.output_text.deltaet response.completed.

Conversations

ResponsesHostServer prend en charge deux modèles d’état de conversation. Le modèle qu’il utilise dépend du fait que votre graphique compilé possède un point de contrôle LangGraph.

Configuration du graphe Source de conversation Ce que l’hôte envoie au graphe lors des tours suivants
Graph sans point de contrôle Historique des réponses à partir du runtime du protocole Historique des réponses antérieures plus l’entrée de requête actuelle
Graph compilé avec un point de contrôle État de point de contrôle LangGraph associé à la conversation ou au fil de réponse Entrée de requête actuelle uniquement

Utilisez un point de contrôle lorsque votre graphique a besoin de l’état d’exécution LangGraph, des interruptions ou de l’état local du nœud entre les tours. Pour les tests locaux, vous pouvez utiliser un point de contrôle en mémoire :

from langgraph.checkpoint.memory import MemorySaver

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

Pour les assistants hébergés en production, utilisez un point de contrôle durable au lieu d’un point de contrôle en mémoire afin que l’état du graphique survive aux redémarrages de conteneur.

Les clients poursuivent une conversation Responses en transmettant previous_response_id ou un identifiant conversation. Pour les tests locaux, chaînez l’ID de réponse précédent dans la requête suivante :

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

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

Lorsque l’assistant s’exécute dans Foundry, le même schéma fonctionne via le point de terminaison Responses de l’assistant hébergé. Si les tours suivants nécessitent également le même système de fichiers du bac à sable hébergé, incluez agent_session_id ou utilisez un identifiant conversation. Pour plus d’informations, consultez Gérer les sessions de l’agent hébergé.

Intervention humaine

Si votre graphique utilise des appels LangGraph interrupt() , ResponsesHostServer affiche les interruptions en attente via les éléments de sortie de l’API Réponses standard :

  • Élément function_call nommé __hosted_agent_adapter_interrupt__.
  • Élément mcp_approval_request avec server_label défini sur langgraph.

Les clients peuvent reprendre le graphe en envoyant soit un élément function_call_output dont le call_id correspond à l’ID d’interruption, soit un élément mcp_approval_response dont le approval_request_id correspond à l’ID d’interruption. Utilisez function_call_output lorsque vous devez envoyer une charge utile LangGraph Command riche comportant des champs resume, update ou goto. Utiliser mcp_approval_response pour un flux d’approbation ou de rejet simple.

Protocole d'invocation

Utilisez InvocationsHostServer quand vos appelants ne peuvent pas utiliser la forme de requête de l’API Réponses ou lorsque votre scénario n’est pas une conversation de conversation. L’hôte Invocations par défaut accepte une chaîne message et un indicateur optionnel stream.

Créer un hôte d’invocation

Utilisez la même fonction de génération de modèle à partir de l’exemple Réponses, mais commencez InvocationsHostServer au lieu de 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()

Ce que fait cet extrait de code : Héberge l’agent LangGraph via POST /invocations. Le point de contrôle MemorySaver offre une continuité multitour locale pour un ID de session donné. En production, utilisez un point de contrôle persistant pour que l’état soit conservé lors des redémarrages du conteneur.

Note

Les agents profonds sont hébergés de la même façon que les autres agents LangGraph. Passez l’agent directement à InvocationsHostServer.

agent = create_deep_agent(...)
InvocationsHostServer(agent).run(port=port)

Tester le point de terminaison des appels

Envoyez une demande de non-diffusion en continu :

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

Les demandes de non diffusion en continu retournent JSON sous cette forme :

{
  "response": "Assistant text"
}

Pour les conversations à plusieurs échanges, réutilisez l’en-tête de réponse x-agent-session-id comme paramètre de requête agent_session_id dans la requête suivante :

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

Les requêtes de streaming renvoient des événements text/event-stream avec des charges utiles de token :

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

Le flux contient des événements de jeton suivis d’un événement terminal done :

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

event: done
data: {}

Personnaliser le schéma de requête

Pour personnaliser le corps de la requête, créez une sous-classe de InvocationsHostServer et redéfinissez parse_request. Vous pouvez également remplacer build_input pour mapper les données analysées à un état de graphe personnalisé.

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

Ce que fait cet extrait de code : Accepte une charge utile de ticket personnalisée et la convertit en message utilisateur unique avant que l’hôte appelle le graphique. Pour obtenir un état de graphique plus complexe, remplacez build_input au lieu d’aplatir la requête en texte.

Déployer

Vous pouvez déployer à l’aide de l’interface CLI Azure développeur ou de l’extension Foundry Toolkit Visual Studio Code. Le flux de travail de l’interface Azure Developer CLI utilise des fichiers azure.yaml d’exemple et Docker. Le flux d’extension offre une expérience de déploiement guidée dans Visual Studio Code.

Le déploiement d’un agent hébergé nécessite le rôle Foundry Project Manager dans le projet. Pour plus d’informations, consultez Déployer un agent hébergé.

Déployer avec Azure Developer CLI

Le langchain-azure-ai référentiel source inclut des exemples d’agents hébergés que vous pouvez exécuter et déployer à l’aide de l’interface CLI Azure développeur. Le flux utilise les azure.yaml, Dockerfile et main.py de chaque échantillon. Pour plus d’informations sur la configuration de l’agent hébergé, azure.yamlconsultez Author azure.yaml pour les agents hébergés.

Installez l’extension de l’agent AI et connectez-vous avant d’initialiser un exemple :

azd ext install azure.ai.agents
azd auth login

Docker doit s’exécuter localement, car azd ai agent run génère l’image conteneur déclarée dans le fichier Dockerfile de l’exemple. Pour plus de détails sur la commande, consultez la documentation de référence de Azure Developer CLI.

Initialiser à partir d’un exemple azure.yaml

Créez un dossier et initialisez-le à partir d’un exemple azure.yaml. Remplacez l’URL par l’exemple azure.yaml que vous souhaitez utiliser.

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

Suivez les instructions affichées par azd ai agent init. Si vous n’avez pas encore de déploiement de projet et de modèle Foundry, le flux d’initialisation peut vous guider tout au long de leur création.

Exécutez localement le conteneur

Exécutez l’hôte de l’agent localement via azd:

azd ai agent run

L’hôte fonctionne sur http://127.0.0.1:8088. Dans un autre terminal, appelez directement le point de terminaison de protocole local :

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

Équivalent PowerShell :

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

Vous pouvez également appeler l’agent local via azd:

azd ai agent invoke --local "Hello!"

Déployer sur Foundry

Si le projet initialisé utilise un nouveau projet foundry et un déploiement de modèle, approvisionnez d’abord les ressources Azure :

azd provision

Déployez l’agent :

azd deploy

Le déploiement place l’assistant dans une image de conteneur, publie cette image dans le registre de conteneurs provisionné et la déploie dans l’environnement d’exécution de l’assistant hébergé de Foundry.

L’infrastructure d’hébergement Foundry injecte des variables d’environnement runtime dans l’agent, notamment :

  • FOUNDRY_PROJECT_ENDPOINT: URL du point de terminaison du projet Foundry où l’agent est déployé.
  • FOUNDRY_MODEL_NAME: nom de déploiement du modèle sélectionné pendant azd ai agent init.
  • APPLICATIONINSIGHTS_CONNECTION_STRING : chaîne de connexion de l'instance Application Insights du projet.

Pour obtenir des concepts de déploiement complets, des autorisations et des détails de gestion, consultez Déployer un agent hébergé et gérer le cycle de vie de l’agent hébergé.

Déployer avec l’extension Foundry Toolkit pour Visual Studio Code

Pour le déploiement basé sur l’extension, consultez Démarrage rapide : Déployer votre premier agent hébergé.

Héberger un agent existant

Si votre application fonctionne déjà avec LangSmith ou l’interface CLI LangGraph, utilisez le langchain_azure_ai.agents.hosting.run module pour héberger en toute transparence l’agent sur Foundry sans modifier son code ou sa configuration.

À partir de la racine du projet, démarrez un hôte Réponses :

python -m langchain_azure_ai.agents.hosting.run --protocol responses

Pour exposer le même graphe via le protocole Invocations, définissez --protocol sur invocations. Si langgraph.json définit plusieurs graphes, passez le nom du graphe en premier argument. Utilisez --config <path> si le fichier de configuration n’est pas au chemin d’accès par défaut langgraph.json . Par exemple:

python -m langchain_azure_ai.agents.hosting.run agent --protocol invocations

Utilisez la même commande de module que le point d’entrée du conteneur lorsque vous déployez l’application existante sur Foundry.

Par exemple, configurez la commande dans azure.yaml. Le paramètre principal est le point d’entrée.

services:
  my-agent:
    host: azure.ai.agent
    kind: hosted
    codeConfiguration:
      runtime: python_3_13
      entryPoint: '-m langchain_azure_ai.agents.hosting.run --protocol responses'
      ...
    ...

Résolution des problèmes

Utilisez cette liste de contrôle pour diagnostiquer les problèmes courants lors du développement d’agents hébergés avec langchain_azure_ai.agents.hosting.

Échec de la validation du schéma graph

Les hôtes par défaut s’attendent à un graphique LangGraph compilé dont l’état a un messages champ, tel que MessagesState. Si votre graphique utilise un schéma d’état personnalisé, sous-classez l’hôte et remplacez build_input. Pour les réponses, remplacez handle_create quand vous avez besoin d’un contrôle total sur l’analyse des requêtes, l’exécution de graphiques et les événements Réponses émis.

L’état de la conversation ne se poursuit pas

Pour le protocole Responses, transmettez previous_response_id ou un ID conversation lors des tours suivants. Si votre graphique utilise un point de contrôle, vérifiez que le point de contrôle est configuré et durable pour l’environnement dans lequel l’agent s’exécute.

Pour le protocole Invocations, la plateforme ne stocke pas l’historique des conversations. Utilisez un paramètre de requête agent_session_id pour acheminer les appels ultérieurs vers le même bac à sable hébergé, et utilisez votre propre magasin d’état ou le point de contrôle LangGraph pour gérer l’état de la conversation.

Impossible d’atteindre le modèle dans le conteneur hébergé

Vérifiez que la version de l’agent hébergé inclut FOUNDRY_MODEL_NAMEet que l’identité de l’agent est autorisée à appeler le projet Foundry. La plateforme définit FOUNDRY_PROJECT_ENDPOINT ; votre code doit lire cette variable lors de son exécution dans Foundry.

Étape suivante