Skip to main content
The chart component renders a bar, line, or pie chart on the canvas. It is display-only.
Component idcanvas.chart
Versionv1
Action namecanvas_show_chart
Interaction classLifecycle-only (no submit or skip)
Default placementSide rail (safe-area-right), rendered inline
Live updatesYes, the PAL can update a visible chart in place
chart is enabled on any PAL with the Magic Canvas skill attached; see Enabling and configuring components. Its only config key is enabled (default true):
{ "config": { "components": { "chart": { "enabled": false } } } }

Behavior

The PAL decides when to draw a chart; there is no developer-triggered path. Its system prompt directs it to chart small numeric comparisons or trends, with short labels and numeric values. The PAL revises a visible chart in place by calling update_component with new data.

Arguments

FieldTypeRequiredDescription
chart_type"bar" | "line" | "pie"Which chart to draw (default bar).
dataarray of {label, value}The data points. At least 1; the renderer accepts at most 12.
data[].labelstringLabel for the point (renderer limit: 1–80 characters).
data[].valuenumberNumeric value for the point.
titlestringHeading above the chart (renderer limit: 1–120 characters).
x_labelstringX-axis label (renderer limit: 1–80 characters).
y_labelstringY-axis label (renderer limit: 1–80 characters).
No other arguments are accepted. Tavus also injects two runtime controls shared by every Canvas action: layout (preferred slot, one of safe-area-right or safe-area-left) and display_mode (enum [inline], always inline).
Arguments exceeding the limits above produce a load error card instead of a chart.

Example invocation

{
  "title": "Pipeline",
  "chart_type": "bar",
  "data": [
    { "label": "Qualified", "value": 18 },
    { "label": "Demo", "value": 11 },
    { "label": "Closed", "value": 4 }
  ],
  "x_label": "Stage",
  "y_label": "Count"
}

Interaction Types

chart is lifecycle-only: sending submit or skip returns a 400 (canvas.chart does not support this interaction type.). The interactions endpoint accepts four types:
TypeWhat it means
dismissThe user closed the card
clearThe canvas was cleared while the chart was on screen
errorThe client failed to display the chart
heartbeatA custom client’s periodic status ping
Expect canvas.chart interactions only from clients you build yourself. The stock Tavus SDK and hosted embed currently POST none of these: the card has no dismiss control, render failures surface only via the local onError callback, clearing the canvas removes instances locally without an interaction, and renderer heartbeats use a separate model-context channel that never reaches the interactions endpoint or your webhook.
Custom clients POST interactions to POST https://tavusapi.com/v2/conversations/{conversation_id}/canvas/interactions (validation rules). Each recorded interaction fires your conversation webhook once as a canvas.interaction event (message_type: "canvas") and is available via GET https://tavusapi.com/v2/conversations/{conversation_id}/canvas/interactions (API key required).

Example Webhook Event

A dismiss POSTed by a custom client:
{
  "message_type": "canvas",
  "event_type": "canvas.interaction",
  "properties": {
    "conversation_id": "c123456",
    "interaction_id": "ci_call_abc_dismiss_8f2e1c9a",
    "tool_call_id": "call_abc",
    "component": "canvas.chart",
    "component_version": "v1",
    "type": "dismiss",
    "value": {},
    "metadata": {},
    "created_at": "2026-06-09T21:14:03.214311"
  }
}
created_at is a Python isoformat() timestamp: UTC but timezone-naive, with microseconds and no trailing Z or offset. The same shape appears in the GET response.
For lifecycle types, Tavus validates the envelope (ids, component, type) but only enforces that value is an object under 16 KB; don’t depend on specific keys inside it.