Compartir a través de


Introducción a AG-UI

En este tutorial se muestra cómo compilar aplicaciones cliente y de servidor mediante el protocolo AG-UI con .NET o Python y Agent Framework. Aprenderá a crear un servidor de AG-UI que hospede un agente de IA y un cliente que se conecte a él para conversaciones interactivas.

Lo que vas a construir

Al final de este tutorial, tendrá lo siguiente:

  • Un servidor AG-UI que hospeda un agente de IA accesible a través de HTTP
  • Una aplicación cliente que se conecta al servidor y transmite respuestas
  • Descripción de cómo funciona el protocolo AG-UI con Agent Framework

Prerrequisitos

Antes de comenzar, asegúrese de que tiene lo siguiente:

Nota:

Estos ejemplos usan modelos de Azure OpenAI. Para más información, consulte implementación de modelos de Azure OpenAI con Azure AI Foundry.

Nota:

Estos ejemplos usan DefaultAzureCredential para la autenticación. Asegúrese de que está autenticado con Azure (por ejemplo, a través de az login). Para más información, consulte la documentación de Azure Identity.

Advertencia

El protocolo AG-UI todavía está en desarrollo y está sujeto a cambios. Mantendremos actualizados estos ejemplos a medida que evoluciona el protocolo.

Paso 1: Crear un servidor de AG-UI

El servidor AG-UI hospeda el agente de IA y lo expone a través de puntos de conexión HTTP mediante ASP.NET Core.

Nota:

El proyecto de servidor requiere el Microsoft.NET.Sdk.Web SDK. Si va a crear un nuevo proyecto desde cero, use dotnet new web o asegúrese de que el archivo .csproj use <Project Sdk="Microsoft.NET.Sdk.Web"> en lugar de Microsoft.NET.Sdk.

Instalar paquetes necesarios

Instale los paquetes necesarios para el servidor:

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

Nota:

El paquete Microsoft.Extensions.AI.OpenAI es necesario para el método de extensión AsIChatClient() que convierte el ChatClient de OpenAI en la interfaz IChatClient esperada por Agent Framework.

Código de servidor

Cree un archivo denominado 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();

Conceptos clave

  • AddAGUI: registra servicios AG-UI con el contenedor de inyección de dependencias.
  • MapAGUI: Método de extensión que registra el endpoint de AG-UI con manejo automático de solicitudes/respuestas y streaming SSE.
  • ChatClient y AsIChatClient(): AzureOpenAIClient.GetChatClient() devuelve el tipo ChatClient de OpenAI. El método de extensión AsIChatClient() (de Microsoft.Extensions.AI.OpenAI) lo convierte en la interfaz IChatClient requerida por Agent Framework.
  • AsAIAgent: crea un agente de Agent Framework a partir de un IChatClient
  • Integración de ASP.NET Core: usa la compatibilidad asincrónica nativa de ASP.NET Core para las respuestas de streaming
  • Instrucciones: el agente se crea con instrucciones predeterminadas, que los mensajes de cliente pueden invalidar.
  • Configuración: AzureOpenAIClient con DefaultAzureCredential proporciona autenticación segura

Configurar y ejecutar el servidor

Establezca las variables de entorno necesarias:

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

Ejecute el servidor:

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

El servidor comenzará a escuchar en http://localhost:8888.

Nota:

Mantenga este servidor en ejecución mientras configura y ejecuta el cliente en el paso 2. Tanto el servidor como el cliente deben ejecutarse simultáneamente para que el sistema completo funcione.

Paso 2: Crear un cliente de AG-UI

El cliente AG-UI se conecta al servidor remoto y muestra las respuestas de streaming.

Importante

Antes de ejecutar el cliente, asegúrese de que el servidor de AG-UI del paso 1 se ejecuta en http://localhost:8888.

Instalar paquetes necesarios

Instale la biblioteca cliente de AG-UI:

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

Nota:

El Microsoft.Agents.AI paquete proporciona el método de extensión AsAIAgent().

Código de cliente

Cree un archivo denominado 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}");
}

Conceptos clave

  • Server-Sent Events (SSE): el protocolo usa SSE para respuestas de streaming.
  • AGUIChatClient: clase de cliente que se conecta a servidores AG-UI e implementa IChatClient
  • AsAIAgent: método de extensión en AGUIChatClient para crear un agente desde el cliente
  • RunStreamingAsync: transmite respuestas como AgentResponseUpdate objetos
  • AsChatResponseUpdate: método de extensión para acceder a propiedades específicas del chat, como ConversationId y ResponseId
  • Administración de sesiones: AgentSession mantiene el contexto de conversación entre las solicitudes.
  • Tipos de contenido: las respuestas incluyen TextContent para mensajes y ErrorContent para errores

