The AG-UI Channel

By the Syncfusion DevTutorials team · Last updated

Wire the agent and the UI over an AG-UI-style event stream: text, tool calls, state deltas, interrupts and human-in-the-loop, without losing what the user typed.

What the AG-UI Channel Is

AG-UI = an open, event-based protocol for the live connection between an agent and your app's interface.

In this lesson, you will wire the order panel to the agent over one event stream, so the panel shows the agent's work as it happens, keeps what the user typed, stops cleanly, and asks the user when the agent needs a yes.

Every lesson so far used events: tokens, tool calls, a proposed action, an A2UI payload. AG-UI is the standard shape for that stream.

When the client handles the events badly, the user loses work. Here, the user is typing a note while the agent updates the order:

Press Play, or use Next to go one step at a time.

  • Frame 1: the user types "Call after 5 pm" into the note.
  • Frame 2: a state update from the agent replaces the whole note. The user's words are gone.
  • Frame 3: with merge, the new delivery date applies and the user's note stays.

Simple lesson: the agent and the user share the same screen. Neither should wipe out the other.

A Real-World Example

Think about a shared online document.

  • Two people type at once. Each sees the other's changes appear.
  • Your words don't disappear when someone else edits another line.
  • If someone needs your approval, a comment asks you, and they wait.

The AG-UI channel works the same way:

  • Seeing the other's changes = events streaming to the UI.
  • Your words stay = state deltas that keep the user's edits.
  • Asking and waiting = human-in-the-loop.

Click the button. The Build tab plays the state update through the naive client.

  • Shared state: watch the note before and after STATE_DELTA.
  • Events from the agent: RUN_STARTED, the user's typing, STATE_DELTA, RUN_FINISHED.
  • The check: the delta must not lose user edits.

Simple lesson: the client decides how each event changes the screen.

What You Will Learn

In this lesson, you will learn:

  1. How MCP, AG-UI and A2UI fit together.
  2. The main AG-UI event types.
  3. How to apply state deltas without losing user edits.
  4. How to interrupt an agent in the middle of a tool call.
  5. How human-in-the-loop requests work.

About AG-UI in this lab

  • AG-UI is an open spec. This course teaches a compatible subset, so the checks stay stable while the spec grows.
  • Real AG-UI sends state changes as JSON Patch operations. The lab shows the changed fields directly, so the idea is easier to see.
  • The human-in-the-loop event here is labelled "custom": check how your framework names it.

Three Protocols, Three Jobs

Step through all three frames.

  • Frame 1: MCP connects the agent to its tools: the order database, the courier.
  • Frame 2: AG-UI connects the agent to your app: the stream of events.
  • Frame 3: A2UI or MCP Apps describe what to draw. They travel inside AG-UI events.
LayerJobIn this course
MCPAgent ↔ toolsThe MCP course
AG-UIAgent ↔ your appThis lesson
A2UI / MCP AppsWhat to renderLessons 8 and 9

Simple lesson: MCP is for tools, AG-UI is the channel, A2UI and MCP Apps are the payload.

The Event Stream

An AG-UI run is a stream of small events. The main ones:

EventWhat it says
RUN_STARTEDThe agent started working
TEXT_MESSAGE_CONTENTA few more words of the answer
TOOL_CALL_START / TOOL_CALL_ENDA tool call began or finished
STATE_DELTASome fields of the shared state changed
RUN_FINISHEDThe agent is done

The client reads each event and updates the screen. You already built most of this: streaming (Lesson 2), tool steps (Lesson 2), and payloads (Lesson 8).

State Deltas

Shared state = data both the agent and the UI can see and change, such as the order's ETA and the ticket note.

State delta = an event with only the fields that changed.

The client must merge the delta, but keep any field the user is editing:

function onStateDelta(patch: Record<string, string>) {
  setState((s) => {
    const next = { ...s };
    for (const [k, v] of Object.entries(patch)) if (!dirty.current.has(k)) next[k] = v;
    return next;
  });
}

dirty is the set of fields the user has typed in. Tell the agent about the user's edit in the next message, so it can adjust.

