Bonnard

An agent, the model in an AI client that acts for a person, changes a dashboard by sending operations to save_dashboard. One call holds up to 20 operations. Bonnard refuses a field that belongs to another operation, and a missing needed field.

Verified 9 Nov 2026.

Operations and their fields
OperationNeededOptional
replace_allitems, and title and description to createtitle, description, columns, params
set_metadataOne of the optional fieldstitle, description, columns, params
additems (one tile), placementNone
editid, items (one tile)None
moveid, placementNone
removeidNone

A call has operations, and dashboard_id and expected_version when it changes a saved dashboard. Bonnard runs the SQL of each added or changed tile one time. A tile whose query fails is named in the reply, and the save succeeds. Bonnard refuses the whole save for SQL that is not read-only, a {{name}} with no declared param, or malformed or nested [[ ]]. columns is accepted and ignored, because the grid is fixed at 4 columns.

replace_all

Creates a dashboard, or replaces all of its tiles. Omit dashboard_id to create one, with title and description. Without them, Bonnard answers title is required (<=200 chars) or description is required (<=500 chars). It must be the only operation in its call. items holds up to 20 tiles in display order.

title takes up to 200 characters, and description up to 500. params takes up to 100 entries, and null clears them. To declare one, go to Add filters to a dashboard.

{"operations":[{"op":"replace_all","title":"Sales","description":"Revenue by month.","items":[{"kind":"chart","id":"by_month","sql":"SELECT date_trunc('month', order_date) AS month, SUM(amount) AS revenue FROM orders GROUP BY 1 ORDER BY 1","chartType":"line","title":"Revenue by month"}]}]}

set_metadata

Changes the dashboard’s title, description, or params, and leaves its tiles as they are.

{"dashboard_id":"<dashboard id>","expected_version":3,"operations":[{"op":"set_metadata","title":"Sales overview"}]}

add

Adds one tile at a placement.

{"dashboard_id":"<dashboard id>","expected_version":3,"operations":[{"op":"add","items":[{"kind":"text","id":"note","text":"Figures exclude refunds."}],"placement":{"position":"end"}}]}

edit

Replaces one whole tile. items[0].id must equal id. Read the dashboard with explore_dashboards first, and pass the tile’s SQL back unless you change it. Without a span, the tile keeps its width.

{"dashboard_id":"<dashboard id>","expected_version":3,"operations":[{"op":"edit","id":"note","items":[{"kind":"text","id":"note","text":"Figures include refunds."}]}]}

move

Moves one tile to a placement.

{"dashboard_id":"<dashboard id>","expected_version":3,"operations":[{"op":"move","id":"note","placement":{"position":"start"}}]}

remove

Removes one tile. A dashboard keeps at least one tile. Removing the last one gets items must be a non-empty array, and in the console at app.bonnard.ai, Save is blocked by Add at least one item.

{"dashboard_id":"<dashboard id>","expected_version":3,"operations":[{"op":"remove","id":"note"}]}

Tiles

A dashboard holds at most 16 chart and KPI tiles, counted after the call is applied. Text tiles do not count. Each tile has an id of up to 64 characters: lowercase letters, digits, _, and -, starting with a letter.

Tile kinds
KindNeededOptionalDefault span
chartkind, id, sql (up to 8,000 characters)title (up to 200 characters), span, and the options in Chart spec2
kpikind, id, sql, titleThe fields in KPI tile1
textkind, id, text (up to 8,000 characters)heading (up to 200 characters), span2

span is 1 to 4 of the grid’s 4 columns. A value of 4 is full width.

A saved dashboard or chart holds at most 65,536 bytes as JSON, so 16 tiles of 8,000-character SQL do not fit. A saved chart’s SQL holds at most 8,000 characters. Bonnard refuses a save over either limit:

def exceeds the 65536-byte cap (<bytes> bytes)

sql is required (<=8000 chars)

Placement

placement says where a tile goes.

placement values
ValueEffect
{"position":"start"}First on the dashboard
{"position":"end"}Last on the dashboard
{"position":"after","afterId":"<tile id>"}After the named tile

Versions

expected_version is needed on each change to a saved dashboard. It comes from the last save or from explore_dashboards. Without it, Bonnard answers:

expected_version is required when editing; read it from explore_dashboards or the last save

If someone else changed the dashboard first, Bonnard refuses the call:

version_conflict: "<id>" is at version <version>, not <expected version>; re-read it and reapply your change

To fix it, read the dashboard with explore_dashboards, then send the change again with the version it returns.

Verified dashboards

An Editor or higher can change a verified dashboard from an AI client. The save writes unpublished changes, and render_dashboard keeps the published version until someone publishes the changes in the console at app.bonnard.ai. Bonnard refuses anyone else:

"<id>" is verified, so only an admin or editor can change it, in the console or from their own AI client

Dashboards customers have

A Viewer who owns a dashboard that customers have cannot change it or delete it from an AI client. An Editor or higher can change it. An AI client gets the first message, and the console the second:

"<id>" is shared with customers, so only an admin or editor can change it

Only an editor or admin can change a dashboard shared with customers.

delete_dashboard

delete_dashboard removes a dashboard the caller saved, and the delete cannot be undone. It needs dashboard_id and expected_version. Bonnard refuses to delete a verified dashboard, and an Editor or higher gets this reply:

"<id>" is verified and cannot be deleted from chat; an admin can delete it in the console

A version that differs from the saved one is refused:

version_conflict: "<id>" is not at version <version>; re-read it before deleting