Configurar y ejecutar el cliente

Opcionalmente, establezca una dirección URL de servidor personalizada:

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

Ejecute el cliente en un terminal independiente (asegúrese de que el servidor del paso 1 se está ejecutando):

dotnet run

Paso 3: Probar el sistema completo

Con el servidor y el cliente en ejecución, ahora puede probar el sistema completo.

Salida esperada

$ 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

Salida codificada por colores

El cliente muestra diferentes tipos de contenido con colores distintos:

  • Amarillo: ejecutar notificaciones iniciadas
  • Cian: respuestas de texto del agente (transmitidas en tiempo real)
  • Verde: Ejecutar notificaciones de finalización
  • Rojo: mensajes de error

Funcionamiento

flujo del lado del servidor

  1. El cliente envía una solicitud HTTP POST con mensajes
  2. ASP.NET punto de conexión principal recibe la solicitud a través de MapAGUI
  3. El agente procesa los mensajes mediante Agent Framework
  4. Las respuestas se convierten en eventos de AG-UI
  5. Los eventos se transmiten como Eventos Enviados Por el Servidor (SSE)
  6. La conexión se cierra cuando se completa la ejecución

Flujo del lado del cliente

  1. AGUIChatClient envía la solicitud HTTP POST al punto de conexión del servidor
  2. El servidor responde con secuencia SSE
  3. El cliente analiza los eventos entrantes en AgentResponseUpdate objetos
  4. Cada actualización se muestra en función de su tipo de contenido.
  5. ConversationId se captura para la continuidad de la conversación
  6. El flujo se completa cuando finaliza la ejecución

Detalles del protocolo

El protocolo AG-UI usa:

  • HTTP POST para enviar solicitudes
  • Eventos Server-Sent (SSE) para respuestas en streaming
  • JSON para la serialización de eventos
  • Identificadores de hilos (como ConversationId) para conservar el contexto de la conversación
  • Ejecutar identificadores (como ResponseId) para realizar el seguimiento de ejecuciones individuales

Pasos siguientes

Ahora que comprende los conceptos básicos de AG-UI, puede hacer lo siguiente:

Recursos adicionales

Prerrequisitos

Antes de comenzar, asegúrese de que tiene lo siguiente:

Nota:

Estos ejemplos usan modelos de Azure OpenAI. Para más información, consulte implementación de modelos de Azure OpenAI con Azure AI Foundry.

Nota:

Estos ejemplos usan DefaultAzureCredential para la autenticación. Asegúrese de que está autenticado con Azure (por ejemplo, a través de az login). Para más información, consulte la documentación de Azure Identity.

Advertencia

El protocolo AG-UI todavía está en desarrollo y está sujeto a cambios. Mantendremos actualizados estos ejemplos a medida que evoluciona el protocolo.

Paso 1: Crear un servidor de AG-UI

El servidor AG-UI hospeda el agente de IA y lo expone a través de puntos de conexión HTTP mediante FastAPI.

Instalar paquetes necesarios

Instale los paquetes necesarios para el servidor:

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

O bien, usando uv:

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

Esto automáticamente instalará agent-framework-core, fastapi y uvicorn como dependencias.

Código de servidor

Cree un archivo denominado 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)

Conceptos clave

  • add_agent_framework_fastapi_endpoint: registra el punto de conexión de AG-UI con el control automático de solicitudes y respuestas y el streaming de SSE.
  • Agent: agente de Agent Framework que controlará las solicitudes entrantes.
  • Integración con FastAPI: usa la compatibilidad asincrónica nativa de FastAPI con las respuestas de streaming.
  • Instrucciones: el agente se crea con instrucciones predeterminadas, que los mensajes de cliente pueden invalidar.
  • Configuración: AzureOpenAIChatClient lee las variables de entorno o acepta parámetros directamente.

Configurar y ejecutar el servidor

Establezca las variables de entorno necesarias:

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

Ejecute el servidor:

python server.py

O bien mediante uvicorn directamente:

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

El servidor comenzará a escuchar en http://127.0.0.1:8888.

Paso 2: Crear un cliente de AG-UI

El cliente AG-UI se conecta al servidor remoto y muestra las respuestas de streaming.

Instalar paquetes necesarios

El paquete AG-UI ya está instalado, que incluye :AGUIChatClient

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

Código de cliente

