Memulai AG-UI

Tutorial ini menunjukkan cara membangun aplikasi server dan klien menggunakan protokol AG-UI dengan Agent Framework. Anda akan mempelajari cara menjalankan agen di balik endpoint AG-UI dan menghubungkan klien agar dapat melakukan percakapan interaktif.

Apa yang akan Anda Bangun

Pada akhir tutorial ini, Anda akan memiliki:

  • Server AG-UI menghosting agen AI yang dapat diakses melalui HTTP
  • Aplikasi klien yang tersambung ke server dan mengalirkan respons
  • Memahami cara kerja protokol AG-UI dengan Agent Framework

Prasyarat

  • .NET 8 atau yang lebih baru
  • Proyek ASP.NET Core
  • MAF yang telah dikonfigurasi AIAgent

Contohnya menggunakan Azure OpenAI, tetapi MapAGUIServer berfungsi dengan agen MAF apa pun.

Membuat server AG-UI

Instal paket hosting:

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

Daftarkan hosting AG-UI dan petakan agen Anda:

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 menerima permintaan AG-UI RunAgentInput dan menyalurkan respons agen sebagai event AG-UI melalui event yang dikirim server (SSE).

Jalankan server pada URL yang digunakan oleh contoh klien:

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

Tip

Lihat sampel .NET untuk memulai penggunaan yang mencakup server lengkap dan klien konsol.

Hubungkan dengan klien .NET

SDK AG-UI .NET menyediakan AGUIChatClient, yang mengimplementasikan IChatClient dan dapat disesuaikan dengan agen 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);
    }
}

Anda juga dapat terhubung dengan klien apa pun yang menerapkan protokol AG-UI.

Kelangsungan percakapan

AG-UI menggunakan threadId dan parentRunId mengidentifikasi permintaan kelanjutan. Pengidentifikasi ini adalah data protokol, bukan kredensial otorisasi.

AGUIChatClient tidak memiliki status. Untuk melanjutkan percakapan yang dimiliki server, ambil pengidentifikasi dari RunStartedEvent giliran pertama, lalu sertakan threadId yang sama dan runId sebelumnya sebagai parentRunId pada permintaan berikutnya:

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

Kirim hanya pesan baru dalam permintaan kelanjutan. MapAGUIServer menggunakan threadId untuk memilih sesi agen yang dihosting dan parentRunId untuk mengidentifikasi eksekusi yang sedang dilanjutkan. Tanpa persistensi sesi yang dihosting, setiap permintaan menerima sesi server baru; klien dapat mengirim ulang riwayat percakapan.

Untuk mempertahankan status milik server di seluruh permintaan, konfigurasikan AgentSession, lalu petakan agen terhosting bernama dengan MapAGUIServer. Untuk batas kepercayaan khusus AG-UI, lihat Pertimbangan produksi dan keamanan.

Langkah berikutnya

Prasyarat

Sebelum memulai, pastikan Anda memiliki hal berikut:

Nota

Sampel ini menggunakan model Azure OpenAI. Untuk informasi selengkapnya, lihat cara menyebarkan model Azure OpenAI dengan Foundry.

Nota

Sampel ini digunakan DefaultAzureCredential untuk autentikasi. Pastikan Anda diautentikasi dengan Azure (misalnya, melalui az login). Untuk informasi selengkapnya, lihat dokumentasi Azure Identity.

Warning

Protokol AG-UI masih dalam pengembangan dan dapat berubah. Kami akan terus memperbarui sampel ini saat protokol berkembang.

Langkah 1: Membuat Server AG-UI

Server AG-UI menyimpan agen AI Anda dan mengaksesnya melalui endpoint HTTP dengan menggunakan FastAPI.

Pasang Paket yang Diperlukan

Instal paket yang diperlukan untuk server:

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

Atau menggunakan uv:

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

Ini akan secara otomatis menginstal agent-framework-core, fastapi, uvicorn, dan sse-starlette sebagai dependensi.

Kode Server

Buat file bernama 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)

Konsep utama

  • add_agent_framework_fastapi_endpoint: Mendaftarkan titik akhir AG-UI dengan penanganan permintaan/respons otomatis dan streaming SSE
  • Agent: Agen Agen Framework yang akan menangani permintaan masuk
  • Integrasi FastAPI: Menggunakan dukungan asinkron asli FastAPI untuk respons streaming
  • Petunjuk: Agen dibuat dengan instruksi bawaan, yang dapat digantikan oleh pesan klien
  • Konfigurasi: OpenAIChatCompletionClient menerima input perutean Azure eksplisit seperti model, azure_endpoint, api_version, dan credential, dan juga dapat membaca dari variabel lingkungan

Mengonfigurasi dan Menjalankan Server

Atur variabel lingkungan yang diperlukan:

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

Jalankan server:

python server.py

Atau menggunakan uvicorn secara langsung:

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

Server akan mulai mendengarkan di http://127.0.0.1:8888.

Langkah 2: Membuat Klien AG-UI

Klien AG-UI terhubung ke server jarak jauh dan menampilkan respons streaming.

Pasang Paket yang Diperlukan

Paket AG-UI sudah diinstal, yang mencakup AGUIChatClient:

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

Kode Klien

Buat file bernama 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())

