Protocol overview
The four JSON schemas that connect the SDK, the runtime and the dashboard, and where each is used.
Kletso is a protocol first: the SDK, the runtime and the dashboard agree on a handful of JSON documents. Everything else (widgets, Workers, React) is replaceable.
| Schema | Purpose | Produced by | Consumed by |
|---|---|---|---|
kletso.ui/v1 | A surface: the component tree the agent wants rendered | The model via render_ui, trigger fixtures, workflows | The SDK, the dashboard’s schematic renderer |
kletso.events/v1 | The event envelope carried by every server message: message.delta, ui.render, app.notify, … | The runtime | The SDK, the dashboard inspectors, webhooks |
| Realtime frames | Client → server (auth, message, action, context, track, screen, switch, ping) and server → client (ready, event, pong, error) over WebSocket or SSE | Both | Both |
kletso.components/v1 | The component manifest written by kletso_flutter:sync | Your Flutter app | The dashboard |
kletso.workflow/v1 | A workflow definition: nodes, edges, input schema | The dashboard builder | The runtime’s workflow runner |
The JSON Schemas live in the kletso_ui_schema package (schemas/*.json) together with fixtures: valid surfaces for every block family, invalid surfaces with the expected rejection code, a 113-event scripted conversation, and example frames. The SDK’s fake backend, the runtime’s tests and the dashboard’s demo mode all run on the same fixtures.
Design rules
- Ids are the map keys. Components live in a flat map keyed by id and reference children by id. Trees stay small and patchable.
- Never throw on bad input. Parsers return a result with issues. Fatal issues (missing root, cycle, oversize) mean “do not render”; non-fatal ones (unknown type, dangling child) degrade gracefully.
- Sequence numbers everywhere. Every event has a monotonic
seqper conversation; clients replay from the last one they saw. - Versioned names.
kletso.ui/v1will coexist with a futurev2; a client that does not know a schema rendersfallbackText.