ChartTools collection exposes a single tool, chart_generator, that produces a typed chart artifact. One instance is created per thread, bound to its thread_id, so the persisted artifact lands on the right conversation without the id being an LLM-facing parameter.
The tool does not render anything server-side. It validates and normalises the data into a small JSON payload, and the frontend’s artifact registry dispatches on the artifact_type to a recharts component (LineChartView, BarChartView, or PieChartView). This is the typed-artifact pattern: the agent emits typed data, the frontend owns the rendering, which keeps the agent’s surface area small (no SVG, no React) and avoids the XSS or sandboxing concerns of agent-emitted markup.
Shared conventions (the @workspace_tool contract, the injected action_and_reasoning argument, and the (content, artifact) return) are documented in Tools; the end-to-end artifact channel (persistence, the SSE artifact event, the frontend registry) is in Agent core logic. The decorator injects the required action_and_reasoning argument, so it is omitted from the argument table below.
Source: backend/app/tools/charts.py
chart_generator
Generate a line, bar, or pie chart that renders in the centre artifact panel.
Description shown to the agent:
Generate a chart that will appear in the centre artifact panel. Pick the chart_type that best matches the user’s intent (line for trends, bar for comparisons, pie for proportions). Returns a confirmation message; the chart itself renders automatically in the frontend after this call. Suppose the chart is already displayed when you compose your reply.Arguments
The data argument
The data field carries strict, instructive guidance to the agent because the shape is enforced on the server. This is the verbatim Field description:
Style options
The optionalstyle object (ChartStyleArgs) is forwarded to the renderer as data, never code; the frontend applies safe defaults when a field is omitted.
Returns: a
(content, artifact) tuple. The content is a confirmation for the agent, e.g. Created a line chart titled 'Revenue' with 4 data points. It is now displayed in the artifact panel., which becomes the summary of the envelope. The artifact is persisted into the artifacts table (tagged with the per-turn index) by the decorator and emitted on the SSE stream as a dedicated artifact event, which updates the centre panel live. Its shape is:
{"success": false, "error": ...} envelope so the agent can retry) when:
chart_typeis not one ofline,bar,pie;datais empty;- any point is not an object, or is missing the literal
namekey.
description is empty, the tool synthesises a subtitle (e.g. Line chart over 4 data points.). The style object is coerced to a plain dict with None fields dropped before persistence.
Implementation: normalises every point (stringifying each name), builds the artifact_type as f"{chart_type}_chart", and returns the tuple; persistence and streaming are handled by the decorator and the SSE layer, not the tool body. Source: backend/app/tools/charts.py.