Charts
Area charts in your AI client
Bonnard draws an area chart for a trend over time, and stacks the areas to show a total and its parts.


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: hereorders, withorder_dateandrevenue.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": "SELECT date_trunc('month', order_date) AS month, SUM(revenue) / 1000 AS revenue FROM orders WHERE order_date >= DATE '2026-01-01' GROUP BY 1 ORDER BY 1",
"chartType": "area",
"title": "Revenue by month, 2026 (£k)",
"encode": { "x": "month", "y": "revenue" },
"fields": [
{ "name": "month", "label": "Month" },
{ "name": "revenue", "label": "Revenue (£k)", "format": "number" }
]
}
]
}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/area.
Stacked areas
Revenue by channel for the last 12 months, as a stacked area.


JSON
{
"sql": "SELECT date_trunc('month', order_date) AS month, channel, SUM(revenue) / 1000 AS revenue FROM orders WHERE order_date >= DATE '2025-10-01' GROUP BY 1, 2 ORDER BY 1",
"chartType": "area",
"stacking": "stacked",
"title": "Revenue by channel, by month (£k)",
"encode": { "x": "month", "y": "revenue", "series": "channel" },
"fields": [
{ "name": "month", "label": "Month" },
{ "name": "revenue", "label": "Revenue (£k)", "format": "number" }
]
}The top edge is each month’s total, and each layer is one channel’s part of it.
A share of the total
Revenue by channel for the last 12 months, as a share of the total.


JSON
{
"sql": "SELECT date_trunc('month', order_date) AS month, channel, SUM(revenue) / 1000 AS revenue FROM orders WHERE order_date >= DATE '2025-10-01' GROUP BY 1, 2 ORDER BY 1",
"chartType": "area",
"stacking": "stacked100",
"title": "Revenue share by channel, by month",
"encode": { "x": "month", "y": "revenue", "series": "channel" },
"fields": [
{ "name": "month", "label": "Month" },
{ "name": "revenue", "label": "Revenue (£k)", "format": "number" }
],
"axes": { "y": { "title": "Share of revenue" } }
}Each month stacks to 100%, so each layer is that channel’s share. The call names the value axis, since a share is not in £k.
Overlapping areas
Weekly revenue for the UK and Germany since July, as overlapping areas.


JSON
{
"sql": "SELECT week_label AS week, region, revenue / 1000 AS revenue FROM weekly_region_revenue WHERE region IN ('UK', 'Germany') AND week_start >= DATE '2026-06-29' ORDER BY week_start",
"chartType": "area",
"xAxisType": "categorical",
"title": "Weekly revenue, UK and Germany (£k)",
"encode": { "x": "week", "y": "revenue", "series": "region" },
"fields": [
{ "name": "week", "label": "Week" },
{ "name": "revenue", "label": "Revenue (£k)", "format": "number" }
]
}Without “stacked”, each region fills down to zero and the two overlap. Bonnard draws a split this way unless the question says otherwise. Keep overlapping areas to a few series.
A running total
Cumulative revenue this year, by month.


JSON
{
"sql": "SELECT month, SUM(revenue) OVER (ORDER BY month) / 1000000 AS revenue FROM (SELECT date_trunc('month', order_date) AS month, SUM(revenue) AS revenue FROM orders WHERE order_date >= DATE '2026-01-01' GROUP BY 1) AS m ORDER BY month",
"chartType": "area",
"title": "Revenue to date, 2026 (£m)",
"encode": { "x": "month", "y": "revenue" },
"fields": [
{ "name": "month", "label": "Month" },
{ "name": "revenue", "label": "Revenue to date (£m)", "format": "number" }
]
}The running total comes from the SQL, a window sum over the months. The area fills under it, so its top edge is revenue to date.
A target line
UK weekly revenue since July as an area, with a line at the £150K target.


JSON
{
"sql": "SELECT week_label AS week, revenue / 1000 AS revenue FROM weekly_region_revenue WHERE region = 'UK' AND week_start >= DATE '2026-06-29' ORDER BY week_start",
"chartType": "area",
"xAxisType": "categorical",
"title": "UK weekly revenue against target (£k)",
"encode": { "x": "week", "y": "revenue" },
"fields": [
{ "name": "week", "label": "Week" },
{ "name": "revenue", "label": "Revenue (£k)", "format": "number" }
],
"reference": [
{ "y": 150, "label": "Target £150K" }
]
}Targets, budgets, shaded bands and average or median lines work the same way, up to six on one chart. On a stacked area, an average or median is of the total.
Options and limits
| Ask for | What Bonnard draws |
|---|---|
| ”stacked” | Series stacked, the top edge the total |
| ”as a share of the total” | A 100% stack, each series as its share at every point |
| ”overlapping” | Each series filled from zero, the default for a split |
| ”cumulative” or “a running total” | A running total from the SQL, filled underneath |
| ”with conversion on the right” | A second axis for a measure in other units, drawn as a line |
| ”a target line” or “the average” | Reference lines and bands, up to six |
| ”a 4-week moving average” or “a trend line” | A dashed line over each series, or over the stack’s total |
| ”make the UK stand out” | Up to three series highlighted |
| ”on a timeline” | Dates spaced by the time between them, the default when unstacked |
| ”start the axis at 100” | A fixed axis range, or one fitted to the data |
| ”missing months as zero” | Gaps filled with zero or the last value, or left as a break |
- There is no cap on series.
- A chart query returns up to 5,000 rows by default.
- Stacked areas keep one slot per row unless the call asks for a timeline. A 100% stack never takes one.
- In a stack, a missing value counts as zero, so the layers stay aligned.
- Each measure on the left axis is filled. A measure on the right axis sits outside the stack, as a line with no fill.
- A 100% stack has no total, so it takes no moving average or trend line.
- An area whose axis starts above zero says so under the chart.
- Labels and axis titles run to 60 characters.
- Lines run straight between points. An area chart draws no data labels. No chart draws a log scale, custom hex colours or zoom.
When Bonnard draws something else
- A target that changes month by month comes from the SQL as a measure, and the agent draws it as a line over bars.