Charts
Waterfall charts in your AI client
Bonnard draws a waterfall chart to walk a total from one level to another through signed changes.


The examples use Acme, a demo retailer that reports in pounds. Each variant is a few words in the question. A follow-up changes a chart already drawn.
How an agent draws it
The chat above ran three tools, in this order:
explore_schemafinds the tables and their columns: herecustomer_months, withcustomer_id,monthandrevenue.sql_queryruns a read-only query, so the agent can check the numbers first.render_charttakes the SQL and the chart options. It runs the query and returns the chart the chat draws.
The render_chart call behind the chart above:
JSON
{
"charts": [
{
"sql": "WITH c AS (SELECT customer_id, SUM(CASE WHEN month = DATE '2026-08-01' THEN revenue END) AS aug, SUM(CASE WHEN month = DATE '2026-09-01' THEN revenue END) AS sep FROM customer_months WHERE month >= DATE '2026-08-01' GROUP BY customer_id) SELECT step, amount, kind FROM (SELECT 1 AS n, 'Aug' AS step, SUM(aug) AS amount, 'opening' AS kind FROM c UNION ALL SELECT 2, 'Lapsed', -SUM(aug), 'change' FROM c WHERE sep IS NULL UNION ALL SELECT 3, 'Repeat', SUM(sep - aug), 'change' FROM c UNION ALL SELECT 4, 'New', SUM(sep), 'change' FROM c WHERE aug IS NULL UNION ALL SELECT 5, 'Sep', SUM(sep), 'closing' FROM c) AS w ORDER BY n",
"chartType": "waterfall",
"title": "Revenue, August to September 2026, by customer",
"encode": { "x": "step", "y": "amount" },
"fields": [
{ "name": "step", "label": "Customers" },
{ "name": "amount", "label": "Revenue", "format": "currency", "currency": "GBP" }
]
}
]
}The query returns one row per bar, in order: each change signed, and a kind column that marks the opening and closing totals.
A call takes up to 10 charts, shown as a carousel. Each example below shows its one entry. A connected agent reads the full option reference with explore_docs, topic charts/waterfall.
Subtotals
September from gross sales to gross profit, with net revenue as a subtotal.


JSON
{
"sql": "SELECT line AS step, amount, CASE line WHEN 'Gross sales' THEN 'total' WHEN 'Net revenue' THEN 'subtotal' WHEN 'Gross profit' THEN 'total' ELSE 'change' END AS kind FROM monthly_pnl WHERE month = DATE '2026-09-01' ORDER BY line_no",
"chartType": "waterfall",
"title": "September 2026, gross sales to gross profit",
"encode": { "x": "step", "y": "amount" },
"fields": [
{ "name": "step", "label": "P&L line" },
{ "name": "amount", "label": "Amount", "format": "currency", "currency": "GBP" }
]
}A subtotal row holds the level at that point, drawn from zero. The changes after it start again from that level.
A variance walk
Q3 revenue by region against the £150K weekly target, as a variance walk.


JSON
{
"sql": "WITH q AS (SELECT region, revenue FROM weekly_region_revenue WHERE week_start >= DATE '2026-06-29') SELECT step, amount, kind FROM (SELECT 0 AS n, 'Target' AS step, COUNT(*) * 150000 AS amount, 'opening' AS kind FROM q UNION ALL SELECT 1, region, SUM(revenue - 150000), 'change' FROM q GROUP BY region UNION ALL SELECT 2, 'Actual', SUM(revenue), 'closing' FROM q) AS w ORDER BY n, amount DESC",
"chartType": "waterfall",
"title": "Q3 2026 revenue against target, by region",
"encode": { "x": "step", "y": "amount" },
"fields": [
{ "name": "step", "label": "Region" },
{ "name": "amount", "label": "Revenue", "format": "currency", "currency": "GBP" }
]
}The target opens the walk, and each region adds its gap above or below it. Steps keep the query’s row order, so the SQL sorts the regions.
A running total
Revenue so far this year, month by month, as a running total.


JSON
{
"sql": "SELECT step, amount, kind FROM (SELECT month_start AS n, month_label AS step, revenue AS amount, 'change' AS kind FROM monthly_revenue WHERE month_start >= DATE '2026-01-01' UNION ALL SELECT DATE '2026-12-31', 'Total', SUM(revenue), 'total' FROM monthly_revenue WHERE month_start >= DATE '2026-01-01') AS w ORDER BY n",
"chartType": "waterfall",
"title": "Revenue by month, 2026 to date",
"encode": { "x": "step", "y": "amount" },
"fields": [
{ "name": "step", "label": "Month" },
{ "name": "amount", "label": "Revenue", "format": "currency", "currency": "GBP" }
]
}The query marks only the last row as a total, so the walk starts from zero with January.
Options and limits
| Ask for | What Bonnard draws |
|---|---|
| ”a waterfall” or “a bridge” | Steps in row order: gains green, losses red, totals grey |
| ”from opening to closing” | Total bars at each end, with the changes between |
| ”with a subtotal” | A total bar inside the walk, which the next change starts from |
| ”in pounds” or “as a percentage” | Currency, percent or compact values on the axis and bars |
| ”start the axis at £1M” | A fixed value axis, with a note under the chart when it starts above zero |
| ”call the axis Revenue” | Axis titles in place of the column labels |
- A total is a row whose marker column reads total, subtotal, opening, closing, start, end, net or balance.
- With no marker column, the first and last rows become the totals, and Bonnard tells the agent it guessed.
- A waterfall draws one measure: a list of measures draws only the first.
- It needs at least two rows: a starting total and one change.
- Bars carry their values up to 12 steps. At phone width, when one value does not fit its bar, only the totals keep theirs.
- The colours are fixed. A waterfall takes no series colours, highlight, legend, target lines or trend lines.
- Labels and axis titles run to 60 characters.
- No chart draws a log scale, custom hex colours or zoom.