Files

Getting Started with AG-UI (Python)

The AG-UI (Agent UI) protocol provides a standardized way for client applications to interact with AI agents over HTTP. This tutorial demonstrates how to build both server and client applications using the AG-UI protocol with Python.

Quick Start - Client Examples

If you want to quickly try out the AG-UI client, we provide three ready-to-use examples:

Basic Interactive Client (client.py)

A simple command-line chat client that demonstrates:

  • Streaming responses in real-time
  • Automatic thread management for conversation continuity
  • Direct AGUIChatClient usage (caller manages message history)

Run:

python client.py

Note: This example sends only the current message to the server. The server is responsible for maintaining conversation history using the thread_id.

Advanced Features Client (client_advanced.py)

Demonstrates advanced capabilities:

  • Tool/function calling
  • Both streaming and non-streaming responses
  • Multi-turn conversations
  • Error handling patterns

Run:

python client_advanced.py

Note: This example shows direct AGUIChatClient usage. Tool execution and conversation continuity depend on server-side configuration and capabilities.

Agent Integration (client_with_agent.py)

Best practice example using Agent wrapper with AgentThread

  • AgentThread maintains conversation state
  • Client-side conversation history management via thread.message_store
  • Hybrid tool execution: client-side + server-side tools simultaneously
  • Full conversation history sent on each request
  • Tool calling with conversation context

To demonstrate hybrid tools:

  1. Start server with server-side tool (Terminal 1):

    # Server has get_time_zone tool
    python server.py
    
  2. Run client with client-side tool (Terminal 2):

    # Client has get_weather tool
    python client_with_agent.py
    

All examples require a running AG-UI server (see Step 1 below for setup).

Understanding AG-UI Architecture

Thread Management

The AG-UI protocol supports two approaches to conversation history:

  1. Server-Managed Threads (client.py, client_advanced.py)

    • Client sends only the current message + thread_id
    • Server maintains full conversation history
    • Requires server to support stateful thread storage
    • Lighter network payload
  2. Client-Managed History (client_with_agent.py)

    • Client maintains full conversation history locally
    • Full message history sent with each request
    • Works with any AG-UI server (stateful or stateless)

The Agent wrapper (used in client_with_agent.py) collects messages from local storage and sends the full history to AGUIChatClient, which then forwards everything to the server.

Tool/Function Calling

The AG-UI protocol supports hybrid tool execution - both client-side AND server-side tools can coexist in the same conversation.

The Hybrid Pattern (client_with_agent.py):

Client defines:           Server defines:
- get_weather()          - get_current_time()
- read_sensors()         - get_server_forecast()

User: "What's the weather in SF and what time is it?"
    ↓
Agent sends: full history + tool definitions for get_weather, read_sensors
    ↓
Server LLM decides: "I need get_weather('SF') and get_current_time()"
    ↓
Server executes get_current_time() → "2025-11-11 14:30:00 UTC"
Server sends function call request → get_weather('SF')
    ↓
Agent intercepts get_weather call → executes locally
    ↓
Client sends result → "Sunny, 72°F"
    ↓
Server combines both results → "It's sunny and 72°F in SF, and the current time is 2:30 PM UTC"
    ↓
Client receives final response

How it works:

  1. Client-Side Tools (client_with_agent.py):

    • Tools defined in Agent's tools parameter execute locally
    • Tool metadata (name, description, schema) sent to server for planning
    • When server requests client tool → client intercepts → executes locally → sends result
  2. Server-Side Tools:

    • Defined in server agent's configuration
    • Server executes directly without client involvement
    • Results included in server's response
  3. Hybrid Pattern (Both Together):

    • Server LLM sees ALL tool definitions (client + server)
    • Decides which to use based on task
    • Server tools execute server-side
    • Client tools execute client-side

Direct AGUIChatClient Usage (client_advanced.py): Even without Agent wrapper, client-side tools work:

  • Tools passed in ChatOptions execute locally
  • Server can also have its own tools
  • Hybrid execution works automatically

What is AG-UI?

AG-UI is a protocol that enables:

  • Remote agent hosting: Host AI agents as web services that can be accessed by multiple clients
  • Streaming responses: Real-time streaming of agent responses using Server-Sent Events (SSE)
  • Standardized communication: Consistent message format for agent interactions
  • Thread management: Maintain conversation context across multiple requests
  • Advanced features: Human-in-the-loop, state management, tool rendering

Prerequisites

Before you begin, ensure you have the following:

  • Python 3.10 or later
  • Azure OpenAI service endpoint and deployment configured
  • Azure CLI installed and authenticated (for DefaultAzureCredential)
  • User has the Cognitive Services OpenAI Contributor role for the Azure OpenAI resource

Note: These samples use Azure OpenAI models. For more information, see how to deploy Azure OpenAI models with Azure AI Foundry.

Note: These samples use DefaultAzureCredential for authentication. Make sure you're authenticated with Azure (e.g., via az login, or environment variables). For more information, see the Azure Identity documentation.

Warning

The AG-UI protocol is still under development and subject to change. We will keep these samples updated as the protocol evolves.

Step 1: Creating an AG-UI Server

The AG-UI server hosts your AI agent and exposes it via HTTP endpoints using FastAPI.

Install Required Packages

pip install agent-framework-ag-ui

Or using uv:

uv pip install agent-framework-ag-ui

Server Code

Create a file named server.py:

# Copyright (c) Microsoft. All rights reserved.

