Partager via


Prise en main de AG-UI

Ce tutoriel montre comment générer à la fois des applications serveur et client à l’aide du protocole AG-UI avec .NET ou Python et Agent Framework. Vous allez apprendre à créer un serveur AG-UI qui héberge un agent IA et un client qui s’y connecte pour des conversations interactives.

Ce que vous allez construire

À la fin de ce tutoriel, vous disposez des points suivants :

  • Un serveur AG-UI hébergeant un agent IA accessible via HTTP
  • Application cliente qui se connecte au serveur et diffuse des réponses
  • Compréhension du fonctionnement du protocole AG-UI avec Agent Framework

Prerequisites

Avant de commencer, vérifiez que vous disposez des éléments suivants :

Note

Ces exemples utilisent des modèles Azure OpenAI. Pour plus d’informations, consultez comment déployer des modèles Azure OpenAI avec Azure AI Foundry.

Note

Ces exemples utilisent DefaultAzureCredential pour l’authentification. Vérifiez que vous êtes authentifié auprès d’Azure (par exemple, via az login). Pour plus d’informations, consultez la documentation d’Azure Identity.

Avertissement

Le protocole AG-UI est toujours en cours de développement et peut être modifié. Nous allons conserver ces exemples mis à jour à mesure que le protocole évolue.

Étape 1 : Création d’un serveur AG-UI

Le serveur AG-UI héberge votre agent IA et l’expose via des points de terminaison HTTP à l’aide de ASP.NET Core.

Note

Le projet de serveur nécessite le Microsoft.NET.Sdk.Web Kit de développement logiciel (SDK). Si vous créez un projet à partir de zéro, utilisez dotnet new web ou vérifiez que votre .csproj fichier utilise <Project Sdk="Microsoft.NET.Sdk.Web"> au lieu de Microsoft.NET.Sdk.

Installer les packages requis

Installez les packages nécessaires pour le serveur :

dotnet add package Microsoft.Agents.AI.Hosting.AGUI.AspNetCore --prerelease
dotnet add package Azure.AI.OpenAI --prerelease
dotnet add package Azure.Identity
dotnet add package Microsoft.Extensions.AI.OpenAI --prerelease

Note

Le Microsoft.Extensions.AI.OpenAI package est requis pour la méthode d'extension AsIChatClient() qui convertit ChatClient d'OpenAI en l'interface IChatClient attendue par Agent Framework.

Code du serveur

Créez un fichier nommé Program.cs:

// Copyright (c) Microsoft. All rights reserved.

using Azure.AI.OpenAI;
using Azure.Identity;
using Microsoft.Agents.AI.Hosting.AGUI.AspNetCore;
using Microsoft.Extensions.AI;
using OpenAI.Chat;

WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpClient().AddLogging();
builder.Services.AddAGUI();

WebApplication app = builder.Build();

string endpoint = builder.Configuration["AZURE_OPENAI_ENDPOINT"]
    ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
string deploymentName = builder.Configuration["AZURE_OPENAI_DEPLOYMENT_NAME"]
    ?? throw new InvalidOperationException("AZURE_OPENAI_DEPLOYMENT_NAME is not set.");

// Create the AI agent
ChatClient chatClient = new AzureOpenAIClient(
        new Uri(endpoint),
        new DefaultAzureCredential())
    .GetChatClient(deploymentName);

AIAgent agent = chatClient.AsIChatClient().AsAIAgent(
    name: "AGUIAssistant",
    instructions: "You are a helpful assistant.");

// Map the AG-UI agent endpoint
app.MapAGUI("/", agent);

await app.RunAsync();