Simple lesson: apply the agent's changes, except where the user is typing.

Interrupts and Human-in-the-Loop

Step through both frames.

  • Frame 1: the user presses Stop while the agent is changing the address. Ignored on the left; the address still changes. On the right, the run is cancelled and nothing changes.
  • Frame 2: the agent pauses to ask "Change the delivery address?". On the left, the question never reaches the screen. On the right, the user approves and the run resumes.

Interrupt

Interrupt = the user stops the run while it is working.

Abort the run, as with Stop in Lesson 2. The agent's server should roll back half-done tool work and end with RUN_CANCELLED.

Human-in-the-Loop

Human-in-the-loop = the agent pauses and waits for a person to decide.

Show the request where the user is working, with the exact details (as in Lesson 5). Send the answer back, so the run continues.

A request nobody sees is a stuck run.

  • If the client ignores the agent's question, the agent waits forever.
  • Show every human-in-the-loop request, even when the panel is closed (for example with a badge).
  • Time out politely, and say what happened.

Easy way to remember: Merge, abort, ask. Merge deltas around the user's edits, abort cleanly on Stop, and show the agent's questions.

Simple lesson: the user can stop the agent, and the agent can ask the user.

Lab Exercise: Wire the AG-UI Client

Your task: change the Lesson 10 settings in the Build tab so all three scenarios pass. Then press Check all scenarios.

Click the button and open the Build tab.

  • The three scenarios: a delta while typing, an interrupt during a tool call, and a request for approval.
  • Shared state: shows whose edit won.
  • Side effects: show whether the address really changed.

Simple lesson: merge, abort and ask, all three.

What Changes per Framework

OptionAG-UI client
Hand-built ReactRead the event stream and handle each type, as above
CopilotKitA reference AG-UI client with shared state and human-in-the-loop
AG-UI SDKsClient and server SDKs for several languages, including .NET
Your agent frameworkMany agent frameworks can emit AG-UI events; check yours

Build It in React

In the Code tab, your component is the AG-UI client. It gets run-start, tool-call-start, state-delta and hitl-request events, and the lab types in the Note box like a real user.

The rule for deltas fits in one loop. Skip any field the user has edited:

for (const [k, v] of Object.entries(e.patch)) if (!edited.current.has(k)) next[k] = v;

Show Stop while a run is going, and call agent.cancel() when it is pressed. When the agent asks a person, show the question and send the answer back with agent.respond(true).

TL;DR

  1. AG-UI = the event channel between agent and app.
  2. Layers = MCP for tools, AG-UI for the channel, A2UI or MCP Apps for the payload.
  3. Events = RUN_STARTED, TEXT_MESSAGE_CONTENT, TOOL_CALL_START/END, STATE_DELTA, RUN_FINISHED.
  4. State delta = merge, but keep fields the user is editing.
  5. Interrupt = abort and roll back, ending with RUN_CANCELLED.
  6. Human-in-the-loop = show the agent's question, send the answer back.

Common mistakes

MistakeWrong ideaCorrect ideaWhat goes wrong
Replacing state"The agent's state is the truth."Merge, keeping the user's edits.The user's note disappears.
Ignoring interrupts"The tool will finish soon anyway."Abort and roll back.The address changes after Stop.
Hiding HITL requests"The panel is closed, it can wait."Show the request where the user is.The run is stuck forever.
Mixing up the layers"AG-UI is a UI format."AG-UI is the transport; A2UI is the format.The team builds the wrong thing.
Tracking the full spec blindly"Use every new event type."Pin the subset you test.A spec change breaks the UI.

Check Your Understanding

Exercises

What to Remember

  • AG-UI is the channel; MCP is for tools; A2UI and MCP Apps are the payload.
  • The client turns each event into a screen change.
  • Merge state deltas, but keep what the user is typing.
  • Stop during a tool call must abort and roll back.
  • Show every human-in-the-loop request, and send the answer back.

Further Reading

Next: Feedback That Improves the Product, where thumbs, corrections and regenerate clicks become events your evals can learn from.