For AI agents
Dashboard operations
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.
| Operation | Needed | Optional |
|---|---|---|
replace_all | items, and title and description to create | title, description, columns, params |
set_metadata | One of the optional fields | title, description, columns, params |
add | items (one tile), placement | None |
edit | id, items (one tile) | None |
move | id, placement | None |
remove | id | None |
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.
| Kind | Needed | Optional | Default span |
|---|---|---|---|
chart | kind, id, sql (up to 8,000 characters) | title (up to 200 characters), span, and the options in Chart spec | 2 |
kpi | kind, id, sql, title | The fields in KPI tile | 1 |
text | kind, id, text (up to 8,000 characters) | heading (up to 200 characters), span | 2 |
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.
| Value | Effect |
|---|---|
{"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 saveIf 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 changeTo 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 clientDashboards 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 itOnly 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 consoleA version that differs from the saved one is refused:
version_conflict: "<id>" is not at version <version>; re-read it before deleting