# Work with large results

> The row and byte limits an agent meets, the references that hold a whole result, and the files made from them.

Updated: 2026-11-09

An agent, the model in an AI client that acts for a person, reads a preview of a query result. Bonnard keeps the bounded result behind a reference, so the agent can make a file without running the query again. [Limits](https://bonnard.ai/docs/reference/limits.md) has the full table.

Verified 9 Nov 2026.

Table: Result limits

| Limit | Value | Applies to |
| --- | --- | --- |
| Rows in a preview | 250 | `sql_query` |
| Rows fetched and captured | 5,000 | `sql_query` |
| Rows with `max_rows` | 500,000. On MySQL / MariaDB, 5,001 | `sql_query` |
| Rows in a chart preview | 10 by default, up to 150 | `render_chart` |
| Reply size in Claude Code and Claude Desktop | 48 KB | Replies to the agent |
| Chart data in a reply, when Bonnard cannot store it | 64 KB | `render_chart`, `render_dashboard` |
| One cell in a preview | 2 KB | `sql_query` |
| Life of a reference | 30 minutes | `resultRef`, `snapshotRef` |

## Row limits

The `sql_query` tool fetches and captures up to 5,000 rows, and its preview shows at most 250. With `max_rows`, it captures up to 500,000, and Bonnard clamps a larger value to 500,000. On MySQL / MariaDB, it stops at 5,001 rows and marks the result complete, with no warning. Add `LIMIT` and `OFFSET` to page through a result.

Set `capture_only: true` with `max_rows`, so Bonnard skips the preview. The reply then holds `resultRef`, the fields, and the row counts, with no rows. `capture_only` and `max_rows` are in the input only while Export data is on.

## Byte limits

A reply to an agent in Claude Code or Claude Desktop holds at most 48 KB, counting its text and its structured content. Above that, the reply holds fewer rows.

Bonnard stores chart data for the widget, and the reply holds a `viewRef` to it, which lasts 24 hours. If Bonnard cannot store the data, the reply carries it, at most 64 KB. Above that, Bonnard draws fewer points and keeps the first and last row. A table keeps its leading rows.

A cell in a preview holds at most 2 KB. The capture and each file keep the whole cell.

## `resultRef`

`resultRef` identifies the rows captured from a result. The `sql_query`, `render_chart`, and `render_dashboard` tools return it while Export data is on. Pass it to `create_export_file` to make a CSV. Pass one from `render_chart` to `save_chart` to keep the chart. It lasts 30 minutes.

## `snapshotRef`

`snapshotRef` identifies a chart or dashboard tile as it was drawn. The `render_chart` and `render_dashboard` tools return it while Export data is on. Pass it to `create_export_file` to make a PNG. Pass one from `render_chart` to `save_chart` to keep the chart. It lasts 30 minutes.

## `create_export_file`

The `create_export_file` tool makes one file from one reference, without running the query again. The file holds exactly the rows its capture holds.

Table: Export formats

| `format` | Takes | Use it for |
| --- | --- | --- |
| `csv` | `resultRef` | A small result, or a file for a person |
| `csv.gz` | `resultRef` | A large result the agent can decompress |
| `png` | `snapshotRef` | An image of a chart or dashboard tile |

The reply holds an `artifactUri`. Read the bytes with `resources/read`. With `deliver: "inline"`, the bytes are also in the reply, for a client that cannot read resources.

## When a reference expires

A call with an expired reference gets an error that holds this text. From `create_export_file`:

```text
References last 30 minutes. Run the query or render the chart again (sql_query, render_chart or render_dashboard), then retry with the new reference.
```

From `save_chart`:

```text
that reference has expired. References last 30 minutes. Re-render the chart with render_chart, then retry with the new reference.
```

To fix it, run the query or draw the chart again, and pass the reference that call returns.