"""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 fastapi import FastAPI

# Read required configuration
endpoint = os.environ.get("AZURE_OPENAI_ENDPOINT")
model = os.environ.get("AZURE_OPENAI_MODEL")
api_key = os.environ.get("AZURE_OPENAI_API_KEY")

if not endpoint:
    raise ValueError("AZURE_OPENAI_ENDPOINT environment variable is required")
if not model:
    raise ValueError("AZURE_OPENAI_MODEL environment variable is required")
if not api_key:
    raise ValueError("AZURE_OPENAI_API_KEY environment variable is required")

# Create the AI agent
agent = Agent(
    name="AGUIAssistant",
    instructions="You are a helpful assistant.",
    client=OpenAIChatCompletionClient(
        azure_endpoint=endpoint,
        model=model,
        api_key=api_key,
    ),
)

# 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=5100)

Key Concepts

  • add_agent_framework_fastapi_endpoint: Registers the AG-UI endpoint with automatic request/response handling and SSE streaming
  • Agent: The agent that will handle incoming requests
  • FastAPI Integration: Uses FastAPI's native async support for streaming responses
  • Instructions: The agent is created with default instructions, which can be overridden by client messages
  • Configuration: OpenAIChatCompletionClient can read from environment variables (AZURE_OPENAI_ENDPOINT, AZURE_OPENAI_MODEL, AZURE_OPENAI_API_KEY) or accept parameters directly

Alternative (simpler): Use environment variables only:

# No need to read environment variables manually
agent = Agent(
    name="AGUIAssistant",
    instructions="You are a helpful assistant.",
    client=OpenAIChatCompletionClient(),  # Reads from environment automatically
)

Configure and Run the Server

Set the required environment variables:

export AZURE_OPENAI_ENDPOINT="https://your-resource.openai.azure.com/"
export AZURE_OPENAI_MODEL="gpt-4o-mini"
# Optional: Set API key if not using DefaultAzureCredential
# export AZURE_OPENAI_API_KEY="your-api-key"

Run the server:

python server.py

Or using uvicorn directly:

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

The server will start listening on http://127.0.0.1:5100.

Step 2: Creating an AG-UI Client

The AG-UI client connects to the remote server and displays streaming responses. The AGUIChatClient is a built-in implementation that integrates with the Agent Framework's standard chat interface.

Install Required Packages

The AGUIChatClient is included in the agent-framework-ag-ui package (already installed if you installed the server packages).

pip install agent-framework-ag-ui

Client Code

Create a file named client.py:

# Copyright (c) Microsoft. All rights reserved.

"""AG-UI client example using AGUIChatClient."""

import asyncio
import os

from agent_framework.ag_ui import AGUIChatClient


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

    # Create client with context manager for automatic cleanup
    async with AGUIChatClient(endpoint=server_url) as client:
        thread_id: str | None = None

        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

                # Send message and stream the response
                print("\nAssistant: ", end="", flush=True)

                # Use metadata to maintain conversation continuity
                metadata = {"thread_id": thread_id} if thread_id else None

                async for update in client.get_response(message, metadata=metadata, stream=True):
                    # Extract thread ID from first update
                    if not thread_id and update.additional_properties:
                        thread_id = update.additional_properties.get("thread_id")
                        if thread_id:
                            print(f"\n[Thread: {thread_id}]")
                            print("Assistant: ", end="", flush=True)

                    # Stream text content as it arrives
                    for content in update.contents:
                        if content.type == "text" and content.text:
                            print(content.text, end="", flush=True)

                print()  # New line after response

        except KeyboardInterrupt:
            print("\n\nExiting...")
        except Exception as e:
            print(f"\nAn error occurred: {e}")


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

Key Concepts

  • AGUIChatClient: Built-in client that implements the Agent Framework's BaseChatClient interface
  • Automatic Event Handling: The client automatically converts AG-UI events to Agent Framework types
  • Thread Management: Pass thread_id in metadata to maintain conversation context across requests
  • Streaming Responses: Use get_response(..., stream=True) for real-time streaming or get_response(..., stream=False) for non-streaming
  • Context Manager: Use async with for automatic cleanup of HTTP connections
  • Standard Interface: Works with all Agent Framework patterns (Agent, tools, etc.)
  • Hybrid Tool Execution: Supports both client-side and server-side tools executing together in the same conversation

Configure and Run the Client

Optionally set a custom server URL:

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

Run the client (in a separate terminal):

python client.py

Step 3: Testing the Complete System

Expected Output

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

User (:q or quit to exit): What is the capital of France?

[Thread: abc123]
Assistant: The capital of France is Paris. It is known for its rich history, culture,
and iconic landmarks such as the Eiffel Tower and the Louvre Museum.

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

Troubleshooting

Connection Refused

Ensure the server is running before starting the client:

# Terminal 1
python server.py

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

Authentication Errors

Make sure you're authenticated with Azure:

az login

Verify you have the correct role assignment on the Azure OpenAI resource.

Streaming Not Working

Check that your client timeout is sufficient:

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

For long-running agents, increase the timeout accordingly.

No Events Received

Ensure you're using the correct Accept header:

headers={"Accept": "text/event-stream"}

And parsing SSE format correctly (lines starting with data: ).

Thread Context Lost

The client automatically manages thread continuity. If context is lost:

  1. Check that threadId is being captured from RUN_STARTED events
  2. Ensure the same client instance is used across messages
  3. Verify the server is receiving the thread_id in subsequent requests

Event Type Mismatches

Remember that event types are UPPERCASE with underscores (RUN_STARTED, not run_started) and field names are camelCase (threadId, not thread_id).

Import Errors

Make sure all packages are installed:

pip install agent-framework-ag-ui agent-framework-core fastapi uvicorn httpx

Or check your virtual environment is activated:

source venv/bin/activate  # Linux/macOS
venv\Scripts\activate     # Windows