Concepts clés

  • AddAGUI : enregistre les services AG-UI auprès du conteneur d’injection de dépendances
  • MapAGUI: méthode d'extension qui enregistre l'endpoint AG-UI avec la gestion automatique des requêtes/réponses et les événements émis par le serveur (SSE) en continu
  • ChatClient et AsIChatClient(): AzureOpenAIClient.GetChatClient() retourne le type d’OpenAI ChatClient . La AsIChatClient() méthode d’extension (de Microsoft.Extensions.AI.OpenAI) la convertit en interface IChatClient requise par Agent Framework
  • AsAIAgent: crée un agent Agent Framework à partir d’un IChatClient
  • intégration ASP.NET Core : utilise la prise en charge asynchrone native d'ASP.NET Core pour les réponses en flux
  • Instructions : l’agent est créé avec des instructions par défaut, qui peuvent être remplacées par des messages clients
  • Configuration : AzureOpenAIClient avec DefaultAzureCredential fournit une authentification sécurisée

Configurer et exécuter le serveur

Définissez les variables d’environnement requises :

export AZURE_OPENAI_ENDPOINT="https://your-resource.openai.azure.com/"
export AZURE_OPENAI_DEPLOYMENT_NAME="gpt-4o-mini"

Exécutez le serveur :

dotnet run --urls http://localhost:8888

Le serveur va commencer à écouter http://localhost:8888.

Note

Maintenez ce serveur en cours d’exécution pendant la configuration et l’exécution du client à l’étape 2. Le serveur et le client doivent s’exécuter simultanément pour que le système complet fonctionne.

Étape 2 : Création d’un client AG-UI

Le client AG-UI se connecte au serveur distant et affiche les réponses en streaming.

Important

Avant d’exécuter le client, vérifiez que le serveur AG-UI de l’étape 1 est en cours d’exécution à http://localhost:8888.

Installer les packages requis

Installez la bibliothèque de client AG-UI :

dotnet add package Microsoft.Agents.AI.AGUI --prerelease
dotnet add package Microsoft.Agents.AI --prerelease

Note

Le Microsoft.Agents.AI package fournit la méthode d’extension AsAIAgent() .

Client Code

Créez un fichier nommé Program.cs:

// Copyright (c) Microsoft. All rights reserved.

using Microsoft.Agents.AI;
using Microsoft.Agents.AI.AGUI;
using Microsoft.Extensions.AI;

string serverUrl = Environment.GetEnvironmentVariable("AGUI_SERVER_URL") ?? "http://localhost:8888";

Console.WriteLine($"Connecting to AG-UI server at: {serverUrl}\n");

// Create the AG-UI client agent
using HttpClient httpClient = new()
{
    Timeout = TimeSpan.FromSeconds(60)
};

AGUIChatClient chatClient = new(httpClient, serverUrl);

AIAgent agent = chatClient.AsAIAgent(
    name: "agui-client",
    description: "AG-UI Client Agent");

AgentSession session = await agent.CreateSessionAsync();
List<ChatMessage> messages =
[
    new(ChatRole.System, "You are a helpful assistant.")
];

try
{
    while (true)
    {
        // Get user input
        Console.Write("\nUser (:q or quit to exit): ");
        string? message = Console.ReadLine();

        if (string.IsNullOrWhiteSpace(message))
        {
            Console.WriteLine("Request cannot be empty.");
            continue;
        }

        if (message is ":q" or "quit")
        {
            break;
        }

        messages.Add(new ChatMessage(ChatRole.User, message));

        // Stream the response
        bool isFirstUpdate = true;
        string? threadId = null;

        await foreach (AgentResponseUpdate update in agent.RunStreamingAsync(messages, session))
        {
            ChatResponseUpdate chatUpdate = update.AsChatResponseUpdate();

            // First update indicates run started
            if (isFirstUpdate)
            {
                threadId = chatUpdate.ConversationId;
                Console.ForegroundColor = ConsoleColor.Yellow;
                Console.WriteLine($"\n[Run Started - Thread: {chatUpdate.ConversationId}, Run: {chatUpdate.ResponseId}]");
                Console.ResetColor();
                isFirstUpdate = false;
            }

            // Display streaming text content
            foreach (AIContent content in update.Contents)
            {
                if (content is TextContent textContent)
                {
                    Console.ForegroundColor = ConsoleColor.Cyan;
                    Console.Write(textContent.Text);
                    Console.ResetColor();
                }
                else if (content is ErrorContent errorContent)
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine($"\n[Error: {errorContent.Message}]");
                    Console.ResetColor();
                }
            }
        }

        Console.ForegroundColor = ConsoleColor.Green;
        Console.WriteLine($"\n[Run Finished - Thread: {threadId}]");
        Console.ResetColor();
    }
}
catch (Exception ex)
{
    Console.WriteLine($"\nAn error occurred: {ex.Message}");
}

