AG-UI (Agent–User Interaction Protocol) Notes

Posted by Night Field's Blog on March 14, 2026

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.