Konsep utama

  • Server-Sent Events (SSE): Protokol menggunakan format SSE (data: {json}\n\n)
  • Jenis Peristiwa: Peristiwa yang berbeda menyediakan metadata dan konten (HURUF BESAR dengan garis bawah):
    • RUN_STARTED: Agen telah mulai memproses
    • TEXT_MESSAGE_START: Awal dari pesan teks dari agen
    • TEXT_MESSAGE_CONTENT: Teks bertahap yang dialirkan dari agen (dengan bidang delta)
    • TEXT_MESSAGE_END: Akhir pesan teks
    • RUN_FINISHED: Penyelesaian berhasil
    • RUN_ERROR: Informasi kesalahan
  • Penamaan Bidang: Bidang peristiwa menggunakan camelCase (misalnya, , threadIdrunId, messageId)
  • Manajemen Utas: threadId mempertahankan konteks percakapan di seluruh permintaan
  • instruksiClient-Side: Pesan sistem dikirim dari klien

Mengonfigurasi dan Menjalankan Klien

Secara opsional atur URL server kustom:

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

Jalankan klien (di terminal terpisah):

python client.py

Langkah 3: Menguji Sistem Lengkap

Dengan server dan klien yang berjalan, Anda sekarang dapat menguji sistem lengkap.

Output yang Diharapkan

$ 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

Output Color-Coded

Klien menampilkan jenis konten yang berbeda dengan warna yang berbeda:

  • Kuning: Menjalankan pemberitahuan yang dimulai
  • Cyan: Respons teks agen (dialirkan secara waktu nyata)
  • Hijau: Menjalankan pemberitahuan penyelesaian
  • Merah: Pesan kesalahan

Pengujian dengan curl (Opsional)

Sebelum menjalankan klien, Anda dapat menguji server secara manual menggunakan 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?"}
    ]
  }'

Anda akan melihat streaming Server-Sent Events kembali:

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

Untuk stream yang idle, curl juga dapat menampilkan baris komentar : keepalive. Ini adalah komentar transportasi SSE, bukan peristiwa AG-UI.

Cara Kerjanya

Proses Server-Side

  1. Klien mengirim permintaan HTTP POST dengan pesan
  2. Titik akhir FastAPI menerima permintaan
  3. AgentFrameworkAgent pembungkus mengatur eksekusi
  4. Agen memproses pesan menggunakan Agent Framework
  5. AgentFrameworkEventBridge mengonversi pembaruan dari agen menjadi acara AG-UI
  6. Respons dialirkan kembali sebagai Server-Sent Events (SSE)
  7. Koneksi ditutup saat proses selesai

Proses Sisi Klien

  1. Klien mengirim permintaan HTTP POST ke titik akhir server
  2. Server merespons dengan aliran SSE
  3. Klien mengurai baris masuk data: sebagai peristiwa JSON
  4. Setiap peristiwa ditampilkan berdasarkan jenisnya
  5. threadId diambil untuk kelangsungan percakapan
  6. Penstriman selesai saat RUN_FINISHED peristiwa tiba

Detail Protokol

Protokol AG-UI menggunakan:

  • HTTP POST untuk mengirim permintaan
  • Server-Sent Events (SSE) untuk respons streaming
  • JSON untuk serialisasi peristiwa
  • ID benang untuk mempertahankan konteks percakapan
  • Jalankan ID untuk melacak eksekusi individual
  • Penamaan jenis peristiwa: HURUF BESAR dengan garis bawah (misalnya, RUN_STARTED, TEXT_MESSAGE_CONTENT)
  • Penamaan bidang: camelCase (misalnya, threadId, , runIdmessageId)
  • SSE mengirim komentar keepalive setiap 15 detik saat stream tidak aktif. Klien yang hanya memproses baris data: mengabaikan komentar ini secara otomatis.

Pola Umum

Konfigurasi Server Kustom

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 harus berupa angka positif atau None.

Beberapa Agen

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

Penanganan Kesalahan

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

Koneksi yang Ditolak

Pastikan server berjalan sebelum memulai klien:

# Terminal 1
python server.py

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

Kesalahan Autentikasi

Pastikan Anda diautentikasi dengan Azure:

az login

Verifikasi bahwa Anda memiliki penetapan peran yang benar pada sumber daya Azure OpenAI.

Streaming Tidak Berfungsi

Periksa apakah batas waktu klien Anda cukup:

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

Untuk agen jangka panjang, tingkatkan batas waktu yang sesuai.

Stream idle secara bawaan mengirimkan komentar keepalive SSE setiap 15 detik. Jika proksi menutup koneksi yang tidak aktif lebih cepat, konfigurasikan nilai positif keepalive_seconds yang lebih kecil saat mendaftarkan titik akhir.

Konteks Utas Hilang

Klien secara otomatis mengelola kelangsungan utas. Jika konteks hilang:

  1. Pastikan bahwa threadId ditangkap dari kejadian RUN_STARTED
  2. Pastikan instans klien yang sama digunakan di seluruh pesan
  3. Verifikasi bahwa server menerima thread_id dalam permintaan berikutnya

Langkah Selanjutnya

Sekarang setelah Anda memahami dasar-dasar AG-UI, Anda dapat:

Sumber Daya Tambahan

Go mendukung AG-UI melalui provider/aguiprovider baik untuk server maupun klien.

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

Gunakan aguiprovider.NewAgent saat aplikasi Go Anda perlu memanggil server AG-UI sebagai agen:

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{},
)

Tip

Lihat sampel server panduan memulai AG-UI dan klien untuk contoh lengkap yang siap dijalankan.