Skip to content

Event System

Events flow from user interactions back to agents, enabling real-time communication between the generated UI and the controlling agent.

type EventType =
// Data events
| "data:submit" // Form submission
| "data:change" // Real-time component changes (opt-in)
// Lifecycle events
| "lifecycle:session_start"
| "lifecycle:session_end"
| "lifecycle:stack_push"
| "lifecycle:stack_pop"
| "lifecycle:focus"
| "lifecycle:blur"
// Interaction events
| "interaction:click"
| "interaction:hover"
| "interaction:scroll"
// Error events
| "error:validation"
| "error:connection";

Every user action is delivered as a canonical flat ActionEnvelope:

interface ActionEnvelope<TPayload = JsonValue> {
sessionId: string;
type: EventType;
payload?: TPayload; // For `data:submit`: { action, data?, tool? }
stackIndex?: number;
pageId?: string;
clientSeq?: number;
}

The envelope is flat by design — no nested event / context / meta blocks. Session-level diagnostic metadata (device info, interface context, user identity) is captured once at subscribe time on the server and doesn’t need to ride per-delivery. See Three-channel topology §“Two envelope shapes, not one” for the full rationale.

Agents specify what events they want when calling ggui_push:

ggui_push({
prompt: "Let user pick travel dates",
schema: {
/* optional output schema */
},
subscribe: {
events: ["data:submit", "lifecycle:stack_pop"],
components: {
"search-input": {
stream: true,
events: ["data:change"],
},
},
},
});

If no subscription is specified, agents receive:

subscribe: {
events: ["data:submit", "lifecycle:session_end"];
}

The agent SDK provides the following MCP tools:

ToolDescription
ggui_pushPush a new UI onto the session stack
ggui_popRemove the top UI from the stack
ggui_receiveWait for and receive user events
ggui_get_sessionGet current session state
ggui_closeClose a session

Real-time communication uses WebSocket with these message types:

generation:start → generation:planning → generation:building →
generation:compiling → generation:complete

These events drive the built-in progress UI in GguiSession, showing users real-time feedback as their UI is being generated.

The React SDK provides hooks and components for consuming events:

<GguiSession
sessionId="sess_abc"
onBeforeAction={(data, meta) => {
// meta = { sessionId, stackIndex }
return { ...data, timestamp: Date.now() };
}}
onInteraction={(envelope) => {
// envelope is a canonical ActionEnvelope
console.log(envelope.type, envelope.payload);
}}
onStackPush={(stackItem) => {
/* new UI pushed */
}}
onError={(error) => {
/* connection error, contract violation, etc. */
}}
/>