Bonnard

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:

  1. explore_schema finds the tables and their columns: here customer_months, with customer_id, month and revenue.
  2. sql_query runs a read-only query, so the agent can check the numbers first.
  3. render_chart takes 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:

render_chartjson

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

Prompt

September from gross sales to gross profit, with net revenue as a subtotal.

render_chartjson

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

Prompt

Q3 revenue by region against the £150K weekly target, as a variance walk.

render_chartjson

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

Prompt

Revenue so far this year, month by month, as a running total.

render_chartjson

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

What a waterfall chart takes
Ask forWhat 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.