Concepts clés

  • Server-Sent Events (SSE) : le protocole utilise SSE pour les réponses de diffusion en continu
  • AGUIChatClient : classe cliente qui se connecte aux serveurs AG-UI et implémente IChatClient
  • AsAIAgent: Méthode d'extension sur AGUIChatClient pour créer un agent à partir du client
  • RunStreamingAsync : Diffuse des réponses en tant qu’objets AgentResponseUpdate
  • AsChatResponseUpdate : méthode d’extension pour accéder aux propriétés spécifiques à la conversation telles que ConversationId et ResponseId
  • Gestion des sessions : le AgentSession maintient le contexte de conversation à travers les requêtes
  • Types de contenu : les réponses incluent TextContent les messages et ErrorContent les erreurs

Configurer et exécuter le client

Définissez éventuellement une URL de serveur personnalisée :

export AGUI_SERVER_URL="http://localhost:8888"

Exécutez le client dans un terminal distinct (vérifiez que le serveur de l’étape 1 est en cours d’exécution) :

dotnet run

Étape 3 : Tester le système complet

Avec le serveur et le client en cours d’exécution, vous pouvez maintenant tester le système complet.

Sortie attendue

$ dotnet run
Connecting to AG-UI server at: http://localhost:8888

User (:q or quit to exit): What is 2 + 2?

[Run Started - Thread: thread_abc123, Run: run_xyz789]
2 + 2 equals 4.
[Run Finished - Thread: thread_abc123]

User (:q or quit to exit): Tell me a fun fact about space

[Run Started - Thread: thread_abc123, Run: run_def456]
Here's a fun fact: A day on Venus is longer than its year! Venus takes
about 243 Earth days to rotate once on its axis, but only about 225 Earth
days to orbit the Sun.
[Run Finished - Thread: thread_abc123]

User (:q or quit to exit): :q

Sortie Codée par Couleur

Le client affiche différents types de contenu avec des couleurs distinctes :

  • Jaune : Exécuter les notifications démarrées
  • Cyan : Réponses de texte de l’agent (diffusées en temps réel)
  • Vert : Notifications d’exécution
  • Rouge : Messages d’erreur

Fonctionnement

flux du côté serveur

  1. Le client envoie une requête HTTP POST avec des messages
  2. Le point de terminaison ASP.NET Core reçoit la demande via MapAGUI
  3. Agent traite les messages à l’aide d’Agent Framework
  4. Les réponses sont converties en événements AG-UI
  5. Les événements sont transmis en continu en tant que Server-Sent Events (SSE)
  6. La connexion se ferme une fois l’exécution terminée

Flux Côté Client

  1. AGUIChatClient envoie une requête HTTP POST au point de terminaison du serveur
  2. Le serveur répond avec le flux SSE
  3. Le client analyse les événements entrants en AgentResponseUpdate objets
  4. Chaque mise à jour s’affiche en fonction de son type de contenu
  5. ConversationId est capturé pour la continuité des conversations
  6. Le flux se termine lorsque l'exécution se termine

Détails du protocole

Le protocole AG-UI utilise :

  • HTTP POST pour l’envoi de requêtes
  • Événements émis par le serveur (SSE) pour les réponses en streaming
  • JSON pour la sérialisation d’événements
  • ID de thread (en tant que ConversationId) pour la maintenance du contexte de conversation
  • ID d'exécution (en tant que ResponseId) pour le suivi des exécutions individuelles

Étapes suivantes

Maintenant que vous comprenez les principes de base de l'AG-UI, vous pouvez :

Ressources additionnelles

Prerequisites

Avant de commencer, vérifiez que vous disposez des éléments suivants :

