TL;DR:
- AG-UI is an open, transport-agnostic protocol that standardises the event stream an AI agent sends to a frontend — covering messages, tool calls, state snapshots, and lifecycle signals.
- It decouples backend agent frameworks (LangGraph, CrewAI, custom) from frontend rendering, so you can swap either side without rebuilding the integration.
- CopilotKit ships a reference implementation, but the protocol itself is framework-neutral and works over SSE, WebSockets, or HTTP streaming.
Building a responsive frontend for an AI agent means more than streaming tokens. Users want to see tool calls firing, intermediate results arriving, and agent state updating in real time. Every team that builds this ends up inventing the same ad-hoc event schema: { type: "tool_call", name: "...", input: {...} }, { type: "token", delta: "..." }, { type: "done" }. AG-UI standardises that schema so you build it once.
What AG-UI Is
AG-UI (Agent-User Interaction protocol) is an open protocol specification for the event stream between a backend AI agent and a frontend application. It defines a common vocabulary of typed events that covers the full lifecycle of an agent turn:
- Lifecycle events:
RUN_STARTED,RUN_FINISHED,RUN_ERROR - Text events:
TEXT_MESSAGE_START,TEXT_MESSAGE_CONTENT,TEXT_MESSAGE_END - Tool events:
TOOL_CALL_START,TOOL_CALL_ARGS,TOOL_CALL_END - State events:
STATE_SNAPSHOT,STATE_DELTA(JSON Patch) - Custom events:
CUSTOMwith a typed payload for app-specific signals
The protocol is transport-agnostic. You can deliver these events over Server-Sent Events, WebSockets, or chunked HTTP. The serialisation format is newline-delimited JSON.
Why a Shared Protocol Matters
Before AG-UI, connecting a LangGraph backend to a React frontend meant building a custom event bridge every time. Switching from LangGraph to CrewAI, or from React to Vue, broke the integration. The result was tight coupling between agent framework choice and frontend rendering logic.
AG-UI inverts this. The backend emits standard AG-UI events. The frontend subscribes to standard AG-UI events. The middleware in between — the HTTP layer, the streaming adapter — is defined by the protocol, not by either end.
This is the same value proposition HTTP gave to web applications: a shared protocol means clients and servers can evolve independently.
Server Side: Emitting AG-UI Events
Any backend that can stream newline-delimited JSON over HTTP can emit AG-UI events. Here’s a minimal Python example using FastAPI:
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
import json
import time
app = FastAPI()
def make_event(event_type: str, **kwargs) -> str:
payload = {"type": event_type, "timestamp": int(time.time() * 1000), **kwargs}
return f"data: {json.dumps(payload)}\n\n"
async def run_agent_stream(message: str):
run_id = "run_001"
yield make_event("RUN_STARTED", runId=run_id, threadId="thread_001")
yield make_event("TEXT_MESSAGE_START", messageId="msg_001", role="assistant")
# Simulate token streaming
response = "I'll search for that information now."
for char in response:
yield make_event("TEXT_MESSAGE_CONTENT", messageId="msg_001", delta=char)
yield make_event("TEXT_MESSAGE_END", messageId="msg_001")
# Emit a tool call
yield make_event("TOOL_CALL_START", toolCallId="tc_001", toolCallName="web_search")
yield make_event("TOOL_CALL_ARGS", toolCallId="tc_001", delta='{"query": "latest AI news"}')
yield make_event("TOOL_CALL_END", toolCallId="tc_001")
yield make_event("RUN_FINISHED", runId=run_id)
@app.post("/agent/stream")
async def stream_agent(body: dict):
return StreamingResponse(
run_agent_stream(body.get("message", "")),
media_type="text/event-stream",
headers={"Cache-Control": "no-cache", "X-Accel-Buffering": "no"},
)
For LangGraph specifically, the langgraph-sdk package includes an AG-UI adapter that maps LangGraph’s native event stream to the AG-UI event schema automatically.
Client Side: Consuming AG-UI Events in React
CopilotKit ships @ag-ui/client and React hooks that consume the protocol:
import { useCoAgent } from "@copilotkit/react-core";
import { AgentState } from "./types";
function AgentPanel() {
const { state, running, messages } = useCoAgent<AgentState>({
name: "my_agent",
initialState: { query: "", results: [] },
});
return (
<div>
{running && <div className="indicator">Agent is running...</div>}
{messages.map((msg) => (
<div key={msg.id}>
{msg.role === "assistant" && <p>{msg.content}</p>}
{msg.toolCalls?.map((tc) => (
<div key={tc.id} className="tool-call">
Calling: {tc.name}
</div>
))}
</div>
))}
{state.results.length > 0 && (
<ul>
{state.results.map((r, i) => <li key={i}>{r}</li>)}
</ul>
)}
</div>
);
}
If you prefer to consume the protocol directly without CopilotKit, the STATE_SNAPSHOT and STATE_DELTA events give you a live view into the agent’s working state. STATE_DELTA uses JSON Patch (RFC 6902), so you apply patches incrementally rather than replacing the full state object on each event.
State Synchronisation
The most useful AG-UI feature beyond token streaming is shared state. The backend agent can write to a typed state object, and the frontend receives that state in real time via STATE_SNAPSHOT (on connect or reset) and STATE_DELTA (incremental patches).
This powers UI patterns that aren’t possible with token streaming alone:
- A sidebar that shows the agent’s current plan, updating as steps complete
- A data table that populates as the agent retrieves results
- A progress indicator that reflects actual agent execution stages, not just spinner heuristics
The state object is defined by the application. AG-UI carries it but doesn’t schema-check it — that’s the application’s responsibility.
Framework Adapters Available in 2026
The AG-UI ecosystem in mid-2026 includes adapters for:
- LangGraph (Python and JS): via
langgraph-sdkAG-UI middleware - CrewAI: community adapter published to PyPI as
crewai-agui - Mastra (TypeScript): built-in AG-UI emitter in Mastra’s agent runtime
- Custom agents: use the raw protocol spec and emit events yourself — it’s intentionally simple
Frontend libraries with AG-UI support include CopilotKit (React), and a Vue 3 composable (@ag-ui/vue) published in early 2026.
When to Use AG-UI vs a Custom Event Schema
AG-UI is worth adopting when:
- You’re building a chat or agent interface that needs to show tool calls and state updates (not just tokens)
- You want to swap agent frameworks without rebuilding the frontend integration
- You’re building multiple frontends against the same agent backend
A custom event schema is fine when your interface only streams tokens and a done signal, or when you’re integrating with an existing opinionated framework that already handles its own streaming.
The protocol specification, TypeScript types, and the Python and TypeScript SDKs are all open source at github.com/ag-ui-protocol/ag-ui.