Cree un archivo denominado 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())

Conceptos clave

  • Eventos Enviados por el Servidor (SSE): el protocolo utiliza el formato SSE (data: {json}\n\n)
  • Tipos de eventos: los distintos eventos proporcionan metadatos y contenido (MAYÚSCULAS con caracteres de subrayado):
    • RUN_STARTED: el agente ha iniciado el procesamiento
    • TEXT_MESSAGE_START: inicio de un mensaje de texto del agente
    • TEXT_MESSAGE_CONTENT: texto incremental transmitido desde el agente (con el campo delta)
    • TEXT_MESSAGE_END: final de un mensaje de texto
    • RUN_FINISHED: finalización correcta
    • RUN_ERROR: información de error
  • Nomenclatura de campos: los campos de evento usan camelCase (por ejemplo, threadId, runId, messageId)
  • Administración de subprocesos: El threadId mantiene el contexto de conversación entre las solicitudes.
  • Instrucciones del Cliente: Los mensajes del sistema se envían desde el cliente

Configurar y ejecutar el cliente

Opcionalmente, establezca una dirección URL de servidor personalizada:

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

Ejecute el cliente (en un terminal independiente):

python client.py

Paso 3: Probar el sistema completo

Con el servidor y el cliente en ejecución, ahora puede probar el sistema completo.

Salida esperada

$ 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

Salida codificada por colores

El cliente muestra diferentes tipos de contenido con colores distintos:

  • Amarillo: ejecutar notificaciones iniciadas
  • Cian: respuestas de texto del agente (transmitidas en tiempo real)
  • Verde: Ejecutar notificaciones de finalización
  • Rojo: mensajes de error

Pruebas con curl (opcional)

Antes de ejecutar el cliente, puede probar el servidor manualmente mediante 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?"}
    ]
  }'

Debería ver un flujo de eventos enviados por el servidor.

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":"..."}

Funcionamiento

flujo del lado del servidor

  1. El cliente envía una solicitud HTTP POST con mensajes
  2. El punto de conexión de FastAPI recibe la solicitud.
  3. AgentFrameworkAgent el envoltorio orquesta la ejecución
  4. El agente procesa los mensajes mediante Agent Framework
  5. AgentFrameworkEventBridge convierte las actualizaciones del agente en eventos de AG-UI
  6. Las respuestas se transmiten como Server-Sent Events (SSE)
  7. La conexión se cierra cuando se completa la ejecución

Flujo del lado del cliente

  1. El cliente envía la solicitud HTTP POST al punto de conexión del servidor
  2. El servidor responde con secuencia SSE
  3. El cliente analiza las líneas entrantes data: como eventos JSON
  4. Cada evento se muestra en función de su tipo.
  5. threadId se captura para la continuidad de la conversación
  6. El stream se completa cuando llega el evento RUN_FINISHED

Detalles del protocolo

El protocolo AG-UI usa:

  • HTTP POST para enviar solicitudes
  • Eventos Server-Sent (SSE) para respuestas en streaming
  • JSON para la serialización de eventos
  • Identificadores de hilos para mantener el contexto de conversación
  • Identificadores de ejecución para seguimiento de ejecuciones individuales
  • Nomenclatura de tipo de evento: UPPERCASE con caracteres de subrayado (por ejemplo, RUN_STARTED, TEXT_MESSAGE_CONTENT)
  • Nomenclatura de campos: camelCase (por ejemplo, threadId, runId, messageId)

Patrones comunes

Configuración del servidor personalizado

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

Múltiples agentes

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

Tratamiento de errores

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

Solución de problemas

Conexión rechazada

Asegúrese de que el servidor se está ejecutando antes de iniciar el cliente:

# Terminal 1
python server.py

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

Errores de autenticación

Asegúrese de que está autenticado con Azure:

az login

Compruebe que tiene la asignación de roles correcta en el recurso de Azure OpenAI.

Streaming no funciona

Compruebe que el tiempo de espera del cliente es suficiente:

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

En el caso de los agentes de larga duración, aumente el tiempo de espera en consecuencia.

Contexto de hilo perdido

El cliente controla automáticamente la continuidad del hilo. Si se pierde el contexto:

  1. Comprobación de que threadId se está capturando de RUN_STARTED eventos
  2. Asegúrese de que se usa la misma instancia de cliente en todos los mensajes.
  3. Compruebe que el servidor recibe el thread_id en las solicitudes posteriores.

Pasos siguientes

Ahora que comprende los conceptos básicos de AG-UI, puede hacer lo siguiente:

Recursos adicionales