Note

Ces exemples utilisent des modèles Azure OpenAI. Pour plus d’informations, consultez comment déployer des modèles Azure OpenAI avec Azure AI Foundry.

Note

Ces exemples utilisent DefaultAzureCredential pour l’authentification. Vérifiez que vous êtes authentifié auprès d’Azure (par exemple, via az login). Pour plus d’informations, consultez la documentation d’Azure Identity.

Avertissement

Le protocole AG-UI est toujours en cours de développement et peut être modifié. Nous allons conserver ces exemples mis à jour à mesure que le protocole évolue.

Étape 1 : Création d’un serveur AG-UI

Le serveur AG-UI héberge votre agent IA et l’expose via des points de terminaison HTTP à l’aide de FastAPI.

Installer les packages requis

Installez les packages nécessaires pour le serveur :

pip install agent-framework-ag-ui --pre

Ou en utilisant UV :

uv pip install agent-framework-ag-ui --prerelease=allow

Cela installe agent-framework-coreautomatiquement , fastapiet uvicorn en tant que dépendances.

Code du serveur

Créez un fichier nommé server.py:

"""AG-UI server example."""

import os

from agent_framework import Agent
from agent_framework.azure import AzureOpenAIChatClient
from agent_framework_ag_ui import add_agent_framework_fastapi_endpoint
from azure.identity import AzureCliCredential
from fastapi import FastAPI

# Read required configuration
endpoint = os.environ.get("AZURE_OPENAI_ENDPOINT")
deployment_name = os.environ.get("AZURE_OPENAI_DEPLOYMENT_NAME")

if not endpoint:
    raise ValueError("AZURE_OPENAI_ENDPOINT environment variable is required")
if not deployment_name:
    raise ValueError("AZURE_OPENAI_DEPLOYMENT_NAME environment variable is required")

chat_client = AzureOpenAIChatClient(
    credential=AzureCliCredential(),
    endpoint=endpoint,
    deployment_name=deployment_name,
)

# Create the AI agent
agent = Agent(
    name="AGUIAssistant",
    instructions="You are a helpful assistant.",
    chat_client=chat_client,
)

# Create FastAPI app
app = FastAPI(title="AG-UI Server")

# Register the AG-UI endpoint
add_agent_framework_fastapi_endpoint(app, agent, "/")

if __name__ == "__main__":
    import uvicorn

    uvicorn.run(app, host="127.0.0.1", port=8888)

Concepts clés

  • add_agent_framework_fastapi_endpoint: enregistre le point de terminaison AG-UI incluant la gestion automatique des demandes/réponses et la diffusion en continu SSE
  • Agent: Agent Framework qui gère les demandes entrantes
  • Intégration de FastAPI : utilise la prise en charge asynchrone native de FastAPI pour les réponses de streaming
  • Instructions : l’agent est créé avec des instructions par défaut, qui peuvent être remplacées par des messages clients
  • Configuration : AzureOpenAIChatClient lit à partir de variables d’environnement ou accepte directement les paramètres

Configurer et exécuter le serveur

Définissez les variables d’environnement requises :

export AZURE_OPENAI_ENDPOINT="https://your-resource.openai.azure.com/"
export AZURE_OPENAI_DEPLOYMENT_NAME="gpt-4o-mini"

Exécutez le serveur :

python server.py

Ou en utilisant directement uvicorn :

uvicorn server:app --host 127.0.0.1 --port 8888

Le serveur va commencer à écouter http://127.0.0.1:8888.

Étape 2 : Création d’un client AG-UI

Le client AG-UI se connecte au serveur distant et affiche les réponses en streaming.

Installer les packages requis

Le package AG-UI est déjà installé, ce qui inclut les AGUIChatClientéléments suivants :

# Already installed with agent-framework-ag-ui
pip install agent-framework-ag-ui --pre

Client Code

Créez un fichier nommé client.py:

"""AG-UI client example."""

import asyncio
import os

from agent_framework import Agent
from agent_framework_ag_ui import AGUIChatClient


