Charts
Line charts in your AI client
Bonnard draws a line chart to show a trend over time or along another ordered axis.


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 '2025-10-01' AND order_date < DATE '2026-10-01' GROUP BY 1 ORDER BY 1",
"chartType": "line",
"xAxisType": "categorical",
"title": "Revenue by month (£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/line.
One line per region
Weekly revenue by region since July, one line per region.


JSON
{
"sql": "SELECT week_start AS week, region, revenue / 1000 AS revenue FROM weekly_region_revenue WHERE week_start >= DATE '2026-06-29' ORDER BY week_start",
"chartType": "line",
"xAxisType": "categorical",
"title": "Weekly revenue by region (£k)",
"encode": { "x": "week", "y": "revenue", "series": "region" },
"fields": [
{ "name": "week", "label": "Week" },
{ "name": "revenue", "label": "Revenue (£k)", "format": "number" }
]
}A split draws one line per value of a column, each in its own colour, with a legend below.
One line per measure
Monthly revenue against budget for the last 12 months, with the budget dashed.


JSON
{
"sql": "SELECT month, revenue / 1000 AS revenue, budget / 1000 AS budget FROM monthly_revenue_budget WHERE month >= DATE '2025-10-01' AND month < DATE '2026-10-01' ORDER BY month",
"chartType": "line",
"xAxisType": "categorical",
"title": "Revenue against budget, by month",
"encode": { "x": "month", "y": ["revenue", "budget"] },
"fields": [
{ "name": "month", "label": "Month" },
{ "name": "revenue", "label": "Revenue", "format": "number" },
{ "name": "budget", "label": "Budget", "format": "number" }
],
"axes": { "y": { "title": "Revenue (£k)" } },
"series": { "Budget": { "line": "dashed" } }
}Each measure is its own line on one shared axis, which the call titles. “Dashed” styles one line; dotted lines, markers and colours work the same way.
A second axis
Weekly orders since July, with the conversion rate on a second axis.


JSON
{
"sql": "SELECT week_start AS week, orders, conversion FROM weekly_orders WHERE week_start >= DATE '2026-06-29' ORDER BY week_start",
"chartType": "line",
"xAxisType": "categorical",
"title": "Weekly orders, with conversion",
"encode": { "x": "week", "y": "orders", "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, with its own scale and format. A target line can sit on either axis.
A moving average
Daily orders since July, with a 7-day average.


JSON
{
"sql": "SELECT order_date AS day, COUNT(*) AS orders FROM orders WHERE order_date >= DATE '2026-07-01' GROUP BY 1 ORDER BY 1",
"chartType": "line",
"title": "Daily orders",
"encode": { "x": "day", "y": "orders" },
"fields": [
{ "name": "day", "label": "Day" },
{ "name": "orders", "label": "Orders", "format": "number" }
],
"overlay": { "kind": "movingAverage", "window": 7 }
}The dashed line averages the last 7 points, with the daily line faded behind it. “A trend line” fits a straight line instead.
A break for missing days
Daily conversion since August, with a gap where tracking was down.


JSON
{
"sql": "SELECT day, orders * 1.0 / sessions AS conversion FROM daily_sessions WHERE day >= DATE '2026-08-01' ORDER BY day",
"chartType": "line",
"title": "Daily conversion since August",
"encode": { "x": "day", "y": "conversion" },
"fields": [
{ "name": "day", "label": "Day" },
{ "name": "conversion", "label": "Conversion", "format": "percent" }
],
"fillGaps": "gap"
}By default the line joins across days with no row. A break suits a rate like this one; counts can fill missing days with 0, and balances with the last value.
Options and limits
| Ask for | What Bonnard draws |
|---|---|
| ”by region” or “one line per channel” | One line per value of a column |
| ”revenue against budget” | One line per measure, on one axis |
| ”on a second axis” | A right axis for a measure in other units |
| ”stacked” or “as a share of the total” | Each line stacked on the one below, or as shares of 100% |
| “a gap where data is missing” | Missing periods left as a break, filled with 0, or held at the last value |
| ”a target line” or “the average” | Reference lines and bands, up to six |
| ”a 7-day average” or “a trend line” | A moving average over 2 to 52 points, or a least-squares line |
| ”dashed”, “dotted” or “with markers” | A line style, width and marker per line |
| ”make the UK stand out” | Up to three lines in colour, the rest grey |
| ”on a timeline” or “evenly spaced” | Dates spaced by the time between them, or one slot per row |
| ”start the axis at 100” | A fixed axis range, or one fitted to the data |
- There is no cap on lines.
- A chart query returns up to 5,000 rows by default.
- Dates sit on a timeline unless the chart is stacked or the call asks for one slot per row. The weekly and monthly examples above ask for slots.
- A 7-day average has no value for the first 6 days, or for any window that holds a gap.
- A 100% stack takes no moving average or trend line, and a line on the right axis gets none.
- Gap filling stops after 10,000 periods.
- Labels and axis titles run to 60 characters.
- A line chart draws no data labels or smoothed lines. No chart draws a log scale, custom hex colours or zoom.
When Bonnard draws something else
- Text on the x axis implies an order that may not exist. For categories, the product suggests a bar chart.
- A target that changes each period, such as a monthly budget, is a measure. The agent draws it as its own line, as in the budget example.