Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Este tutorial demonstra como criar aplicativos cliente e servidor usando o protocolo AG-UI com o Agent Framework. Você aprenderá a hospedar um agente por trás de um ponto de extremidade AG-UI e conectar um cliente para conversas interativas.
O que você construirá
Ao final deste tutorial, você terá:
- Um servidor AG-UI que hospeda um agente de IA acessível via HTTP
- Um aplicativo cliente que se conecta ao servidor e transmite respostas
- Noções básicas de como o protocolo AG-UI funciona com o Agent Framework
Pré-requisitos
- .NET 8 ou posterior
- Um projeto de ASP.NET Core
- Um MAF configurado
AIAgent
O exemplo usa Azure OpenAI, mas MapAGUIServer funciona com qualquer agente do MAF.
Criar um servidor AG-UI
Instale o pacote de hospedagem:
dotnet add package Microsoft.Agents.AI.Hosting.AGUI.AspNetCore --prerelease
Registre AG-UI hospedagem e mapeie seu agente:
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.Hosting.AGUI.AspNetCore;
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
builder.Services.AddAGUIServer();
AIAgent agent = CreateAgent();
WebApplication app = builder.Build();
app.MapAGUIServer("/", agent);
await app.RunAsync();
MapAGUIServer aceita AG-UI RunAgentInput solicitações e transmite a resposta do agente como eventos AG-UI por meio de eventos enviados pelo servidor (SSE).
Execute o servidor na URL usada pelo exemplo do cliente:
dotnet run --urls http://localhost:8888
Dica
Consulte o .NET exemplo de introdução para um cliente de console e servidor completo.
Conectar-se com um cliente .NET
O SDK do AG-UI .NET forneceAGUIChatClient, que implementa IChatClient e pode ser adaptado a um agente MAF:
dotnet add package AGUI.Client --prerelease
dotnet add package Microsoft.Agents.AI --prerelease
using AGUI.Abstractions;
using AGUI.Client;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
using HttpClient httpClient = new() { BaseAddress = new Uri("http://localhost:8888") };
AGUIChatClient chatClient = new(new AGUIChatClientOptions(httpClient, "/"));
AIAgent remoteAgent = chatClient.AsAIAgent();
AgentSession session = await remoteAgent.CreateSessionAsync();
List<AgentResponseUpdate> firstTurnUpdates = [];
await foreach (AgentResponseUpdate update in
remoteAgent.RunStreamingAsync("Hello", session))
{
firstTurnUpdates.Add(update);
foreach (TextContent text in update.Contents.OfType<TextContent>())
{
Console.Write(text.Text);
}
}
Você também pode se conectar a qualquer cliente que implemente o protocolo AG-UI.
Continuidade da conversa
AG-UI usa threadId e parentRunId para identificar solicitações de continuação. Esses identificadores são dados de protocolo, não credenciais de autorização.
AGUIChatClient é sem estado. Para continuar uma conversa de propriedade do servidor, obtenha os identificadores da primeira curva RunStartedEvente, em seguida, inclua o mesmo threadId e o anterior parentRunIdrunId da próxima solicitação:
RunStartedEvent started = firstTurnUpdates
.Select(update => update.AsChatResponseUpdate().RawRepresentation)
.OfType<RunStartedEvent>()
.FirstOrDefault()
?? throw new InvalidOperationException("The server didn't return a run-started event.");
ChatMessage nextMessage = new(ChatRole.User, "What did I just say?");
ChatClientAgentRunOptions continuationOptions = new()
{
ChatOptions = new ChatOptions
{
RawRepresentationFactory = _ => new RunAgentInput
{
ThreadId = started.ThreadId,
ParentRunId = started.RunId,
Messages = new[] { nextMessage }.AsAGUIMessages().ToList(),
},
},
};
await foreach (AgentResponseUpdate update in
remoteAgent.RunStreamingAsync([nextMessage], session, continuationOptions))
{
// Process the continued response.
}
Envie apenas as novas mensagens em uma solicitação de continuação.
MapAGUIServer usa threadId para selecionar a sessão do agente hospedado e parentRunId identificar a execução que está sendo continuada. Sem persistência de sessão hospedada, cada solicitação recebe uma nova sessão de servidor; em vez disso, o cliente pode reenviar o histórico de conversas.
Para manter o estado de propriedade AgentSession do servidor entre solicitações, configure a persistência e o isolamento da sessão hospedada e mapeie o agente hospedado nomeado com MapAGUIServer. Para obter o limite de confiança específico do AG-UI, consulte considerações sobre produção e segurança.
Próximas Etapas
Recursos relacionados
Pré-requisitos
Antes de começar, verifique se você tem o seguinte:
- Python 3.10 ou posterior
- Ponto de extremidade do serviço Azure OpenAI e implantação configurada
- CLI do Azure instalada e autenticada
- O usuário tem o papel
Cognitive Services OpenAI Contributorpara o recurso do Azure OpenAI
Note
Esses exemplos usam modelos do Azure OpenAI. Para obter mais informações, confira como implantar modelos do Azure OpenAI com o Foundry.
Note
Esses exemplos usam DefaultAzureCredential para autenticação. Verifique se você está autenticado com o Azure (por exemplo, via az login). Para obter mais informações, consulte a documentação da Identidade do Azure.
Warning
O protocolo AG-UI ainda está em desenvolvimento e está sujeito a alterações. Manteremos essas amostras atualizadas à medida que o protocolo evoluir.
Etapa 1: Criando um servidor AG-UI
O servidor AG-UI hospeda seu agente de IA e o disponibiliza através de endpoints HTTP usando FastAPI.
Instalar pacotes necessários
Instale os pacotes necessários para o servidor:
pip install agent-framework-ag-ui --pre
Ou usando uv:
uv pip install agent-framework-ag-ui --prerelease=allow
Isso instalará automaticamente agent-framework-core, fastapi, uvicorn e sse-starlette como dependências.
Código do servidor
Crie um arquivo chamado server.py:
"""AG-UI server example."""
import os
from agent_framework import Agent
from agent_framework.openai import OpenAIChatCompletionClient
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_CHAT_COMPLETION_MODEL")
if not endpoint:
raise ValueError("AZURE_OPENAI_ENDPOINT environment variable is required")
if not deployment_name:
raise ValueError("AZURE_OPENAI_CHAT_COMPLETION_MODEL environment variable is required")
chat_client = OpenAIChatCompletionClient(
model=deployment_name,
azure_endpoint=endpoint,
api_version=os.getenv("AZURE_OPENAI_API_VERSION"),
credential=AzureCliCredential(),
)
# Create the AI agent
agent = Agent(
name="AGUIAssistant",
instructions="You are a helpful assistant.",
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)
Conceitos-chave
-
add_agent_framework_fastapi_endpoint: registra o endpoint AG-UI com gerenciamento automático de solicitações/respostas e streaming de SSE -
Agent: o agente do Agent Framework que lidará com solicitações de entrada - Integração do FastAPI: usa o suporte assíncrono nativo do FastAPI para respostas de streaming
- Instruções: O agente é criado com instruções padrão, que podem ser substituídas por mensagens de cliente
-
Configuração:
OpenAIChatCompletionClientaceita entradas explícitas de roteamento do Azure, comomodel,azure_endpoint,api_version, ecredential, e também pode ler de variáveis do ambiente
Configurar e executar o servidor
Defina as variáveis de ambiente necessárias:
export AZURE_OPENAI_ENDPOINT="https://your-resource.openai.azure.com/"
export AZURE_OPENAI_CHAT_COMPLETION_MODEL="gpt-4o-mini"
Execute o servidor:
python server.py
Ou usando o uvicorn diretamente:
uvicorn server:app --host 127.0.0.1 --port 8888
O servidor começará a escutar em http://127.0.0.1:8888.
Etapa 2: Criando um cliente AG-UI
O cliente AG-UI se conecta ao servidor remoto e exibe respostas de streaming.
Instalar pacotes necessários
O pacote AG-UI já está instalado, o que inclui :AGUIChatClient
# Already installed with agent-framework-ag-ui
pip install agent-framework-ag-ui --pre
Código do cliente
Crie um arquivo chamado 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(endpoint=server_url)
# Create agent with the chat client
agent = Agent(
name="ClientAgent",
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())
Conceitos-chave
-
Server-Sent Events (SSE): o protocolo usa o formato SSE (
data: {json}\n\n) -
Tipos de evento: eventos diferentes fornecem metadados e conteúdo (UPPERCASE com sublinhados):
-
RUN_STARTED: o agente iniciou o processamento -
TEXT_MESSAGE_START: início de uma mensagem de texto do agente -
TEXT_MESSAGE_CONTENT: texto incremental transmitido do agente (com o campodelta) -
TEXT_MESSAGE_END: fim de uma mensagem de texto -
RUN_FINISHED: conclusão bem-sucedida -
RUN_ERROR: informações de erro
-
-
Nomenclatura de campo: os campos de evento usam camelCase (por exemplo, ,
threadId,runId,messageId) -
Gerenciamento de threads: o
threadIdmantém o contexto da conversa entre solicitações - Instruções do lado do cliente: as mensagens do sistema são enviadas do cliente
Configurar e executar o cliente
Opcionalmente, defina uma URL de servidor personalizada:
export AGUI_SERVER_URL="http://127.0.0.1:8888/"
Execute o cliente (em um terminal separado):
python client.py
Etapa 3: Testando o sistema completo
Com o servidor e o cliente em execução, agora você pode testar o sistema completo.
Saída 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
Saída Codificada por Cores
O cliente exibe diferentes tipos de conteúdo com cores distintas:
- Amarelo: executar notificações iniciadas
- Ciano: Respostas de texto do agente (transmitidas em tempo real)
- Verde: executar notificações de conclusão
- Vermelho: Mensagens de erro
Testando com curl (opcional)
Antes de executar o cliente, você pode testar o servidor manualmente usando 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?"}
]
}'
Você vai ver Server-Sent Events sendo transmitidos de volta.
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":"..."}
Para um fluxo inativo, curl também pode exibir linhas de comentário : keepalive. Estes são comentários de transporte SSE, não eventos AG-UI.
Como funciona
Fluxo do Lado do Servidor
- Cliente envia solicitação HTTP POST com mensagens
- O endpoint do FastAPI recebe a solicitação
-
AgentFrameworkAgentwrapper orquestra a execução - O agente processa as mensagens usando o Agent Framework
-
AgentFrameworkEventBridgeconverte atualizações de agente em eventos de AG-UI - As respostas são transmitidas como Eventos Enviados pelo Servidor (SSE)
- A conexão é fechada quando a execução é concluída
Fluxo de Client-Side
- O cliente envia solicitação HTTP POST para o ponto de extremidade do servidor
- O servidor responde com o fluxo SSE
- O cliente analisa as linhas de entrada
data:como eventos JSON - Cada evento é exibido com base em seu tipo
-
threadIdé capturado para continuidade da conversa - O fluxo é concluído quando o evento
RUN_FINISHEDchega
Detalhes do protocolo
O protocolo AG-UI usa:
- HTTP POST para enviar solicitações
- Server-Sent Events (SSE) para respostas de streaming
- JSON para serialização de eventos
- IDs de thread para manter o contexto de conversação
- Executar IDs para acompanhar execuções individuais
- Nomenclatura de tipo de evento: UPPERCASE com sublinhados (por exemplo,
RUN_STARTED,TEXT_MESSAGE_CONTENT) - Nomenclatura de campo: camelCase (por exemplo,
threadId,runId,messageId) - A SSE envia comentários de manutenção da conexão a cada 15 segundos enquanto o fluxo estiver inativo. Os clientes que processam apenas
data:linhas ignoram esses comentários automaticamente.
Padrões comuns
Configuração do 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",
keepalive_seconds=30, # Defaults to 15; set to None to disable
)
keepalive_seconds deve ser um número positivo ou None.
Vários 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")
Tratamento de erros
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}")
Troubleshooting
Conexão recusada
Verifique se o servidor está em execução antes de iniciar o cliente:
# Terminal 1
python server.py
# Terminal 2 (after server starts)
python client.py
Erros de autenticação
Verifique se você está autenticado com o Azure:
az login
Verifique se você tem a atribuição de função correta no recurso do Azure OpenAI.
Streaming não funcionando
Verifique se o tempo limite configurado para o cliente é adequado.
httpx.AsyncClient(timeout=60.0) # 60 seconds should be enough
Para agentes de longa execução, aumente o tempo limite correspondentemente.
As streams ociosas emitem um comentário de keepalive SSE a cada 15 segundos, por padrão. Se um proxy fechar conexões ociosas mais cedo, configure um valor positivo keepalive_seconds menor ao registrar o ponto de extremidade.
Contexto de thread perdido
O cliente gerencia automaticamente a continuidade do thread. Se o contexto for perdido:
- Verifique se
threadIdestá sendo capturado deRUN_STARTEDeventos - Verifique se a mesma instância do cliente é usada entre mensagens
- Verifique se o servidor está recebendo o
thread_idem solicitações subsequentes
Próximas etapas
Agora que você entende as noções básicas do AG-UI, você pode:
- Adicionar ferramentas de back-end: criar ferramentas de função personalizadas para seu domínio
Recursos adicionais
Go oferece suporte à AG-UI por meio de provider/aguiprovider para ambos os servidores e clientes.
import "github.com/microsoft/agent-framework-go/provider/aguiprovider"
mux := http.NewServeMux()
mux.Handle("/", aguiprovider.NewJSONHTTPHandler(myAgent, aguiprovider.HandlerConfig{}))
if err := http.ListenAndServe(":8888", mux); err != nil {
log.Fatal(err)
}
Use aguiprovider.NewAgent quando seu aplicativo Go precisar chamar um servidor AG-UI como um agente:
import aguiSSEClient "github.com/ag-ui-protocol/ag-ui/sdks/community/go/pkg/client/sse"
a := aguiprovider.NewAgent(
aguiSSEClient.NewClient(aguiSSEClient.Config{Endpoint: serverURL}),
aguiprovider.AgentConfig{},
)
Dica
Consulte os exemplos de servidor de primeiros passos do AG-UI e de cliente para ver exemplos completos e executáveis.