async def main():
    """Main client loop."""
    # Get server URL from environment or use default
    server_url = os.environ.get("AGUI_SERVER_URL", "http://127.0.0.1:8888/")
    print(f"Connecting to AG-UI server at: {server_url}\n")

    # Create AG-UI chat client
    chat_client = AGUIChatClient(server_url=server_url)

    # Create agent with the chat client
    agent = Agent(
        name="ClientAgent",
        chat_client=chat_client,
        instructions="You are a helpful assistant.",
    )

    # Get a thread for conversation continuity
    thread = agent.create_session()

    try:
        while True:
            # Get user input
            message = input("\nUser (:q or quit to exit): ")
            if not message.strip():
                print("Request cannot be empty.")
                continue

            if message.lower() in (":q", "quit"):
                break

            # Stream the agent response
            print("\nAssistant: ", end="", flush=True)
            async for update in agent.run(message, session=thread, stream=True):
                # Print text content as it streams
                if update.text:
                    print(f"\033[96m{update.text}\033[0m", end="", flush=True)

            print("\n")

    except KeyboardInterrupt:
        print("\n\nExiting...")
    except Exception as e:
        print(f"\n\033[91mAn error occurred: {e}\033[0m")


if __name__ == "__main__":
    asyncio.run(main())

Concepts clés

  • Server-Sent Events (SSE) : le protocole utilise le format SSE (data: {json}\n\n)
  • Types d’événements : différents événements fournissent des métadonnées et du contenu (MAJUSCULES soulignées) :
    • RUN_STARTED: l’agent a démarré le traitement
    • TEXT_MESSAGE_START: Début d’un message texte de l’agent
    • TEXT_MESSAGE_CONTENT: texte incrémentiel diffusé par l'agent (avec le champ delta)
    • TEXT_MESSAGE_END: Fin d’un sms
    • RUN_FINISHED:Achèvement réussi
    • RUN_ERROR: Informations sur l’erreur
  • Nommage de champ : les champs d’événement utilisent camelCase (par exemple, threadId, runId, messageId)
  • Gestion des threads : le threadId contextualise le contexte de conversation entre les demandes
  • Client-Side Instructions : les messages système sont envoyés à partir du client

Configurer et exécuter le client

Définissez éventuellement une URL de serveur personnalisée :

export AGUI_SERVER_URL="http://127.0.0.1:8888/"

Exécutez le client (dans un terminal distinct) :

python client.py

Étape 3 : Tester le système complet

Avec le serveur et le client en cours d’exécution, vous pouvez maintenant tester le système complet.

Sortie attendue

$ python client.py
Connecting to AG-UI server at: http://127.0.0.1:8888/

User (:q or quit to exit): What is 2 + 2?

[Run Started - Thread: abc123, Run: xyz789]
2 + 2 equals 4.
[Run Finished - Thread: abc123, Run: xyz789]

User (:q or quit to exit): Tell me a fun fact about space

[Run Started - Thread: abc123, Run: def456]
Here's a fun fact: A day on Venus is longer than its year! Venus takes
about 243 Earth days to rotate once on its axis, but only about 225 Earth
days to orbit the Sun.
[Run Finished - Thread: abc123, Run: def456]

User (:q or quit to exit): :q

Sortie Codée par Couleur

Le client affiche différents types de contenu avec des couleurs distinctes :

  • Jaune : Exécuter les notifications démarrées
  • Cyan : Réponses de texte de l’agent (diffusées en temps réel)
  • Vert : Notifications d’exécution
  • Rouge : Messages d’erreur

Test avec curl (facultatif)

Avant d’exécuter le client, vous pouvez tester le serveur manuellement à l’aide de curl :

curl -N http://127.0.0.1:8888/ \
  -H "Content-Type: application/json" \
  -H "Accept: text/event-stream" \
  -d '{
    "messages": [
      {"role": "user", "content": "What is 2 + 2?"}
    ]
  }'

Vous devriez voir le flux des Server-Sent Events :

data: {"type":"RUN_STARTED","threadId":"...","runId":"..."}

