AG-UI (Agent–User Interaction Protocol) Notes
Why AG-UI?
The first time someone comes across AG-UI, they usually ask:
We already have SSE / WebSocket. Why do we need AG-UI?
Here’s the distinction:
- SSE/WebSocket solve how to transmit (Transport)
- AG-UI solves what to transmit (Interaction Protocol)
Analogy:
| Layer | Role |
|---|---|
| TCP | Transmits byte streams |
| HTTP | Defines request/response semantics |
| SSE | Defines server-push streaming |
| AG-UI | Defines Agent–UI interaction event semantics |
Limitations of SSE
SSE only sends events:
1
2
event: message
data: hello
But it doesn’t know:
1
2
3
4
Is this plain text?
Is this a Tool Call?
Is this an approval request?
Is this a state sync?
To SSE, it’s all just strings.
That’s why different Agent Frameworks end up defining their own event formats.
For example:
LangGraph:
1
2
3
{
"type": "tool_start"
}
Another framework:
1
2
3
{
"event": "tool.begin"
}
The frontend has to adapt to each one.
The Core Value of AG-UI
AG-UI defines a unified event model:
1
2
3
{
"type": "TOOL_CALL_START"
}
1
2
3
{
"type": "TEXT_MESSAGE_CONTENT"
}
1
2
3
{
"type": "STATE_DELTA"
}
No matter the backend:
- LangGraph
- OpenAI Agents SDK
- CrewAI
- PydanticAI
- Custom Agent
The frontend sees the same events.
How AG-UI Relates to MCP and A2A
MCP
Solves:
1
Agent ↔ Tool
For example:
1
2
3
4
GitHub
Jira
Slack
MySQL
A2A
Solves:
1
Agent ↔ Agent
For example:
1
2
3
4
5
Research Agent
↓
Coding Agent
↓
Review Agent
AG-UI
Solves:
1
Agent ↔ UI
For example:
1
2
3
4
React
Vue
Mobile App
Desktop App
Who Are the Two Parties in AG-UI Communication?
Many sources describe it as:
1
User ↔ Agent
But a more accurate framing is:
1
Agent Runtime ↔ Agent Client
Or:
1
Agent Backend ↔ Agent Frontend
Common scenarios:
Web
1
2
3
4
5
React/Vue
↕
AG-UI
↕
Agent Runtime
Mobile
1
2
3
4
5
iOS/Android
↕
AG-UI
↕
Agent Runtime
Desktop
1
2
3
4
5
Electron/Tauri
↕
AG-UI
↕
Agent Runtime
Putting AG-UI Into Practice
Frontend
Without AG-UI
React listens to SSE directly:
1
const es = new EventSource("/agent");
Then parses whatever custom events the backend sends.
Downside:
Every Agent Framework needs its own adapter.
With AG-UI
The frontend only deals with standard events:
1
2
3
4
5
6
7
8
TEXT_MESSAGE_START
TEXT_MESSAGE_CONTENT
TEXT_MESSAGE_END
TOOL_CALL_START
TOOL_CALL_END
STATE_DELTA
For example:
1
2
3
4
5
6
7
client.subscribe(event => {
switch(event.type) {
case "TOOL_CALL_START":
showTool(event.toolName)
break
}
})
Switching the Agent Runtime doesn’t require frontend changes.
Backend
LangGraph
Native events:
1
2
3
on_tool_start
on_tool_end
on_llm_new_token
Transformation:
1
2
3
LangGraph Event
↓
AG-UI Event
For example:
1
2
3
on_tool_start
↓
TOOL_CALL_START
LangChain
Using a Callback Handler:
1
2
class AgUiHandler(BaseCallbackHandler):
...
Mapping:
1
2
3
4
5
6
7
on_tool_start
↓
TOOL_CALL_START
on_llm_new_token
↓
TEXT_MESSAGE_CONTENT
OpenCode
OpenCode has its own event system:
1
2
3
4
task_start
tool_start
tool_end
message_chunk
Integration:
1
2
3
4
5
OpenCode Event
↓
AG-UI Adapter
↓
React/Vue/UI
What Actually Makes AG-UI Valuable
A lot of people think it’s just about token streaming.
Turns out streaming is the easy part.
What’s actually valuable:
Human In The Loop
Agent:
1
About to delete the production database
Sends:
1
2
3
{
"type": "APPROVAL_REQUEST" // actual AG-UI uses the interrupt mechanism; this is a simplified illustration
}
Frontend automatically shows:
1
2
Approve
Reject
After the user chooses, execution continues.
Shared State
Agent:
1
2
3
{
"type": "STATE_DELTA"
}
Updates the shared state.
React/Vue sync the UI automatically.
Generative UI
Agent outputs:
1
2
3
4
{
"type": "UI_COMPONENT", // actual AG-UI implements this through tool calls + state; this is a conceptual illustration
"component": "table"
}
Frontend renders automatically:
1
2
3
4
Table
Chart
Form
Card
Architect’s Perspective
If the system is just:
1
2
3
React
↓
Agent
Then SSE is enough.
But if the goal is:
1
2
3
4
5
Support LangGraph
Support ADK
Support OpenAI Agents
Support OpenCode
Support custom Agents
And also:
1
2
3
Web
Mobile
Desktop
That’s where AG-UI’s value shows up.
Unified as:
1
2
3
4
5
Agent Adapter
↓
AG-UI
↓
Unified UI
TL;DR
1
2
3
4
5
MCP = The USB port for Agents
A2A = The RPC protocol for Agents
AG-UI = The frontend protocol for Agents
Or:
1
2
3
SSE = The delivery company
AG-UI = The standardized packaging inside the box
You can get by without AG-UI.
AG-UI’s goal is to standardize the connection between different Agent Frameworks and different frontend frameworks.
-
Previous
LangChain vs LangGraph vs DeepAgents vs OpenCode: A Framework Comparison and DeepAgents Architecture Deep Dive -
Next
LLM Agent Context & Memory Management: Problems, Solutions, and Practice