Close Menu
    Facebook X (Twitter) Instagram
    Articles Stock
    • Home
    • Technology
    • AI
    • Pages
      • About ArticlesStock — AI & Technology Journalist
      • Contact us
      • Disclaimer For Articles Stock
      • Privacy Policy
      • Terms and Conditions
    Facebook X (Twitter) Instagram
    Articles Stock
    AI

    A Coding Deep Dive into Agentic UI, Generative UI, State Synchronization, and Interrupt-Pushed Approval Flows

    Naveed AhmadBy Naveed Ahmad01/05/2026Updated:01/05/2026No Comments24 Mins Read
    blog 1 25


    On this tutorial, we construct the whole Agentic UI stack from the bottom up utilizing plain Python, with out counting on exterior frameworks to summary away the core concepts. We implement the AG-UI occasion stream to make agent conduct observable in actual time, and we herald A2UI as a declarative layer that permits interfaces to be outlined as structured JSON slightly than executable code. As we progress, we allow an LLM to generate full consumer interfaces from pure language, synchronize agent and UI state by way of JSON Patch updates, and implement human-in-the-loop security for vital actions. Additionally, we acquire a transparent, end-to-end understanding of how agent reasoning transforms into interactive, protocol-compliant consumer interfaces.

    Copy CodeCopiedUse a unique Browser
    import subprocess, sys
    for pkg in ["openai", "rich", "pydantic"]:
       subprocess.check_call([sys.executable, "-m", "pip", "install", "-q", pkg])
    
    
    import os, getpass
    
    
    if os.environ.get("OPENAI_API_KEY"):
       API_KEY = os.environ["OPENAI_API_KEY"]
       print(" Utilizing OPENAI_API_KEY from setting.")
    else:
       attempt:
           from google.colab import userdata
           API_KEY = userdata.get("OPENAI_API_KEY")
           print(" Utilizing OPENAI_API_KEY from Colab Secrets and techniques.")
       besides Exception:
           API_KEY = getpass.getpass(" Enter your OpenAI API key (hidden): ")
           print(" API key obtained.")
    
    
    BASE_URL = os.environ.get("OPENAI_BASE_URL", "https://api.openai.com/v1")
    MODEL    = os.environ.get("OPENAI_MODEL", "gpt-4o-mini")
    
    
    import json, re, time, uuid, copy, textwrap
    from enum import Enum
    from dataclasses import dataclass, discipline, asdict
    from typing import Any, Non-obligatory, Generator
    from pydantic import BaseModel, Discipline
    
    
    from openai import OpenAI
    from wealthy.console import Console
    from wealthy.panel import Panel
    from wealthy.desk import Desk
    from wealthy.tree import Tree
    from wealthy.textual content import Textual content
    from wealthy.markdown import Markdown
    from wealthy import field
    
    
    console = Console(width=105)
    shopper  = OpenAI(api_key=API_KEY, base_url=BASE_URL)
    
    
    def llm(messages, **kw):
       attempt:
           return shopper.chat.completions.create(mannequin=MODEL, messages=messages, temperature=0.2, **kw)
       besides Exception as e:
           console.print(f"[red]LLM error: {e}[/]")
           return None
    
    
    def hdr(n, title, sub=""):
       console.print()
       console.rule(f"[bold cyan]SECTION {n}", fashion="cyan")
       physique = f"[bold white]{title}[/]n[dim]{sub}[/]" if sub else f"[bold white]{title}[/]"
       console.print(Panel(physique, border_style="cyan", padding=(1, 2)))
    
    
    
    
    hdr(1, "AG-UI Protocol — Occasion System",
       "The true AG-UI protocol makes use of ~16 occasion varieties streamed through SSE.n"
       "We implement all core occasion varieties and a streaming emitter in pure Python.")
    
    
    class AGUIEventType(str, Enum):
       RUN_STARTED          = "RUN_STARTED"
       RUN_FINISHED         = "RUN_FINISHED"
       RUN_ERROR            = "RUN_ERROR"
       TEXT_MESSAGE_START   = "TEXT_MESSAGE_START"
       TEXT_MESSAGE_CONTENT = "TEXT_MESSAGE_CONTENT"
       TEXT_MESSAGE_END     = "TEXT_MESSAGE_END"
       TOOL_CALL_START      = "TOOL_CALL_START"
       TOOL_CALL_ARGS       = "TOOL_CALL_ARGS"
       TOOL_CALL_RESULT     = "TOOL_CALL_RESULT"
       TOOL_CALL_END        = "TOOL_CALL_END"
       STATE_SNAPSHOT       = "STATE_SNAPSHOT"
       STATE_DELTA          = "STATE_DELTA"
       INTERRUPT            = "INTERRUPT"
       CUSTOM               = "CUSTOM"
       STEP_STARTED         = "STEP_STARTED"
       STEP_FINISHED        = "STEP_FINISHED"
    
    
    
    
    @dataclass
    class AGUIEvent:
       sort: AGUIEventType
       knowledge: dict = discipline(default_factory=dict)
       event_id: str = discipline(default_factory=lambda: str(uuid.uuid4())[:8])
       timestamp: float = discipline(default_factory=time.time)
    
    
       def to_sse(self) -> str:
           payload = {"sort": self.sort.worth, "id": self.event_id, **self.knowledge}
           return f"occasion: ag-uindata: {json.dumps(payload)}nn"
    
    
       def to_json(self) -> dict:
           return {"sort": self.sort.worth, "id": self.event_id, "ts": self.timestamp, **self.knowledge}
    
    
    
    
    class AGUIEventStream:
       def __init__(self):
           self.occasions: checklist[AGUIEvent] = []
           self.listeners: checklist = []
    
    
       def emit(self, occasion: AGUIEvent):
           self.occasions.append(occasion)
           for listener in self.listeners:
               listener(occasion)
    
    
       def on(self, callback):
           self.listeners.append(callback)
    
    
       def replay(self) -> checklist[dict]:
           return [e.to_json() for e in self.events]
    
    
    
    
    def demo_agui_lifecycle():
       stream = AGUIEventStream()
    
    
       event_colors = {
           "RUN_": "daring inexperienced", "TEXT_": "cyan", "TOOL_": "magenta",
           "STATE_": "yellow", "INTERRUPT": "daring crimson", "STEP_": "dim",
       }
    
    
       def frontend_listener(occasion: AGUIEvent):
           coloration = "white"
           for prefix, c in event_colors.objects():
               if occasion.sort.worth.startswith(prefix):
                   coloration = c
                   break
           element = json.dumps(occasion.knowledge)[:80] if occasion.knowledge else ""
           console.print(f"  [{color}] {occasion.sort.worth:.<28}[/] {element}")
    
    
       stream.on(frontend_listener)
    
    
       run_id = str(uuid.uuid4())[:8]
       console.print("[bold]Simulating full AG-UI agent run...[/]n")
    
    
       stream.emit(AGUIEvent(AGUIEventType.RUN_STARTED, {"run_id": run_id}))
    
    
       stream.emit(AGUIEvent(AGUIEventType.STEP_STARTED, {"step": "analyzing_query", "label": "Understanding request"}))
       stream.emit(AGUIEvent(AGUIEventType.STEP_FINISHED, {"step": "analyzing_query"}))
    
    
       msg_id = str(uuid.uuid4())[:8]
       stream.emit(AGUIEvent(AGUIEventType.TEXT_MESSAGE_START, {"message_id": msg_id, "function": "assistant"}))
       for chunk in ["I'll ", "look up ", "the data ", "and build ", "a dashboard ", "for you."]:
           stream.emit(AGUIEvent(AGUIEventType.TEXT_MESSAGE_CONTENT, {"message_id": msg_id, "delta": chunk}))
       stream.emit(AGUIEvent(AGUIEventType.TEXT_MESSAGE_END, {"message_id": msg_id}))
    
    
       tool_id = str(uuid.uuid4())[:8]
       stream.emit(AGUIEvent(AGUIEventType.TOOL_CALL_START, {"tool_call_id": tool_id, "title": "query_database"}))
       stream.emit(AGUIEvent(AGUIEventType.TOOL_CALL_ARGS, {"tool_call_id": tool_id, "args_delta": '{"question": "SELECT income FROM gross sales"}'}))
       stream.emit(AGUIEvent(AGUIEventType.TOOL_CALL_RESULT, {"tool_call_id": tool_id, "outcome": [{"month": "Jan", "revenue": 42000}, {"month": "Feb", "revenue": 58000}]}))
       stream.emit(AGUIEvent(AGUIEventType.TOOL_CALL_END, {"tool_call_id": tool_id}))
    
    
       stream.emit(AGUIEvent(AGUIEventType.STATE_SNAPSHOT, {
           "state": {"active_agent": "DataAnalyst", "stage": "rendering", "progress": 0.75}
       }))
       stream.emit(AGUIEvent(AGUIEventType.STATE_DELTA, {
           "delta": [{"op": "replace", "path": "/progress", "value": 1.0}]
       }))
    
    
       stream.emit(AGUIEvent(AGUIEventType.INTERRUPT, {
           "motive": "high_risk_action",
           "description": "Agent needs to ship an electronic mail to all 5,000 prospects.",
           "choices": ["approve", "reject", "modify"],
       }))
    
    
       stream.emit(AGUIEvent(AGUIEventType.RUN_FINISHED, {"run_id": run_id, "standing": "accomplished"}))
    
    
       console.print(Panel(
           stream.occasions[3].to_sse(),
           title="[bold]Instance SSE wire format (the way it appears to be like on the community)",
           border_style="dim",
       ))
    
    
       desk = Desk(title="AG-UI Occasion Stream Abstract", field=field.ROUNDED)
       desk.add_column("Class", fashion="cyan", width=15)
       desk.add_column("Occasions", justify="middle", fashion="inexperienced")
       counts = {}
       for e in stream.occasions:
           cat = e.sort.worth.rsplit("_", 1)[0] if "_" in e.sort.worth else e.sort.worth
           counts[cat] = counts.get(cat, 0) + 1
       for cat, n in counts.objects():
           desk.add_row(cat, str(n))
       desk.add_row("[bold]TOTAL", f"[bold]{len(stream.occasions)}")
       console.print(desk)
    
    
    demo_agui_lifecycle()

    We begin by constructing the spine of each agentic frontend: the AG-UI occasion stream. We implement all 16 occasion varieties from the true AG-UI specification, lifecycle occasions, token-by-token textual content streaming, streamed instrument calls, state snapshots, deltas, and interrupt alerts, and serialize them into the SSE wire format that manufacturing methods use over HTTP. We then wire up a frontend listener that reacts to every occasion because it arrives, simulating the precise expertise a React or Flutter app would have consuming this stream.

    Copy CodeCopiedUse a unique Browser
    hdr(2, "A2UI — Declarative Part Bushes",
       "Google's A2UI spec: brokers emit flat JSON element lists with ID refs.n"
       "The shopper's widget registry maps varieties → native widgets.n"
       "Secure like knowledge, expressive like code. No executable code despatched.")
    
    
    class A2UIMessageType(str, Enum):
       CREATE_SURFACE      = "createSurface"
       UPDATE_COMPONENTS   = "updateComponents"
       UPDATE_DATA_MODEL   = "updateDataModel"
       DELETE_SURFACE       = "deleteSurface"
    
    
    
    
    @dataclass
    class A2UIComponent:
       id: str
       sort: str
       properties: dict = discipline(default_factory=dict)
       kids: checklist[str] = discipline(default_factory=checklist)
    
    
       def to_dict(self) -> dict:
           d = {"id": self.id, "sort": self.sort, **self.properties}
           if self.kids:
               d["children"] = self.kids
           return d
    
    
    
    
    @dataclass
    class A2UIDataModel:
       knowledge: dict = discipline(default_factory=dict)
    
    
       def get_binding(self, path: str) -> Any:
           components = [p for p in path.split("/") if p]
           val = self.knowledge
           for p in components:
               if isinstance(val, dict):
                   val = val.get(p)
               elif isinstance(val, checklist) and p.isdigit():
                   val = val[int(p)]
               else:
                   return None
           return val
    
    
    
    
    @dataclass
    class A2UISurface:
       surface_id: str
       parts: checklist[A2UIComponent] = discipline(default_factory=checklist)
       data_model: A2UIDataModel = discipline(default_factory=A2UIDataModel)
    
    
       def to_messages(self) -> checklist[dict]:
           msgs = []
           msgs.append({
               "sort": A2UIMessageType.CREATE_SURFACE.worth,
               "surfaceId": self.surface_id,
           })
           msgs.append({
               "sort": A2UIMessageType.UPDATE_COMPONENTS.worth,
               "surfaceId": self.surface_id,
               "parts": [c.to_dict() for c in self.components],
           })
           if self.data_model.knowledge:
               msgs.append({
                   "sort": A2UIMessageType.UPDATE_DATA_MODEL.worth,
                   "surfaceId": self.surface_id,
                   "dataModel": self.data_model.knowledge,
               })
           return msgs
    
    
    
    
    class WidgetRegistry:
       def __init__(self):
           self._renderers = {}
    
    
       def register(self, component_type: str, render_fn):
           self._renderers[component_type] = render_fn
    
    
       def render(self, element: A2UIComponent, floor: A2UISurface, indent: int = 0):
           fn = self._renderers.get(element.sort)
           if fn:
               fn(element, floor, indent)
           else:
               pad = "  " * indent
               console.print(f"{pad}[dim]⟨{element.sort} id={element.id}⟩ (no renderer)[/]")
    
    
       def render_tree(self, floor: A2UISurface):
           comp_map = {c.id: c for c in floor.parts}
           all_children = set()
           for c in floor.parts:
               all_children.replace(c.kids)
           roots = [c for c in surface.components if c.id not in all_children]
    
    
           def _render(comp_id: str, indent: int):
               comp = comp_map.get(comp_id)
               if not comp:
                   return
               self.render(comp, floor, indent)
               for child_id in comp.kids:
                   _render(child_id, indent + 1)
    
    
           for root in roots:
               _render(root.id, 0)
    
    
    
    
    registry = WidgetRegistry()
    
    
    def _resolve(comp, floor, key, default=None):
       val = comp.properties.get(key, default)
       binding = comp.properties.get("dataBinding")
       if binding and isinstance(binding, str) and binding.startswith("/"):
           resolved = floor.data_model.get_binding(binding)
           if resolved will not be None:
               return resolved
       if isinstance(val, str) and val.startswith("/") and "/" in val[1:]:
           resolved = floor.data_model.get_binding(val)
           if resolved will not be None:
               return resolved
       return val
    
    
    def _to_float(val, default=0.0):
       if isinstance(val, (int, float)):
           return float(val)
       if isinstance(val, str):
           cleaned = val.strip().rstrip("%")
           attempt:
               f = float(cleaned)
               if "%" in val or f > 1:
                   return f / 100.0
               return f
           besides ValueError:
               return default
       return default
    
    
    def render_card(comp, floor, indent):
       pad = "  " * indent
       title = str(_resolve(comp, floor, "title", "Card"))
       console.print(f"{pad}┌─{'─' * 50}─┐")
       console.print(f"{pad}│ [bold]{title:^50}[/] │")
       console.print(f"{pad}├─{'─' * 50}─┤")
       if not comp.kids:
           subtitle = str(_resolve(comp, floor, "subtitle", ""))
           if subtitle:
               console.print(f"{pad}│  {subtitle:<49}│")
           console.print(f"{pad}└─{'─' * 50}─┘")
    
    
    def render_text(comp, floor, indent):
       pad = "  " * indent
       textual content = _resolve(comp, floor, "textual content", "")
       fashion = comp.properties.get("fashion", "physique")
       types = {"headline": "daring white", "physique": "white", "caption": "dim", "label": "daring cyan"}
       console.print(f"{pad}[{styles.get(style, 'white')}]{textual content}[/]")
    
    
    def render_button(comp, floor, indent):
       pad = "  " * indent
       label = str(_resolve(comp, floor, "label", "Button"))
       variant = comp.properties.get("variant", "main")
       colours = {"main": "daring white on blue", "secondary": "white on grey30", "hazard": "daring white on crimson"}
       console.print(f"{pad}  [{colors.get(variant, 'white')}]  {label}  [/]")
    
    
    def render_text_field(comp, floor, indent):
       pad = "  " * indent
       label = comp.properties.get("label", "Enter")
       placeholder = comp.properties.get("placeholder", "")
       console.print(f"{pad}  {label}: [dim]┌──────────────────────────┐[/]")
       console.print(f"{pad}          [dim]│ {placeholder:<25}│[/]")
       console.print(f"{pad}          [dim]└──────────────────────────┘[/]")
    
    
    def render_row(comp, floor, indent):
       cross
    
    
    def render_column(comp, floor, indent):
       cross
    
    
    def render_image(comp, floor, indent):
       pad = "  " * indent
       alt = comp.properties.get("alt", "picture")
       console.print(f"{pad}  [dim]  [{alt}][/]")
    
    
    def render_divider(comp, floor, indent):
       pad = "  " * indent
       console.print(f"{pad}  {'─' * 50}")
    
    
    def render_chip(comp, floor, indent):
       pad = "  " * indent
       label = str(_resolve(comp, floor, "label", ""))
       console.print(f"{pad}  [on grey23] {label} [/]")
    
    
    def render_progress(comp, floor, indent):
       pad = "  " * indent
       raw_value = _resolve(comp, floor, "worth", 0)
       worth = max(0.0, min(1.0, _to_float(raw_value, 0.0)))
       label = str(_resolve(comp, floor, "label", ""))
       bar_len = int(worth * 40)
       bar = f"[green]{'█' * bar_len}[/][dim]{'░' * (40 - bar_len)}[/]"
       console.print(f"{pad}  {label}: {bar} {worth*100:.0f}%")
    
    
    for title, fn in [
       ("card", render_card), ("text", render_text), ("button", render_button),
       ("text-field", render_text_field), ("row", render_row), ("column", render_column),
       ("image", render_image), ("divider", render_divider), ("chip", render_chip),
       ("progress-bar", render_progress),
    ]:
       registry.register(title, fn)
    
    
    
    
    console.print("n[bold]Demo: A2UI reserving kind — agent generates a restaurant reservation UI[/]n")
    
    
    booking_surface = A2UISurface(
       surface_id="booking-form-1",
       parts=[
           A2UIComponent("root", "card", {"title": "  Reserve a Table"}, children=["c1", "c2", "c3", "c4", "c5", "c6"]),
           A2UIComponent("c1", "textual content", {"textual content": "", "dataBinding": "/restaurant/title", "fashion": "headline"}),
           A2UIComponent("c2", "textual content", {"textual content": "", "dataBinding": "/restaurant/delicacies", "fashion": "caption"}),
           A2UIComponent("c3", "divider", {}),
           A2UIComponent("c4", "text-field", {"label": "Date", "placeholder": "YYYY-MM-DD"}),
           A2UIComponent("c5", "text-field", {"label": "Friends", "placeholder": "1-12"}),
           A2UIComponent("c6", "button", {"label": "Reserve Now", "variant": "main", "motion": "submit_booking"}),
       ],
       data_model=A2UIDataModel({"restaurant": {"title": "Chez Laurent", "delicacies": "French Up to date • $$$$"}})
    )
    
    
    console.print(Panel(
       "n".be part of(json.dumps(m, indent=2)[:200] for m in booking_surface.to_messages()),
       title="[bold]A2UI JSONL stream (what goes over the wire)",
       border_style="yellow",
    ))
    
    
    console.print("[bold]Rendered by shopper widget registry:[/]n")
    registry.render_tree(booking_surface)
    
    
    console.print()
    t = Desk(title="A2UI Flat Part Checklist (Adjacency Mannequin)", field=field.ROUNDED)
    t.add_column("ID", fashion="cyan", width=8)
    t.add_column("Sort", fashion="inexperienced", width=14)
    t.add_column("Youngsters", fashion="yellow", width=20)
    t.add_column("Bindings", fashion="magenta", width=25)
    for c in booking_surface.parts:
       binding = c.properties.get("dataBinding", "")
       t.add_row(c.id, c.sort, ", ".be part of(c.kids) if c.kids else "—", binding or "—")
    console.print(t)

    We implement Google’s A2UI specification: a flat adjacency-list mannequin the place parts reference kids by ID slightly than nesting, making the format trivially streamable and simple for LLMs to generate incrementally. We construct a client-side Widget Registry that maps summary sort strings like “card”, “text-field”, and “progress-bar” to concrete terminal renderers, mirroring how a manufacturing app maps them to React parts or Flutter widgets. We show the complete cycle with a restaurant reserving kind, full with knowledge mannequin bindings that decouple dynamic values from UI construction, precisely because the A2UI spec prescribes.

    Copy CodeCopiedUse a unique Browser
    hdr(3, "Generative UI — LLM Produces Reside Interfaces",
       "The agent generates A2UI element timber dynamically based mostly on the question.n"
       "That is the core of 'Generative UI' — context-adaptive interfacesn"
       "that go far past text-only chat responses.")
    
    
    A2UI_GENERATION_PROMPT = """
    You might be an A2UI Generative UI agent. Given a consumer question, you generate a wealthy 
    interactive interface — NOT textual content. You output an A2UI element tree as JSON.
    
    
    RULES:
    1. Output a flat checklist of parts utilizing the adjacency mannequin (kids = checklist of IDs).
    2. Out there element varieties: card, textual content, button, text-field, row, column, divider, chip, picture, progress-bar, choose, date-picker, data-table
    3. Embody a separate "dataModel" object for dynamic values. Use "/path/to/worth" bindings.
    4. The ROOT element ought to be a "card" with all others as descendants.
    5. Take into consideration what UI BEST serves the consumer — varieties for enter, tables for knowledge, 
      progress bars for standing, chips for tags, buttons for actions.
    
    
    OUTPUT FORMAT (strict JSON, nothing else):
    {
     "surfaceId": "unique-id",
     "parts": [
       {"id": "root", "type": "card", "title": "...", "children": ["c1", "c2"]},
       {"id": "c1", "sort": "textual content", "textual content": "...", "fashion": "headline"},
       ...
     ],
     "dataModel": { ... }
    }
    """
    
    
    
    
    def generate_ui(user_query: str) -> Non-obligatory[A2UISurface]:
       console.print(f"  [dim]Producing UI for:[/] [bold]{user_query}[/]")
       response = llm([
           {"role": "system", "content": A2UI_GENERATION_PROMPT},
           {"role": "user", "content": user_query},
       ], max_tokens=1200)
    
    
       if not response:
           return None
    
    
       uncooked = response.decisions[0].message.content material
       attempt:
           cleaned = re.sub(r'```jsons*|s*```', '', uncooked).strip()
           spec = json.masses(cleaned)
       besides json.JSONDecodeError:
           console.print(f"[red]Did not parse generated UI: {uncooked[:200]}[/]")
           return None
    
    
       parts = []
       for c in spec.get("parts", []):
           parts.append(A2UIComponent(
               id=c.get("id", str(uuid.uuid4())[:6]),
               sort=c.get("sort", "textual content"),
               properties={ok: v for ok, v in c.objects() if ok not in ("id", "sort", "kids")},
               kids=c.get("kids", []),
           ))
    
    
       floor = A2UISurface(
           surface_id=spec.get("surfaceId", f"gen-{uuid.uuid4().hex[:6]}"),
           parts=parts,
           data_model=A2UIDataModel(spec.get("dataModel", {})),
       )
    
    
       return floor
    
    
    
    
    def demo_generative_ui(question: str):
       floor = generate_ui(question)
       if floor:
           console.print(f"n[bold green]Generated {len(floor.parts)} parts:[/]")
           registry.render_tree(floor)
    
    
           console.print()
           varieties = {}
           for c in floor.parts:
               varieties[c.type] = varieties.get(c.sort, 0) + 1
           console.print("  [dim]Part varieties used:[/] " + ", ".be part of(f"[cyan]{t}[/]×{n}" for t, n in varieties.objects()))
    
    
           if floor.data_model.knowledge:
               console.print(f"  [dim]Knowledge mannequin keys:[/] {checklist(floor.data_model.knowledge.keys())}")
           console.print()
    
    
    
    
    console.print("n[bold]Demo 1: Agent generates an onboarding kind[/]")
    demo_generative_ui(
       "Create a consumer onboarding circulate: gather title, electronic mail, function (dropdown), "
       "most popular notification methodology (chips), and a 'Get Began' button."
    )
    
    
    console.print("n[bold]Demo 2: Agent generates an information dashboard[/]")
    demo_generative_ui(
       "Present a challenge standing dashboard with: challenge title 'Atlas v2', "
       "4 crew members, dash progress at 68%, 3 blockers flagged as vital, "
       "and motion buttons for 'View Backlog' and 'Schedule Standup'."
    )
    
    
    console.print("n[bold]Demo 3: Agent generates a affirmation dialog[/]")
    demo_generative_ui(
       "Present a cost affirmation: $2,450 cost to Visa ending 4242, "
       "order #ORD-8891, with Approve and Decline buttons."
    )
    

    We hand the keys to the LLM and let it generate full A2UI element timber at runtime from plain English descriptions, that is Generative UI in its purest kind. We immediate the mannequin with the A2UI schema and element catalog, and it produces absolutely structured surfaces with playing cards, varieties, chips, progress bars, and knowledge bindings, selecting the perfect UI sample for every question. We run three demos, an onboarding circulate, a challenge dashboard, and a cost affirmation, displaying how the identical agent adapts its interface to wildly completely different contexts with no single hardcoded format.

    Copy CodeCopiedUse a unique Browser
    hdr(4, "State Synchronization — Shared State Between Agent & UI",
       "AG-UI syncs state bidirectionally utilizing STATE_SNAPSHOT and STATE_DELTA.n"
       "The agent IS the state machine; the UI IS the renderer.n"
       "JSON Patch diffs preserve updates minimal and environment friendly.")
    
    
    
    
    class SharedState:
       def __init__(self, preliminary: dict = None):
           self.state: dict = preliminary or {}
           self.historical past: checklist[dict] = []
           self.model: int = 0
    
    
       def snapshot(self) -> AGUIEvent:
           return AGUIEvent(AGUIEventType.STATE_SNAPSHOT, {"state": copy.deepcopy(self.state), "model": self.model})
    
    
       def apply_delta(self, operations: checklist[dict]) -> AGUIEvent:
           for op in operations:
               path_parts = [p for p in op["path"].cut up("/") if p]
               goal = self.state
               for half in path_parts[:-1]:
                   if isinstance(goal, dict):
                       goal = goal.setdefault(half, {})
                   elif isinstance(goal, checklist) and half.isdigit():
                       goal = goal[int(part)]
    
    
               key = path_parts[-1] if path_parts else None
               if secret's None:
                   proceed
    
    
               if op["op"] == "exchange":
                   goal[key] = op["value"]
               elif op["op"] == "add":
                   if isinstance(goal, checklist) and key.isdigit():
                       goal.insert(int(key), op["value"])
                   else:
                       goal[key] = op["value"]
               elif op["op"] == "take away":
                   if isinstance(goal, dict):
                       goal.pop(key, None)
    
    
           self.model += 1
           self.historical past.append({"model": self.model, "ops": operations})
           return AGUIEvent(AGUIEventType.STATE_DELTA, {"delta": operations, "model": self.model})
    
    
    
    
    console.print("n[bold]Demo: Doc overview pipeline — 3 brokers, shared state[/]n")
    
    
    stream = AGUIEventStream()
    state = SharedState({
       "doc": {"title": "This autumn Technique Report", "standing": "draft", "word_count": 2840},
       "pipeline": {"stage": "analysis", "progress": 0.0},
       "brokers": {"lively": "Researcher", "queue": ["Editor", "Reviewer"]},
       "suggestions": [],
    })
    
    
    def log_event(occasion: AGUIEvent):
       if occasion.sort in (AGUIEventType.STATE_SNAPSHOT, AGUIEventType.STATE_DELTA):
           if occasion.sort == AGUIEventType.STATE_DELTA:
               ops = occasion.knowledge.get("delta", [])
               for op in ops:
                   console.print(f"  [yellow]STATE_DELTA[/] v{occasion.knowledge.get('model')}: "
                                 f"[cyan]{op['op']}[/] {op['path']} → {op.get('worth', '∅')}")
           else:
               console.print(f"  [yellow]STATE_SNAPSHOT[/] v{occasion.knowledge.get('model')}: {checklist(occasion.knowledge['state'].keys())}")
    
    
    stream.on(log_event)
    
    
    stream.emit(state.snapshot())
    
    
    console.print("n[bold green]▸ Researcher agent working...[/]")
    stream.emit(state.apply_delta([
       {"op": "replace", "path": "/pipeline/stage", "value": "research_complete"},
       {"op": "replace", "path": "/pipeline/progress", "value": 0.33},
       {"op": "add",     "path": "/feedback/0", "value": {"agent": "Researcher", "note": "Added 4 new data sources"}},
    ]))
    
    
    console.print("n[bold green]▸ Editor agent working...[/]")
    stream.emit(state.apply_delta([
       {"op": "replace", "path": "/agents/active", "value": "Editor"},
       {"op": "replace", "path": "/pipeline/stage", "value": "editing"},
       {"op": "replace", "path": "/pipeline/progress", "value": 0.66},
       {"op": "replace", "path": "/document/word_count", "value": 3150},
    ]))
    
    
    console.print("n[bold green]▸ Reviewer agent working...[/]")
    stream.emit(state.apply_delta([
       {"op": "replace", "path": "/agents/active", "value": "Reviewer"},
       {"op": "replace", "path": "/pipeline/stage", "value": "review_complete"},
       {"op": "replace", "path": "/pipeline/progress", "value": 1.0},
       {"op": "replace", "path": "/document/status", "value": "approved"},
    ]))
    
    
    console.print(Panel(
       json.dumps(state.state, indent=2),
       title="[bold]Ultimate shared state after pipeline",
       border_style="inexperienced",
    ))
    
    
    t = Desk(title="State Historical past (variations)", field=field.ROUNDED)
    t.add_column("Model", fashion="cyan", justify="middle")
    t.add_column("Operations", fashion="yellow")
    for h in state.historical past:
       ops_summary = "; ".be part of(f"{o['op']} {o['path']}" for o in h["ops"])
       t.add_row(str(h["version"]), ops_summary[:70])
    console.print(t)
    
    
    
    
    hdr(5, "Human-in-the-Loop — AG-UI INTERRUPT Occasions",
       "When an agent hits a high-stakes motion, it emits an INTERRUPT occasion.n"
       "The frontend renders an approval UI. Execution pauses till the humann"
       "approves, rejects, or modifies. State is preserved all through.")
    
    
    
    
    @dataclass
    class InterruptRequest:
       interrupt_id: str
       action_description: str
       risk_level: str
       affected_resources: checklist[str]
       proposed_changes: dict
       choices: checklist[str] = discipline(default_factory=lambda: ["approve", "reject", "modify"])
    
    
    
    
    @dataclass
    class InterruptResponse:
       interrupt_id: str
       determination: str
       modifications: Non-obligatory[dict] = None
    
    
    
    
    class InterruptableAgent:
       RISK_RULES = {
           "delete":     "vital",
           "cost":    "vital",
           "email_all":  "excessive",
           "publish":    "excessive",
           "replace":     "medium",
           "learn":       "low",
       }
    
    
       def __init__(self):
           self.stream = AGUIEventStream()
           self.pending_interrupts: dict[str, InterruptRequest] = {}
    
    
       def assess_and_maybe_interrupt(self, motion: str, particulars: dict) -> Non-obligatory[InterruptRequest]:
           threat = "low"
           for key phrase, degree in self.RISK_RULES.objects():
               if key phrase in motion.decrease():
                   threat = degree
                   break
    
    
           if threat in ("vital", "excessive"):
               interrupt = InterruptRequest(
                   interrupt_id=str(uuid.uuid4())[:8],
                   action_description=motion,
                   risk_level=threat,
                   affected_resources=particulars.get("assets", []),
                   proposed_changes=particulars.get("modifications", {}),
               )
               self.pending_interrupts[interrupt.interrupt_id] = interrupt
    
    
               self.stream.emit(AGUIEvent(AGUIEventType.INTERRUPT, {
                   "interrupt_id": interrupt.interrupt_id,
                   "motive": threat,
                   "description": interrupt.action_description,
                   "affected_resources": interrupt.affected_resources,
                   "proposed_changes": interrupt.proposed_changes,
                   "choices": interrupt.choices,
               }))
               return interrupt
           return None
    
    
       def resolve_interrupt(self, response: InterruptResponse) -> str:
           interrupt = self.pending_interrupts.pop(response.interrupt_id, None)
           if not interrupt:
               return "No pending interrupt discovered."
    
    
           if response.determination == "approve":
               return f" APPROVED: '{interrupt.action_description}' executing now."
           elif response.determination == "reject":
               return f" REJECTED: '{interrupt.action_description}' cancelled."
           elif response.determination == "modify":
               return f"  MODIFIED: '{interrupt.action_description}' up to date with: {response.modifications}"
           return f"Unknown determination: {response.determination}"
    
    
    
    
    console.print("n[bold]Demo: Agent encounters actions of various threat ranges[/]n")
    agent = InterruptableAgent()
    
    
    actions = [
       ("Read user profile",      {"resources": ["user:123"]}),
       ("Replace consumer preferences", {"assets": ["user:123"], "modifications": {"theme": "darkish"}}),
       ("Delete consumer account",     {"assets": ["user:123", "data:all"], "modifications": {"motion": "permanent_delete"}}),
       ("E-mail all 12,000 customers",  {"assets": ["email:newsletter"], "modifications": {"topic": "Massive Announcement"}}),
       ("Publish weblog put up",       {"assets": ["post:draft-42"], "modifications": {"standing": "public"}}),
    ]
    
    
    def event_logger(occasion):
       if occasion.sort == AGUIEventType.INTERRUPT:
           d = occasion.knowledge
           risk_style = {"vital": "daring crimson", "excessive": "daring yellow"}.get(d["reason"], "white")
           console.print(f"n  [bold] INTERRUPT EVENT[/]")
           console.print(f"    Danger: [{risk_style}]{d['reason'].higher()}[/]")
           console.print(f"    Motion: {d['description']}")
           console.print(f"    Affected: {d['affected_resources']}")
           console.print(f"    Choices: {d['options']}")
    
    
    agent.stream.on(event_logger)
    
    
    outcomes = []
    for action_desc, particulars in actions:
       interrupt = agent.assess_and_maybe_interrupt(action_desc, particulars)
       if interrupt:
           determination = "reject" if interrupt.risk_level == "vital" else "approve"
           outcome = agent.resolve_interrupt(InterruptResponse(interrupt.interrupt_id, determination))
       else:
           outcome = f" AUTO-EXECUTED: '{action_desc}' (low threat, no approval wanted)"
    
    
       outcomes.append((action_desc, outcome))
    
    
    console.print()
    t = Desk(title="Execution Outcomes", field=field.ROUNDED, show_lines=True)
    t.add_column("Motion", fashion="white", width=28)
    t.add_column("Consequence", fashion="dim", width=55)
    for action_desc, end in outcomes:
       t.add_row(action_desc, outcome)
    console.print(t)

    We construct a SharedState engine that emits AG-UI STATE_SNAPSHOT and STATE_DELTA occasions utilizing JSON Patch operations, preserving the agent backend and the frontend UI completely synchronized by way of each mutation. We show this with a three-agent doc overview pipeline through which a Researcher, Editor, and Reviewer every modify the shared state in sequence, and the frontend sees each change the moment it happens. We then implement the AG-UI INTERRUPT sample, through which the agent assesses threat ranges for proposed actions, emits interrupt occasions for any harmful actions, and pauses execution till a human approves, rejects, or modifies the plan.

    Copy CodeCopiedUse a unique Browser
    hdr(6, "Full Pipeline — LLM-Pushed Adaptive UI",
       "The entire Agentic UI structure in a single pipeline:n"
       "  Consumer question → Intent evaluation → UI sample choice →n"
       "  A2UI technology → AG-UI occasion streaming → State sync → Render")
    
    
    
    
    UI_ROUTER_PROMPT = """
    You're a UI routing agent. Given a consumer question, determine what sort of UI to generate.
    
    
    RESPOND IN JSON ONLY:
     wizard 
    """
    
    
    
    
    class AgenticUIPipeline:
       def __init__(self):
           self.stream = AGUIEventStream()
           self.state = SharedState({"pipeline": {"stage": "idle"}, "renders": 0})
           self.interrupt_agent = InterruptableAgent()
    
    
       def route(self, question: str) -> dict:
           resp = llm([
               {"role": "system", "content": UI_ROUTER_PROMPT},
               {"role": "user", "content": query},
           ], max_tokens=300)
    
    
           if not resp:
               return {"intent": "dashboard", "reasoning": "fallback", "ui_complexity": "easy",
                       "needs_approval": False, "data_requirements": []}
           uncooked = resp.decisions[0].message.content material
           attempt:
               return json.masses(re.sub(r'```jsons*|s*```', '', uncooked).strip())
           besides json.JSONDecodeError:
               return {"intent": "dashboard", "reasoning": "parse_fallback", "ui_complexity": "easy",
                       "needs_approval": False, "data_requirements": []}
    
    
       def run(self, user_query: str):
           run_id = str(uuid.uuid4())[:8]
           console.print(Panel(f"[bold]{user_query}[/]", title=" Consumer Question", border_style="white"))
    
    
           self.stream.emit(AGUIEvent(AGUIEventType.RUN_STARTED, {"run_id": run_id}))
           self.stream.emit(AGUIEvent(AGUIEventType.STEP_STARTED, {"step": "routing"}))
    
    
           routing = self.route(user_query)
           console.print(f"n  [bold cyan] Router Choice:[/]")
           console.print(f"    Intent: [green]{routing.get('intent')}[/] | "
                         f"Complexity: [yellow]{routing.get('ui_complexity')}[/] | "
                         f"Approval: {'' if routing.get('needs_approval') else ''}")
           console.print(f"    Reasoning: [dim]{routing.get('reasoning', '')}[/]")
    
    
           self.stream.emit(AGUIEvent(AGUIEventType.STEP_FINISHED, {"step": "routing", "outcome": routing}))
    
    
           self.state.apply_delta([
               {"op": "replace", "path": "/pipeline/stage", "value": "generating"},
           ])
    
    
           self.stream.emit(AGUIEvent(AGUIEventType.STEP_STARTED, {"step": "generating_ui"}))
    
    
           msg_id = str(uuid.uuid4())[:8]
           self.stream.emit(AGUIEvent(AGUIEventType.TEXT_MESSAGE_START, {"message_id": msg_id}))
           self.stream.emit(AGUIEvent(AGUIEventType.TEXT_MESSAGE_CONTENT, {
               "message_id": msg_id,
               "delta": f"Constructing a {routing.get('intent')} interface for you..."
           }))
           self.stream.emit(AGUIEvent(AGUIEventType.TEXT_MESSAGE_END, {"message_id": msg_id}))
    
    
           floor = generate_ui(user_query)
           self.stream.emit(AGUIEvent(AGUIEventType.STEP_FINISHED, {"step": "generating_ui"}))
    
    
           if routing.get("needs_approval") and floor:
               self.stream.emit(AGUIEvent(AGUIEventType.INTERRUPT, {
                   "motive": "ui_confirmation",
                   "description": f"Generated {len(floor.parts)} element UI. Render it?",
                   "choices": ["render", "regenerate", "cancel"],
               }))
               console.print("n  [bold yellow]  INTERRUPT:[/] UI generated, awaiting human approval...")
               console.print("  [green]→ Auto-approving for demo...[/]")
    
    
           if floor:
               self.state.apply_delta([
                   {"op": "replace", "path": "/pipeline/stage", "value": "rendering"},
                   {"op": "replace", "path": "/renders", "value": self.state.state.get("renders", 0) + 1},
               ])
    
    
               console.print(f"n[bold green]  Rendered Interface ({len(floor.parts)} parts):[/]n")
               registry.render_tree(floor)
    
    
               self.stream.emit(AGUIEvent(AGUIEventType.CUSTOM, {
                   "subtype": "a2ui_surface",
                   "floor": floor.to_messages(),
               }))
    
    
           self.state.apply_delta([{"op": "replace", "path": "/pipeline/stage", "value": "complete"}])
           self.stream.emit(AGUIEvent(AGUIEventType.RUN_FINISHED, {"run_id": run_id, "standing": "success"}))
    
    
           console.print()
           event_counts = {}
           for e in self.stream.occasions:
               event_counts[e.type.value] = event_counts.get(e.sort.worth, 0) + 1
           t = Desk(title="Pipeline Occasion Abstract", field=field.ROUNDED)
           t.add_column("Occasion Sort", fashion="cyan")
           t.add_column("Rely", justify="middle", fashion="inexperienced")
           for etype, depend in sorted(event_counts.objects()):
               t.add_row(etype, str(depend))
           console.print(t)
    
    
    
    
    pipeline = AgenticUIPipeline()
    
    
    console.print("n[bold]Demo 1: Agent builds a settings kind[/]")
    pipeline.run(
       "Create a notification settings panel the place I can toggle electronic mail/SMS/push, "
       "set quiet hours, and decide a notification sound."
    )
    
    
    pipeline.stream = AGUIEventStream()
    pipeline.state = SharedState({"pipeline": {"stage": "idle"}, "renders": 0})
    
    
    console.print("n[bold]Demo 2: Agent builds an order monitoring dashboard[/]")
    pipeline.run(
       "Present order #ORD-7742 standing: shipped through FedEx, monitoring 789456123, "
       "estimated supply March 24, 2 of three objects delivered. Present a progress bar "
       "and motion buttons for 'Contact Help' and 'Request Refund'."
    )
    
    
    
    
    hdr(7, "Incremental UI Updates — Reside Floor Modification",
       "A2UI surfaces are incrementally updateable. The agent can add, take away,n"
       "or modify parts and knowledge bindings on a reside floor withoutn"
       "regenerating the entire tree. Important for real-time collaboration.")
    
    
    
    
    class LiveSurface:
       def __init__(self, floor: A2UISurface):
           self.floor = floor
           self.update_log: checklist[str] = []
    
    
       def add_component(self, element: A2UIComponent, parent_id: Non-obligatory[str] = None):
           self.floor.parts.append(element)
           if parent_id:
               for c in self.floor.parts:
                   if c.id == parent_id:
                       c.kids.append(element.id)
                       break
           self.update_log.append(f"ADD  {element.sort}#{element.id} → dad or mum:{parent_id or 'root'}")
    
    
       def update_component(self, component_id: str, new_props: dict):
           for c in self.floor.parts:
               if c.id == component_id:
                   c.properties.replace(new_props)
                   self.update_log.append(f"UPD  #{component_id} props: {checklist(new_props.keys())}")
                   return
           self.update_log.append(f"ERR  #{component_id} not discovered")
    
    
       def remove_component(self, component_id: str):
           self.floor.parts = [c for c in self.surface.components if c.id != component_id]
           for c in self.floor.parts:
               if component_id in c.kids:
                   c.kids.take away(component_id)
           self.update_log.append(f"DEL  #{component_id}")
    
    
       def update_data(self, path: str, worth: Any):
           self.floor.data_model.knowledge = _set_nested(self.floor.data_model.knowledge, path, worth)
           self.update_log.append(f"DATA {path} = {worth}")
    
    
    
    
    def _set_nested(d: dict, path: str, worth: Any) -> dict:
       components = [p for p in path.split("/") if p]
       d = copy.deepcopy(d)
       present = d
       for p in components[:-1]:
           present = present.setdefault(p, {})
       if components:
           present[parts[-1]] = worth
       return d
    
    
    
    
    console.print("n[bold]Demo: Reside collaborative enhancing — agent modifies UI in real-time[/]n")
    
    
    preliminary = A2UISurface(
       surface_id="task-board",
       parts=[
           A2UIComponent("board", "card", {"title": "  Sprint Board"}, children=["t1", "t2", "t3"]),
           A2UIComponent("t1", "chip", {"label": "AUTH-101: Login circulate", "variant": "in_progress"}),
           A2UIComponent("t2", "chip", {"label": "AUTH-102: OAuth setup", "variant": "todo"}),
           A2UIComponent("t3", "chip", {"label": "AUTH-103: 2FA", "variant": "todo"}),
       ],
       data_model=A2UIDataModel({"dash": {"title": "Dash 14", "velocity": 21}}),
    )
    
    
    reside = LiveSurface(preliminary)
    
    
    console.print("[bold]Preliminary board:[/]")
    registry.render_tree(reside.floor)
    
    
    console.print("n[bold yellow]Agent updating board in real-time...[/]n")
    
    
    reside.update_component("t1", {"variant": "finished", "label": " AUTH-101: Login circulate"})
    reside.update_component("t2", {"variant": "in_progress", "label": " AUTH-102: OAuth setup"})
    reside.add_component(
       A2UIComponent("t4", "chip", {"label": "AUTH-104: Password reset", "variant": "todo"}),
       parent_id="board"
    )
    reside.update_data("/dash/velocity", 25)
    reside.remove_component("t3")
    
    
    console.print("[bold]Up to date board:[/]")
    registry.render_tree(reside.floor)
    
    
    console.print()
    t = Desk(title="Incremental Replace Log", field=field.ROUNDED)
    t.add_column("#", fashion="cyan", width=4, justify="middle")
    t.add_column("Operation", fashion="yellow")
    for i, entry in enumerate(reside.update_log, 1):
       t.add_row(str(i), entry)
    console.print(t)

    We wire each piece collectively right into a single AgenticUIPipeline class that takes a consumer question, classifies its intent with an LLM router, selects the appropriate UI sample, generates an A2UI floor, streams the whole course of over AG-UI occasions, manages shared state, and renders the outcome, the entire structure in a single run. We then construct a LiveSurface class that helps incremental A2UI updates: including, modifying, and eradicating parts on an already-rendered floor with out regenerating the entire tree, which is important for real-time collaborative experiences. We demo this with a dash board that an agent updates reside, marking duties full, including new ones, and adjusting knowledge mannequin values, all tracked in an in depth operation log.

    Copy CodeCopiedUse a unique Browser
    hdr(8, "Reference — The Agentic UI Protocol Stack",
       "How AG-UI, A2UI, MCP, and A2A match collectively within the fashionable agent structure.")
    
    
    console.print(Panel("""
    [bold white]THE AGENTIC UI STACK (2026)[/]
    
    
     ┌──────────────────────────────────────────────────────┐
     │  [bold cyan]USER INTERFACE[/]  (React, Flutter, SwiftUI, Terminal)  │
     │  Renders native widgets from element specs          │
     └────────────────────────┬─────────────────────────────┘
                              │  A2UI element timber (JSON)
                              │  AG-UI occasions (SSE / WebSocket)
     ┌────────────────────────┴─────────────────────────────┐
     │  [bold yellow]AG-UI PROTOCOL[/]  (Agent  Consumer Interplay)          │
     │  • Occasion streaming (TEXT, TOOL_CALL, STATE, INTERRUPT)│
     │  • Bidirectional state sync (SNAPSHOT + DELTA)        │
     │  • Human-in-the-loop (INTERRUPT → approval circulate)      │
     └────────────────────────┬─────────────────────────────┘
                              │
     ┌────────────────────────┴─────────────────────────────┐
     │  [bold magenta]AGENT RUNTIME[/]  (LangGraph, CrewAI, customized, and so on.)    │
     │  • Generates A2UI surfaces (Generative UI)            │
     │  • Manages shared state                               │
     │  • Orchestrates sub-agents through A2A protocol           │
     │  • Accesses instruments through MCP protocol                    │
     └────────────────────────┬─────────────────────────────┘
                              │
     ┌────────────────────────┴─────────────────────────────┐
     │  [bold green]LLM BACKBONE[/]  (GPT, Claude, Gemini, and so on.)           │
     │  • Generates element timber as structured output     │
     │  • Causes about UI patterns per context              │
     │  • Streams tokens for real-time rendering              │
     └──────────────────────────────────────────────────────┘
    
    
    [dim]Protocol roles:
     AG-UI  = Agent  Consumer (streaming occasions, state, HITL)
     A2UI   = Agent → UI (declarative element specs)
     A2A    = Agent → Agent (delegation, sub-agents)
     MCP    = Agent → Instruments (operate calling, context)[/]
    """, title="[bold]Structure Reference", border_style="cyan"))
    
    
    
    
    ref = Desk(title="Agentic UI Ideas — Fast Reference", field=field.DOUBLE_EDGE, show_lines=True)
    ref.add_column("Idea", fashion="daring cyan", width=22)
    ref.add_column("What It Does", fashion="white", width=35)
    ref.add_column("Key Mechanism", fashion="yellow", width=28)
    
    
    ref.add_row("AG-UI Occasions",     "Stream agent actions to frontend in real-time",  "SSE/WebSocket + ~16 occasion varieties")
    ref.add_row("A2UI Elements",  "Declarative UI timber — secure, moveable, native",  "Flat JSON + widget registry")
    ref.add_row("State Sync",       "Hold agent & UI state in lockstep",              "STATE_SNAPSHOT + STATE_DELTA")
    ref.add_row("Generative UI",    "LLM generates UI at runtime, not simply textual content",     "A2UI JSON as structured output")
    ref.add_row("INTERRUPT (HITL)", "Pause execution for human approval",             "INTERRUPT occasion → approval circulate")
    ref.add_row("Incremental Replace","Modify reside surfaces with out full regeneration", "A2UI updateComponents message")
    ref.add_row("Knowledge Binding",     "UI reads from a shared knowledge mannequin",              "JSON Pointer paths (/path/to/val)")
    ref.add_row("Widget Registry",  "Consumer maps summary varieties to native widgets",   "Catalog of trusted parts")
    
    
    console.print(ref)
    
    
    
    
    console.print(Panel(
       "[bold green]Tutorial full![/]nn"
       "[dim]What you constructed:[/]n"
       "  • A full AG-UI occasion system with all 16 occasion typesn"
       "  • An A2UI renderer with flat adjacency-list parts + knowledge bindingn"
       "  • LLM-powered Generative UI that creates interfaces from pure languagen"
       "  • Bidirectional state sync with JSON Patch deltasn"
       "  • Human-in-the-loop interrupt and approval flowsn"
       "  • Incremental reside floor updatesnn"
       "[dim]To go additional:[/]n"
       "  • Serve AG-UI occasions over actual SSE with FastAPIn"
       "  • Connect with CopilotKit React parts for an actual frontendn"
       "  • Use Pydantic AI's AGUIAdapter for manufacturing agent hostingn"
       "  • Add A2A protocol for multi-agent delegationn"
       "  • Deploy on AWS Bedrock AgentCore with native AG-UI assist",
       title="[bold] What's Subsequent?",
       border_style="inexperienced",
       padding=(1, 2),
    ))
    

    We shut with a visible protocol stack diagram displaying precisely how AG-UI, A2UI, A2A, and MCP match collectively within the fashionable agentic structure, from the LLM spine on the backside to the native UI on the high. We offer a quick-reference desk mapping each idea we constructed, occasion streaming, element timber, state sync, generative UI, interrupts, incremental updates, knowledge binding, and widget registries, to their core mechanisms. We level the way in which ahead to manufacturing: serving AG-UI occasions over actual SSE with FastAPI, connecting to CopilotKit React parts, utilizing Pydantic AI’s AGUIAdapter, and deploying on AWS Bedrock AgentCore.

    In conclusion, we’ve got a completely useful Agentic UI pipeline that takes a easy natural-language question and transforms it right into a structured, interactive interface powered by an clever agent. We don’t simply assemble parts; we perceive how every layer operates and connects, from real-time AG-UI occasion streaming and declarative A2UI interface definitions to state synchronization by way of JSON Patch and enforced human-in-the-loop security mechanisms. This readability permits us to motive about system conduct, debug successfully, and lengthen performance with out counting on black-box abstractions. Additionally, we depart with the flexibility to design our personal agent-driven UI methods, adapt them to completely different use circumstances, and confidently construct production-ready experiences the place brokers and interfaces evolve collectively in a managed, clear, and scalable method.


    Try the Full Codes with Notebook here. Additionally, be happy to comply with us on Twitter and don’t neglect to hitch our 130k+ ML SubReddit and Subscribe to our Newsletter. Wait! are you on telegram? now you can join us on telegram as well.

    Have to associate with us for selling your GitHub Repo OR Hugging Face Web page OR Product Launch OR Webinar and so on.? Connect with us

    The put up A Coding Deep Dive into Agentic UI, Generative UI, State Synchronization, and Interrupt-Pushed Approval Flows appeared first on MarkTechPost.



    Source link

    Naveed Ahmad

    Naveed Ahmad is a technology journalist and AI writer at ArticlesStock, covering artificial intelligence, machine learning, and emerging tech policy. Read his latest articles.

    Related Posts

    Y Combinator alum Skio sells for $105M money, solely raised $8M, founder says

    01/05/2026

    As Tim Prepare dinner steps down, Apple hit file gross sales — however a chip scarcity looms

    01/05/2026

    Moonshot AI Open-Sources FlashKDA: CUTLASS Kernels for Kimi Delta Consideration with Variable-Size Batching and H20 Benchmarks

    01/05/2026
    Leave A Reply Cancel Reply

    Categories
    • AI
    Recent Comments
      Facebook X (Twitter) Instagram Pinterest
      © 2026 ThemeSphere. Designed by ThemeSphere.

      Type above and press Enter to search. Press Esc to cancel.