Canvases, the workspace and state ownership
A canvas — a dashboard, a query workbench — sits beside the chat and shows what the agents are building while they build it. The person edits it too. That makes it shared state, and shared state needs one rule above all: every key has exactly one writer.
The workspace
The agents keep a compact record of what the conversation built in the AG-UI
state, under kaboo_workspace:
| Key | What it holds |
|---|---|
focus |
Where the agents are working now: a dashboard or query id, and the widgets they touched. |
dashboards |
Each dashboard's id, title, version and widgets — by id, never data. |
queries |
Each saved query's id, title and columns. |
sources |
The data sources the conversation uses. |
pending |
Work an agent started and hasn't finished. |
changes |
What each agent did, in order: "Added 2 widgets on Churn by region". |
Tool results write it through state effects: a mapper per tool turns a
successful call into JSON Patch operations, which reach the browser as
STATE_DELTAs the moment the call succeeds
(kaboo-workflows: Shared state).
Following the agent
- Follow mode. The canvas opens whatever
focusnames, and points out the widgets the agent touched. The person can turn it off. - Presence.
useAgentPresence()says which sub-agents are working and on which tool. - Ghost widgets.
useLiveToolCalls(/plot_widgets$/)returns the plot calls in flight with their arguments so far, so the widgets an agent is writing show as outlines before the call runs. - What Kaboo did.
changesis a readable log, with links to what each change touched.
Lab scenario: delegate-dashboard.
Telling the agent what the person sees
The agents read the workspace at every model call, through workspace views,
so they extend what exists instead of listing and reading it first. In the lab,
extending a dashboard takes two tool calls with a view and four without
(workspace-extend
against
workspace-extend-read;
yarn lab compare workspace-vs-read --live for a real model).
What the person does on the canvas reaches the agent two ways:
- Context, for what they are looking at:
useAgentContextsends the open dashboard's version and a summary with every run, so "this chart" means the chart on screen. - Actions, for intents: "Ask Kaboo" on a widget, or changing a variable,
sends a readable message with a structured
kaboo_actioninforwardedProps, which the host can route to a workflow without parsing text (workspace-refresh).
Who owns each key
| Key | Writer | The browser |
|---|---|---|
kaboo_sessions |
kaboo-workflows: the agents' transcripts and a paused run | never sees it |
kaboo_workspace |
kaboo-workflows' state effects | sees it, read-only |
your keys, such as kaboo_references |
the browser | owns them |
kaboo-runtime enforces the split: server keys come only from the store, a
browser's copy is ignored, and a hidden key never reaches the browser, live or
on replay
(kaboo-runtime: Replay & state).
A host vouches for a server key of its own by returning it from enrich.
Dashboards themselves stay out of state: they live in their service, the canvas fetches them, and the workspace holds only their ids and versions. The person's edits go to the service; the agents see them through context and the next effect, never by the browser writing the workspace.