A2UI Basics: Declarative Agent-to-UI Composition¶
Demonstrates the UI namespace for building rich agent UIs declaratively.
Key concepts:
UIComponent: frozen dataclass with composition operators
UI.text(), UI.button(), UI.text_field(): component factories
UI.bind(), UI.required(): data binding and validation
UI.surface(): named UI surface (compilation root)
compile_surface(): nested Python tree → flat A2UI JSON
Operators: | (Row), >> (Column), + (sibling group)
Tip
What you’ll learn How to use operator syntax for composing agents.
Source: 70_a2ui_basics.py
from adk_fluent._ui import (
UI,
UIBinding,
UICheck,
UIComponent,
UISurface,
compile_surface,
)
# --- 1. Component creation ---
text = UI.text("Hello, World!")
assert text._kind == "Text"
button = UI.button("Click Me")
assert button._kind == "Button"
field = UI.text_field("Name")
assert field._kind == "TextField"
# --- 2. Composition operators ---
# | creates a Row (horizontal layout)
row = UI.text("Left") | UI.text("Right")
assert row._kind == "Row"
assert len(row._children) == 2
# >> creates a Column (vertical layout)
col = UI.text("Top") >> UI.text("Bottom")
assert col._kind == "Column"
assert len(col._children) == 2
# Nest them
layout = (UI.text("A") | UI.text("B")) >> UI.text("Footer")
assert layout._kind == "Column"
# --- 3. Data binding ---
binding = UI.bind("/user/name")
assert isinstance(binding, UIBinding)
assert binding.path == "/user/name"
# --- 4. Validation ---
check = UI.required("Name is required")
assert isinstance(check, UICheck)
assert check.fn == "required"
email_check = UI.email("Invalid email")
assert email_check.fn == "email"
# --- 5. Surfaces ---
surface = UI.surface("contact_form", UI.text("Contact Us") >> UI.text_field("Name"))
assert isinstance(surface, UISurface)
assert surface.name == "contact_form"
# Surface with theme
themed = surface.with_theme(primaryColor="#3b82f6")
assert len(themed.theme) == 1
# Surface with initial data
with_data = surface.with_data(name="")
assert len(with_data.data) == 1
# --- 6. Compilation ---
msgs = compile_surface(surface)
assert len(msgs) == 2 # createSurface + updateComponents
create_msg = msgs[0]
assert "createSurface" in create_msg
assert create_msg["createSurface"]["surfaceId"] == "contact_form"
update_msg = msgs[1]
assert "updateComponents" in update_msg
components = update_msg["updateComponents"]["components"]
assert len(components) >= 2 # Column + TextField (+ Text)
# --- 7. Generic component (escape hatch) ---
custom = UI.component("BarChart", data="test", x="date", y="value")
assert custom._kind == "BarChart"
# --- 8. Presets ---
form = UI.form("Feedback", fields={"name": "text", "email": "email", "message": "longText"})
assert isinstance(form, UISurface)
dashboard = UI.dashboard("Metrics", cards=[{"title": "Users", "bind": "/users"}])
assert isinstance(dashboard, UISurface)
confirm = UI.confirm("Delete this item?")
assert isinstance(confirm, UISurface)
table = UI.table(["Name", "Email"], data_bind="/users")
assert isinstance(table, UISurface)
wizard = UI.wizard("Setup", steps=[("Welcome", UI.text("Hi")), ("Done", UI.text("Bye"))])
assert isinstance(wizard, UISurface)
print("All A2UI basics assertions passed!")