> For the complete documentation index, see [llms.txt](https://documentation.proto.cx/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://documentation.proto.cx/docs/modules/ai-agents/workflows-and-actions/send-graph.md).

# Send graph

Render data as a chart image directly in the chat window.

`Action` — Renders data as a chart image directly in the chat window.

## What it does

Displays numeric data visually as a chart — bar, line, pie, or a Combo chart pairing bars with a line — so a person can see trends or breakdowns without leaving the conversation.

## When to use it

To show a person their spending breakdown, a trend over time, or any numeric result from an earlier Send API or SQL query action.

## Settings

| Setting              | Description                                                                                                                                                                                                                                                                                                                         |
| -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Graph type**       | The chart style: Bar, Grouped bar, Stacked bar, Line, Multi-line, Pie, or Combo.                                                                                                                                                                                                                                                    |
| **Chart data input** | A variable or JSON resolving to a list of `{x, y, series}` rows. Entered as a [chat script](/docs/developers/chat-scripts.md) expression. For **Combo**, this becomes two separate inputs, **Bar data input** and **Line data input**, one inside each of a **Bar data** / **Line data** collapsible section — see [Combo](#combo). |
| **Graph title**      | The chart's heading. Always a single field, even for Combo. Truncates with an ellipsis if too long to fit; hovering shows the full text.                                                                                                                                                                                            |
| **X-axis label**     | Label for the horizontal axis. Always a single field, even for Combo.                                                                                                                                                                                                                                                               |
| **Y-axis label**     | Label for the vertical axis. For **Combo**, this becomes a separate **Y-axis label** field inside each of the **Bar data** / **Line data** sections, used differently from a normal Y-axis label — see [Combo](#combo).                                                                                                             |
| **Colour scheme**    | Default, Blue, Green, Grey, Orange, Rose, Violet, Yellow, Neutral, Distinct, Vivid, or Mild.                                                                                                                                                                                                                                        |
| **Show grid lines**  | Toggles grid lines on the chart. Not shown on the form when Graph type is Pie, which has no axes to draw grid lines against.                                                                                                                                                                                                        |
| **Show legend**      | Toggles the chart's legend, on by default. Not shown on the form when Graph type is Bar or Line — see [Legend](#legend).                                                                                                                                                                                                            |

Press **Save** to confirm edits.

## Chart data format

The **Chart data input** is always an array of row objects with three fields:

| Field    | Description                                                                                                                                                                    |
| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `x`      | The category, time point, or slice label.                                                                                                                                      |
| `y`      | The numeric value for that row.                                                                                                                                                |
| `series` | Groups rows into separate bars/lines. Required for Grouped bar, Stacked bar, and Multi-line; omit it for single-series Bar, Line, and Pie, and for each of Combo's two inputs. |

The expected shape per graph type:

{% tabs %}
{% tab title="Bar" %}
A single series — one bar per `x` value. Omit `series`.

```json
[
  { "x": "Jan", "y": 1200 },
  { "x": "Feb", "y": 980 },
  { "x": "Mar", "y": 1450 }
]
```

{% endtab %}

{% tab title="Grouped bar" %}
Multiple bars per `x`, one for each `series`, placed side by side.

```json
[
  { "x": "Jan", "y": 1200, "series": "2023" },
  { "x": "Jan", "y": 1500, "series": "2024" },
  { "x": "Feb", "y": 980,  "series": "2023" },
  { "x": "Feb", "y": 1100, "series": "2024" }
]
```

{% endtab %}

{% tab title="Stacked bar" %}
Same shape as Grouped bar, but each `series` stacks on top of the others within one bar per `x`.

```json
[
  { "x": "Jan", "y": 800, "series": "Food" },
  { "x": "Jan", "y": 400, "series": "Transport" },
  { "x": "Feb", "y": 650, "series": "Food" },
  { "x": "Feb", "y": 330, "series": "Transport" }
]
```

{% endtab %}

{% tab title="Line" %}
A single line connecting each `x` point in order. Omit `series`.

```json
[
  { "x": "Mon", "y": 32 },
  { "x": "Tue", "y": 41 },
  { "x": "Wed", "y": 38 },
  { "x": "Thu", "y": 47 }
]
```

{% endtab %}

{% tab title="Multi-line" %}
One line per `series`, each sharing the same `x` axis.

```json
[
  { "x": "Mon", "y": 32, "series": "Deposits" },
  { "x": "Mon", "y": 18, "series": "Withdrawals" },
  { "x": "Tue", "y": 41, "series": "Deposits" },
  { "x": "Tue", "y": 22, "series": "Withdrawals" }
]
```

{% endtab %}

{% tab title="Pie" %}
One slice per row — `x` is the slice label and `y` is its value. `series` is ignored.

```json
[
  { "x": "Food", "y": 40 },
  { "x": "Transport", "y": 25 },
  { "x": "Bills", "y": 35 }
]
```

{% endtab %}

{% tab title="Combo" %}
Two independent single-series lists, one per input — **Bar data input** and **Line data input**. Each uses the plain Bar/Line shape below — omit `series` in both.

**Bar data input:**

```json
[
  { "x": "Jan", "y": 1200 },
  { "x": "Feb", "y": 980 },
  { "x": "Mar", "y": 1450 }
]
```

**Line data input:**

```json
[
  { "x": "Jan", "y": 15 },
  { "x": "Feb", "y": 12 },
  { "x": "Mar", "y": 18 }
]
```

{% endtab %}
{% endtabs %}

## Combo

**Combo** draws two series on one chart — bars from **Bar data input** and a line from **Line data input** — sharing the same `x` categories. The bar and the line are each plotted against their own value axis (bars on the left, the line on the right), so the two can use completely different scales; the bar axis always starts at zero, so a bar is never cut off above zero.

Selecting this graph type reorganises the form: **Bar data input** and **Line data input** each sit inside their own collapsible section — **Bar data** and **Line data**, both expanded by default — and each section has its own field, literally labelled **Y-axis label**:

| Setting              | Becomes                                                                                                                                                                                 |
| -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Chart data input** | **Bar data input** and **Line data input** — two separate fields, one per series, each in the plain `{x, y}` shape (see the "Combo" tab above).                                         |
| **Y-axis label**     | A separate **Y-axis label** field inside each of the **Bar data** and **Line data** sections. Both fields carry the same literal label — only the section they sit in tells them apart. |

**Graph title** and **X-axis label** stay single, shared fields — they are not split per series.

Neither Y-axis label field renders as an axis label on the chart. Instead, each names its series in the legend, the tooltip, and the exported table/CSV — for example, entering "Revenue" as the Y-axis label in the Bar data section makes the bar series appear as "Revenue" wherever its name is shown. Leave either blank and that series falls back to a default name ("Bar" or "Line").

The Y-axis label in the Bar data section must not be `x` — that name is reserved for the chart's category axis and reusing it is rejected when the action is saved (see [Validation](#validation)). The Y-axis label in the Line data section has no such restriction.

Both **Bar data input** and **Line data input** must be filled in. If either is left blank, the action does nothing and moves straight to the next action in the flow — the same behaviour as leaving **Chart data input** blank on any other graph type.

If **Colour scheme** is left at Default, Combo uses the Distinct scheme rather than the platform's usual default palette, since it needs matching solid colours for the bar, the line, and their legend swatches. The bar takes the scheme's first colour and the line its second (or the bar's colour again, if the scheme provides only one).

## Legend

A legend lists each series with a colour swatch and its name.

| Graph type                                                  | Legend behaviour                                                                                                                                                                                                                                                                                                                                                          |
| ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Bar**, **Line**                                           | Never shown, even when **Show legend** is on — there is only one series, and the axis label already names it. The **Show legend** setting itself isn't shown on the form for these two types, since there's nothing for it to control.                                                                                                                                    |
| **Grouped bar**, **Stacked bar**, **Multi-line**, **Combo** | One row per series, listed below the chart. Wraps onto further lines as needed; no values are shown, only the swatch and name.                                                                                                                                                                                                                                            |
| **Pie**                                                     | One row per slice, each showing its value and share of the total, for example "40 (44.4%)". In the webchat widget, it sits beside the pie when there's room for the whole list to fit without scrolling, otherwise below it, wrapping into a grid of columns; in the Inbox conversation thread, it's always drawn below the chart in that wrapping grid, never beside it. |

Pie slices carry no label of their own — the legend and the hover tooltip are the only places a slice's name and value appear on the chart. Turning **Show legend** off for a Pie chart leaves its slices identifiable only by colour and by hovering them.

## Viewing and exporting a chart

Every rendered chart has controls in its top-right corner: a table/graph toggle, a CSV download, and — while viewing the chart, not the table — a PNG download. This is the same in the Inbox conversation thread (where a live agent views the conversation) and in the webchat widget; both render the Send graph message with their own copy of the same chart component.

| Control                           | Does                                                                                                                                                                                                         |
| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **View as table / view as graph** | Switches between the chart and a scrollable data table of the same values — one column per series (or per slice, for Pie) alongside the category column. Selecting it again restores the chart.              |
| **Download data as CSV**          | Downloads the same rows shown in the table, as a CSV file.                                                                                                                                                   |
| **Download chart as PNG**         | Downloads an image of the chart. Hidden while the table is showing, since there is no chart to capture at that point. Exported images always have a white background, regardless of the chat's colour theme. |

Hovering a bar, line point, or pie slice shows its exact value in a tooltip; for Pie, the tooltip also shows the slice's share of the total. Bars also print their value directly on the bar, abbreviated for large numbers (for example, 12,345 shows as 12.3K) — hover for the exact figure. A bar with a value of exactly 0 is marked with a small "0" at its baseline instead of drawing a bar. Line and Multi-line charts print each point's value near it when there's room for every point to show its own label without overlapping; otherwise no point labels are shown and the values remain available by hovering.

In the table and CSV, the column headings follow the chart's own labels: for single-series **Bar** and **Line** charts, the value column is headed with the **Y-axis label** if one is set, rather than a generic placeholder; for **Pie**, the two columns default to "label" and "value" unless **X-axis label** and **Y-axis label** are set, which override those defaults (Pie has no axes, so these two settings otherwise have no effect on the chart itself); for **Combo**, the three columns are the shared `x` category followed by the bar series and the line series, each named from that series' own **Y-axis label** field (or "Bar" / "Line" if left blank). Numeric values, including negative numbers, export as plain numbers rather than as quoted text.

In the webchat widget, charts (and their table view) render taller when the AI agent is published through the fullscreen webchat product than in the standard Webchat popup. The same chart in the Inbox conversation thread always renders at one fixed height, regardless of channel.

## Validation

When **Chart data input** (or, for Combo, **Bar data input** / **Line data input**) is entered as literal JSON rather than a variable or a template expression, it's checked as soon as the action is saved:

* The list must not be empty — `[]` is rejected.
* Each row must match the shape for the graph type: a `series` value is rejected for Bar, Line, Pie, and each of Combo's two inputs; it's required for Grouped bar, Stacked bar, and Multi-line.
* `x` values (or `x`/`series` pairs, for multi-series types) must not repeat within the same input.
* `y` values must not be negative for Pie.

A row that fails is reported by number and field, for example "Row 2 is invalid (y: Field required)", shown inline under the specific field that failed — including the correct one of **Bar data input** / **Line data input** for Combo.

If the field instead holds a chat variable, or JSON with an embedded variable reference, none of this can be checked on save — it's only evaluated, and can only fail, when the action runs.

## Example

```
Send graph
• Type:  Bar
• Data:  {recent_transactions}
• Title: "Your transactions this month"
```

## Related

{% content-ref url="/pages/dS84QlBWMPsz088Q7VcB" %}
[Send API](/docs/modules/ai-agents/workflows-and-actions/send-api.md)
{% endcontent-ref %}

{% content-ref url="/pages/h76VVFDGINQSgTbHDUvJ" %}
[SQL query](/docs/modules/ai-agents/workflows-and-actions/sql-query.md)
{% endcontent-ref %}
