3.6.0 is the AI release. The library has carriedobservation hooks,native annotations, and astreaming-first runtime for a while; this version turns those pieces into an explicit AI-facing surface. Charts now declare what they're for, datasets get profiled and ranked, audiences get calibrated, and conversations anchor back onto the chart instead of stopping at a chat bubble. Three case-study posts published alongside this release walk through what that makes possible. Full release notes are onGitHub.
Why this matters
The default pattern for "AI on a chart" today is a chat box next to the visualization. The user types a question in prose, the model answers in prose, and the chart is decorative. Both ends lose information: the user has to verbalize which point they meant; the model has to verbalize where the answer applies. The chart already encodes those spatial signals on screen. The 3.6.0 surface is a bet that the right shape isn't "chat with a chart" buttwo-way structured context — charts emit profiled data and capability descriptors, models consume those AND return back annotations the chart natively renders.
Three things compose under that frame: a heuristic recommendation engine that ranks charts for a dataset (so any agent can answer "which chart?"), a focus + interrogation pair that gives a chat surface a point-of-anchor (so any agent can answer "about which row?"), and a capability descriptor per chart that turns the library itself into a structured catalog (so an LLM can reason about the visualization options without prompt-stuffing the entire reference docs). None of these primitives require an LLM to be useful — the recommender is offline-deterministic; the interrogation hook is headless — but each one produces the kind of structured context that lands cleanly when a model is on the other side.
A chart recommendation engine — heuristic-first, LLM-optional
Every chart in the library now ships a capability descriptor: what data shapes it serves, what intents (`trend`, `correlation`, `distribution`, `part-to-whole`, eleven more) it answers well, what settings change those answers, and what `buildProps` would look like against a given profile. suggestCharts(data, options?) returns a ranked list of suggestions with runnable props, an audit trail of reasons, and caveats. Pair it with anAudienceProfile — a serializable per-organization config of familiarity numbers and adoption targets — and the ranking calibrates to who is actually reading.
The deeper architectural move is that the same descriptors feedsuggestDashboard (composite multi-intent views with honestintentsMissing reporting), suggestStretchCharts (a literacy-growth surface that shows charts the audience is unfamiliar with but the data actually supports),scoreChart (single-chart introspection), useChartSuggestions (the React hook), and the MCP server's suggestCharts tool. One catalog, many surfaces. The post onCharts that know what they're forwalks through the design, the audience layer, and the stretch surface in detail.
Anchored conversation — focus + interrogation + annotation
The other half of "AI on a chart" is what happens when the user wants to ask aboutthis point. Two new hooks compose into that pattern: useChartFocussubscribes to the chart's observation store and returns the latest hover/click as{ datum, x, y, source }; useChartInterrogation gives consumers a { ask, history, summary, annotations, loading, error, reset } surface where the consumer brings their own LLM via onQuery. The hook supplies the model with the profiled data summary, the suggestion list, and the current focus datum as structured context; the model returns annotations the chart natively renders.
The detail post — Anchored conversations — works through the bidirectional loop: the user points at a data point, the AI answers about that specific point, and the answer lives on the chart as a clickable note. Pronouns work. Comparisons get cheap. Answers persist where they're useful. The chart accumulates institutional knowledge about itself.
Compose that with the realtime runtime and the chat surface flips from passive observer to active narrator:Live conversational dashboardssketches the product shape — streaming data + an AI watching alongside you + anchored annotations + a conversational follow-up surface — and walks through the pieces that compose it.
Capability descriptor refinements
Authoring the per-chart descriptors surfaced a few cases where the chart family's recommendation behavior was wrong on its face. Those are tightened in this release:
AreaChart is now a single-series chart.Multi-series area overlays are an occlusion nightmare; the capability subselects to the leading series (largest cumulative y) when the input has 2+ groups and surfaces a caveat. Gradient fill is the baseline default. AreaChart now outranks LineChart on single-series trend (the gradient is more visually arresting than a thin line); LineChart still wins on multi-series because it shows the whole dataset instead of one slice.DifferenceChart accepts 2+ series via top-2 subselection.Previously rejected anything other than exactly two series; now picks the two series with the highest cumulative y and emits a caveat when subselecting from 3+. Makes the chart a real alternative on multi-series data where the comparison-between-two story is the interesting one.Scatterplot and ConnectedScatterplot prefer the canonical 2-numeric form when a sequence axis is present.On {quarter, revenue, profit} data both charts now plot revenue × profit (the canonical correlation form) instead of recapitulating a line chart on quarter. ConnectedScatterplot threads the sequence as orderAccessor so the path encodes temporal progression — Hans Rosling's "income vs life expectancy over years" shape, served automatically when the data supports it.X_FIELD_HINT recognizes calendar-segment field names.The profiler's x-axis name regex now matches quarter, qtr,fiscal, and week. Without this,{quarter, revenue, region} data fell into scatter-fallback provenance and series detection never fired — lineBy / areaBy were silently dropped and multi-series time-series charts zigzagged across regions.
For agents — the MCP server and the CLI
npx semiotic-mcp launches a Model Context Protocol server that exposesrenderChart, interrogateChart, suggestCharts, anddiagnoseConfig as MCP tools. Agents inside Claude Code, Cursor, Windsurf, and other MCP-aware environments can drive Semiotic directly — render a static SVG, profile a dataset, ask the recommender for a ranked list, repair a config that doesn't validate.npx semiotic-ai --doctor covers the CLI variant: pass a{component, props, data} JSON spec and get back a validated config (or a ranked list of alternatives if the requested chart doesn't fit the data).
Upgrade notes
Most of 3.6.0 is additive. The capability-descriptor refinements above are the one behavior change worth flagging:
- AreaChart on multi-series data. If you were passing multi-series data to
AreaChart directly (not via suggestCharts) and relying on the chart to render overlapping multi-area output, that path still works at the chart level — the capability change affects what the recommender suggests, not the chart's prop surface. The chart's areaBy prop is untouched. The change is aboutsuggestCharts output: AreaChart suggestions now subselect their data. - Scatterplot's x/y on sequence-shaped data. Same caveat — the chart still plots whatever you pass it; the recommender's
buildProps output changes. Any code reading suggestion.props.xAccessor / yAccessor for charts with {sequence, num1, num2} shape will now see the two numerics in place of the sequence. DifferenceChart data pivoting.The chart's wide-form data contract (`{x, a, b}`) is unchanged. The recommender now pivots long-form input automatically and emits the wide form onsuggestion.props.data.