data: {"type":"TEXT_MESSAGE_START","messageId":"...","role":"assistant"}

data: {"type":"TEXT_MESSAGE_CONTENT","messageId":"...","delta":"The"}

data: {"type":"TEXT_MESSAGE_CONTENT","messageId":"...","delta":" answer"}

...

data: {"type":"TEXT_MESSAGE_END","messageId":"..."}

data: {"type":"RUN_FINISHED","threadId":"...","runId":"..."}

Fonctionnement

flux du côté serveur

  1. Le client envoie une requête HTTP POST avec des messages
  2. Le point de terminaison FastAPI reçoit la requête
  3. AgentFrameworkAgent un wrapper orchestre l’exécution
  4. Agent traite les messages à l’aide d’Agent Framework
  5. AgentFrameworkEventBridge convertit les mises à jour de l’agent en événements AG-UI
  6. Les réponses sont diffusées en flux continu sous forme d'événements émis par le serveur (SSE)
  7. La connexion se ferme une fois l’exécution terminée

Flux Côté Client

  1. Le client envoie une requête HTTP POST au point de terminaison du serveur
  2. Le serveur répond avec le flux SSE
  3. Le client analyse les lignes entrantes data: en tant qu’événements JSON
  4. Chaque événement est affiché en fonction de son type
  5. threadId est capturé pour la continuité des conversations
  6. Le flux se termine lorsque l'événement RUN_FINISHED arrive.

Détails du protocole

Le protocole AG-UI utilise :

  • HTTP POST pour l’envoi de requêtes
  • Événements émis par le serveur (SSE) pour les réponses en streaming
  • JSON pour la sérialisation d’événements
  • ID de thread pour la maintenance du contexte de conversation
  • Identifiants d'exécution pour le suivi des exécutions individuelles
  • Nommage de type d’événement : UPPERCASE avec traits de soulignement (par exemple, RUN_STARTED, TEXT_MESSAGE_CONTENT)
  • Nommage de champ : camelCase (par exemple, threadId, runId, messageId)

Modèles courants

Configuration de serveur personnalisée

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

# Add CORS for web clients
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

add_agent_framework_fastapi_endpoint(app, agent, "/agent")

Agents multiples

app = FastAPI()

weather_agent = Agent(name="weather", ...)
finance_agent = Agent(name="finance", ...)

add_agent_framework_fastapi_endpoint(app, weather_agent, "/weather")
add_agent_framework_fastapi_endpoint(app, finance_agent, "/finance")

Gestion des erreurs

try:
    async for event in client.send_message(message):
        if event.get("type") == "RUN_ERROR":
            error_msg = event.get("message", "Unknown error")
            print(f"Error: {error_msg}")
            # Handle error appropriately
except httpx.HTTPError as e:
    print(f"HTTP error: {e}")
except Exception as e:
    print(f"Unexpected error: {e}")

Résolution des problèmes

Connexion refusée

Vérifiez que le serveur est en cours d’exécution avant de démarrer le client :

# Terminal 1
python server.py

# Terminal 2 (after server starts)
python client.py

Erreurs d’authentification

Vérifiez que vous êtes authentifié auprès d’Azure :

az login

Vérifiez que vous disposez de l’attribution de rôle correcte sur la ressource Azure OpenAI.

Streaming non opérationnel

Vérifiez que le temps d'attente pour votre client est suffisant.

httpx.AsyncClient(timeout=60.0)  # 60 seconds should be enough

Pour les agents fonctionnant sur de longues périodes, ajustez le délai d'attente en conséquence.

Contexte de thread perdu

Le client gère automatiquement la continuité des threads. Si le contexte est perdu :

  1. Vérifiez que threadId soit capturé à partir des événements RUN_STARTED
  2. Vérifiez que la même instance cliente est utilisée entre les messages
  3. Vérifiez que le serveur reçoit le thread_id dans les demandes suivantes

Étapes suivantes

Maintenant que vous comprenez les principes de base de l'AG-UI, vous pouvez :

Ressources additionnelles