* updates to final deprecated pieces and versions * fix mypy * fix readme links
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
AGUIChatClientusage (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:
-
Start server with server-side tool (Terminal 1):
# Server has get_time_zone tool python server.py -
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:
-
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
-
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:
-
Client-Side Tools (
client_with_agent.py):- Tools defined in Agent's
toolsparameter execute locally - Tool metadata (name, description, schema) sent to server for planning
- When server requests client tool → client intercepts → executes locally → sends result
- Tools defined in Agent's
-
Server-Side Tools:
- Defined in server agent's configuration
- Server executes directly without client involvement
- Results included in server's response
-
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 Contributorrole 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 streamingAgent: 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:
OpenAIChatCompletionClientcan 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'sBaseChatClientinterface- Automatic Event Handling: The client automatically converts AG-UI events to Agent Framework types
- Thread Management: Pass
thread_idin metadata to maintain conversation context across requests - Streaming Responses: Use
get_response(..., stream=True)for real-time streaming orget_response(..., stream=False)for non-streaming - Context Manager: Use
async withfor 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:
- Check that
threadIdis being captured fromRUN_STARTEDevents - Ensure the same client instance is used across messages
- Verify the server is receiving the
thread_idin 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