Charts
Bar charts in your AI client
Bonnard draws a bar chart to compare categories or periods.


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_date,regionandrevenue.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 region, SUM(revenue) / 1000 AS revenue FROM orders WHERE order_date >= DATE '2026-07-01' AND order_date < DATE '2026-10-01' GROUP BY region ORDER BY revenue DESC",
"chartType": "bar",
"title": "Revenue by region, Q3 2026 (£k)",
"encode": { "x": "region", "y": "revenue" },
"fields": [
{ "name": "region", "label": "Region" },
{ "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/bar.
Stacked bars
Revenue by channel for the last 12 months, stacked.


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": "bar",
"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" }
]
}Each bar is the month’s total, split by channel. “As a share of the total” stacks each bar to 100%.
Side by side
Revenue by channel for the last four months, side by side.


JSON
{
"sql": "SELECT date_trunc('month', order_date) AS month, channel, SUM(revenue) / 1000 AS revenue FROM orders WHERE order_date >= DATE '2026-06-01' GROUP BY 1, 2 ORDER BY 1",
"chartType": "bar",
"stacking": "grouped",
"title": "Revenue by channel, June to September (£k)",
"encode": { "x": "month", "y": "revenue", "series": "channel" },
"fields": [
{ "name": "month", "label": "Month" },
{ "name": "revenue", "label": "Revenue (£k)", "format": "number" }
]
}Each channel gets its own bar. Bonnard draws a split this way unless the question says otherwise.
Horizontal bars
Revenue by product category in September.


JSON
{
"sql": "SELECT category, SUM(revenue) / 1000 AS revenue FROM order_lines WHERE order_date >= DATE '2026-09-01' AND order_date < DATE '2026-10-01' GROUP BY category ORDER BY revenue DESC",
"chartType": "bar",
"title": "Revenue by category, September 2026 (£k)",
"encode": { "x": "category", "y": "revenue" },
"fields": [
{ "name": "category", "label": "Category" },
{ "name": "revenue", "label": "Revenue (£k)", "format": "number" }
]
}Bars turn sideways on their own when a label runs past 12 characters, as “Tops and T-shirts” does. Say “horizontal” or “upright” to choose.
A second axis
Weekly orders stacked by channel, with the conversion rate as a line on the right.


JSON
{
"sql": "SELECT week_label AS week, channel, orders, conversion FROM weekly_channel_orders WHERE week_start >= DATE '2026-06-29' ORDER BY week_start",
"chartType": "bar",
"stacking": "stacked",
"xAxisType": "categorical",
"title": "Weekly orders by channel, with conversion",
"encode": { "x": "week", "y": "orders", "series": "channel", "y2": "conversion" },
"fields": [
{ "name": "week", "label": "Week" },
{ "name": "orders", "label": "Orders", "format": "number" },
{ "name": "conversion", "label": "Conversion", "format": "percent" }
]
}A measure in other units goes on a right axis, drawn as a line outside the stack.
A target line
UK weekly revenue since July, 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": "bar",
"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.
Options and limits
| Ask for | What Bonnard draws |
|---|---|
| ”stacked” | Series stacked in each bar |
| ”as a share of the total” | A 100% stack, each series as its share of the bar |
| ”side by side” | One bar per series, the default for a split |
| ”horizontal” or “upright” | Bars turned sideways, or kept upright |
| ”with the forecast as a line” | A measure drawn as a line on the same axis, outside the stack |
| ”on the right” | A second axis for a measure in other units |
| ”a target line” or “the average” | Reference lines and bands, up to six |
| ”make outerwear stand out” | Up to three bars or series highlighted |
| ”on a timeline” | Dates spaced by the time between them |
| ”with a moving average” or “a trend line” | A dashed line computed over each series, the bars faded behind it |
| ”missing months as zero” | Periods with no row drawn as 0, carried forward, or left empty |
| ”start the axis at 100” | A fixed axis range, or one fitted to the data |
- There is no cap on bars or series.
- A chart query returns up to 5,000 rows by default.
- A line over the bars or a second axis keeps the chart upright.
- A 100% stack and horizontal bars keep one slot per row, never a timeline.
- Labels and axis titles run to 60 characters. When bars cannot turn sideways, category labels over 11 characters are cut short and tilted.
- A bar chart draws no data labels. No chart draws a log scale, custom hex colours or zoom.
When Bonnard draws something else
- A histogram is a bar chart over buckets. The agent computes the buckets in SQL, then draws the bars.
- Many categories: the agent keeps the top rows, or groups the rest as “Other” in SQL.