The format

Actions and state

Components never run code. When the reader taps, types or answers, your app gets an action and decides what happens next.

View as Markdown

Nothing in an answer runs code. When the reader acts, the SDK hands your app an action, and your app decides what happens: usually the model's next turn.

Actions

The reader The action
Taps a Button with ask, a button outside a form, or a follow-up question { type: "ask", text, node }
Submits a Form { type: "submit", node, form, button, fields }
Finishes a Quiz { type: "quiz", node, score, total, answers }
Votes in a Poll { type: "vote", node, name, choice }
Ticks a Checklist item, marks a flashcard known { type: "state", node, name, value }
Taps a Button with href nothing: the link opens
Switches a tab, opens details, moves a what-if slider nothing: it all happens on the page
TypeScript
createAnswer(el, {
  core,
  onAction: (action) => {
    if (action.type === "ask") send(action.text);
    if (action.type === "submit") send(`Book ${action.fields.flight} for ${action.fields.guests}`);
  },
});

With connectAgent, actions become the next user message by themselves (sendActions: false stops that), in words the core writes the same way everywhere:

Text
I finished the quiz: 1 of 2 right.
1. What absorbs light in a leaf? I answered "B. Chlorophyll" (right).
2. Which gas do plants take in? I answered "Oxygen" (wrong).

Form fields

fields is keyed by each field's name, or its label as one word when it has none:

Field Value
Input, TextArea, Select, Radio, Date, Time, Stepper, Combobox, TimeSlots, RatingInput text
Slider a number
Switch true or false
Checkboxes, and a ToggleGroup that allows several a list of the chosen options
Camera, File a list of Files, the browser's own, for your app to upload
Location { lat, lng, accuracy } in degrees and metres when the reader shared it, or the place they typed
Scan the code, as text; a photo of it, when they took one, as files under <name>-photo

The SDK checks required before it sends anything. A photo, a file or a location exists only after the reader acted: nothing is captured until they tap.

State

What the reader has done is also kept as plain JSON for each component, so it can be saved, restored, or shared with an agent:

Component State
Quiz { "answers": [index or null per question] }
Flashcards { "known": [card index] }
Poll { "vote": option or null }
Checklist { "done": [item index] }
WhatIf { "values": { slider name: number } }
Form { "fields": { name: value } }

onComponentState(node, state) tells you when it changes, and answer.applyState({ [node]: state }) sets it, say from a saved session. With AG-UI the state rides in the shared state's morphscreen key, so an agent can read what the reader did and set it too (AG-UI agents).