Ask a coding agent for a chart and you usually get one. Ask it for a chart you can brush, link to a second chart and filter from a table, and the request can grow into renderer-specific event handlers with edge cases to test. On October 22, 2026 Microsoft Research published Flint-interactive, a language that moves that event-handling into a compiler so the agent only has to say what a selection means and what should change in response.
Flint itself is not new. It is an MIT-licensed project from Microsoft that compiles short, human-editable chart specs into native specs for Vega-Lite, ECharts, Chart.js, Plotly or Excel. Version 1.0, logged in the changelog on October 19 and published to npm on October 21, added the interactive layer: 23 interaction presets, a semantic event model and an API that connects charts to the application around them. The research post explains the design; the repository documents its limits.
One disambiguation before anything else. This Flint is a Microsoft chart library and has nothing to do with Recursive's Flint coding model, which we covered in our Recursive Flint post. This post is about the chart compiler: what it does for an agent, why interactivity currently works on only one of its five backends, how a filter changes the denominator of what a reader sees, and where keyboard access comes from.
- 01Flint is a chart compiler, not a model.An agent writes data, semantic types, a chart spec and an optional interaction spec. The compiler infers scales, axes and formatting and emits a backend-native spec. No language model is inside Flint; it runs under whichever agent calls it.
- 02Interactions are semantic events mapped to update operators.The compiler resolves raw clicks, drags and key presses into events that name chart elements and data, and renders update operators such as set-style, set-annotation and set-viewport. The agent never touches renderer marks or hit-testing.
- 03Interactivity runs on Vega-Lite only, as of October 26.The repository's API guide says presets currently support Vega-Lite; on another backend the chart renders static with a warning. The 52 chart types and 5 backends apply to static output, not to interaction.
- 04Filter and highlight modes answer different questions.The 1.0 filter-controls preset either removes rows that fail a filter or mutes them. Removing rows changes every share-of-total the chart shows; muting keeps the denominator. Pick the mode to match the claim the chart makes.
- 05Keyboard navigation is a preset, not a default.An accessible-navigation preset walks titles, axes, legends, series and marks by keyboard, naming each. It is not combined with the simpler keyboard-targeting option, and neither is on unless the spec asks.
01 — The ReleaseWhat Microsoft published, and on which dates
Three dates sit behind this release and they are easy to conflate. The Microsoft Research post introducing Flint-interactive is dated October 22, 2026. The project site and the repository changelog record Flint 1.0, the release that introduced the interactive layer, under October 19. The npm registry shows version 1.0.0 published on October 21 and 1.0.1 the same day. Keep the changelog date, npm publication date and research-post date separate when describing availability.
What 1.0 contains, per the repository: interaction presets, semantic events, and an interaction API that connects charts to an application. The README puts the project's scale at 52 chart types across five rendering backends, 14 themes and 23 interaction presets, and lists an arXiv paper, an MIT licence and two npm packages that version together, the library and an MCP server. The changelog's 1.0.0 entry adds a validation function that checks a list of chart updates against a chart in one pass and a filter-controls preset that draws controls under a chart.
The failure case in reading this release is treating the headline counts as a single feature set. They are not. The chart-type and backend counts describe static output. The 23 presets describe interaction, which section 04 shows is narrower. Keep the two ledgers separate and the rest of the documentation makes sense.
- Research blog postFlint-interactive introduced
- October 22, 2026Microsoft Research
- Flint 1.0 changelog entryinteractive layer added
- October 19, 2026project site and CHANGELOG.md agree
- npm publishflint-chart and flint-chart-mcp
- 1.0.0 and 1.0.1 on October 21registry timestamps, read October 26
- Static scopeREADME
- 52 types · 5 backends · 14 themesVega-Lite, ECharts, Chart.js, Plotly, native Excel
- Interactive scopedocs/interaction-api.md
- 23 presets · Vega-Lite onlyother backends render static with an interactions_ignored warning
02 — The ProblemWhy generated interactivity breaks
The research post names two reasons agents struggle with interactive charts, and both will be familiar to anyone who has asked for one. The first is generation cost: an agent rarely produces a satisfactory interactive visualisation in one turn, so the work becomes rounds of reasoning, coding and debugging that burn tokens and time. The second is reliability: expressive interactive charts introduce poor layouts and broken interactions easily, and each fix risks a new fault.
The post's diagnosis is that both problems come from the absence of a high-level language for interaction. Built-in interactions in chart libraries are not expressive enough for bespoke behaviour, so the agent drops down to the library's event model and writes handlers against renderer-specific marks. Those handlers depend on hit-testing, layout and rendering state that the agent cannot see and did not write.
A concrete illustration, built on the research post's own first example. Ask an agent for two scatter plots where brushing a region in one highlights the same countries in the other. The hand-written version must track the brush rectangle, map pixels to data, find matching rows, find the corresponding marks in the second chart, restyle them, and undo all of it on a click elsewhere. Any change to axis range, mark size or theme can break a step. The same request in Flint is one preset, linked-brush, with a group-by field. The compiler centralises those responsibilities; the resulting interaction still needs testing.
Event code against marks
Pixel-to-data mapping, hit-testing, cross-chart lookups, restyling and reset logic, all specific to one renderer and all re-derived every time the chart changes. Our illustration, not a measurement.
A preset or a handler on events
Declare linked-brush with a groupBy, or map a semantic event to set-style and set-annotation in a handle function. The compiler resolves triggers, elements and rendering; the agent writes intent.
03 — The MechanismEvents in, operators out
The post describes Flint Canvas as a state machine that tracks interactions and manages rendering state, and splits the work into two layers. Visual logic belongs to the compiler: it resolves raw triggers such as clicks, drags and key presses into semantic events that identify chart elements and the data behind them, and it translates update operators into rendered changes, handling hit-testing and low-level updates. Interaction logic belongs to the author: a mapping from semantic events to update operators, such as set-style to highlight, set-annotation to label a point or set-viewport to pan and zoom.
The API guide makes this concrete. You mount a chart with a backend and a list of interactions; presets come from factory functions, and bespoke interactions define a trigger and a handle function that maps the event to a sequence of chart updates. The same events can leave the chart entirely: an application listens for them to filter a table, update a second chart or change its own state, and sends update operators back to drive the chart from a widget. The post's second example, a table row selecting a bubble and vice versa, is exactly that loop.
Two details in the API guide matter for anyone building on it. State is not part of the spec: what the chart currently shows, an emphasis, a note or a viewport, arrives as a chart update through the surface, so a spec stays a description and never a snapshot. And a chart with no interactions mounts no interaction runtime, so a static Flint chart costs about the same as a plain Vega-Lite embed. The failure case is a developer who passes an empty updates list expecting a static chart; the guide says even an empty list mounts the runtime so the host can apply updates later.
Triggers to events, operators to pixels
Hit-testing, element resolution, rendering and layout. The author never manipulates renderer-specific marks.
Event to update operator
A preset with options, or a trigger plus a handle function that returns updates such as set-style, set-annotation, set-viewport.
What is shown arrives as an update
Emphasis, notes, viewport and order are chart updates applied through the surface, never fields in the spec.
No interactions, no runtime
A spec without interactions mounts nothing extra and costs about the same as a plain Vega-Lite embed, per the guide.
04 — The CatalogueTwenty-three presets, one backend
The declarative spec documentation lists the presets with what the reader does, what the chart must provide and what resets them. They fall into families: emphasis on click or hover, with or without grouping; pinned annotations; inspection of the nearest mark or of every series at one x position; rectangular, freehand, axis and angular selections; linked brushing across charts; zoom and pan; legend toggling; filter controls; a context menu of host actions; axis highlighting and drag-to-reorder; and keyboard navigation. Each preset declares the chart semantics it needs, so a brush-angle preset on a bar chart is refused rather than silently ignored.
The limit that the headline counts hide is in the API guide's first note: Flint's interaction presets currently support Vega-Lite. Mount a chart on ECharts, Chart.js or Plotly with an interaction spec and it renders static, with a warning named interactions_ignored. Excel output is native chart objects and has no Flint runtime at all. So the 52-types-by-5-backends matrix is a static matrix, and the interactive matrix is 23 presets on one backend, as read on October 26, 2026.
The example that catches teams is an existing ECharts dashboard. Flint will compile charts for it, and the themes apply, but adding a linked-brush preset will not make those charts interactive. The honest options are to render the interactive charts on Vega-Lite or to wait for backend support that the documentation does not yet promise a date for. We would not plan a product around the second.
| Family | Presets | Needs from the chart | What the reader does |
|---|---|---|---|
| Emphasis | click-highlight, click-group-focus, hover-group-focus, axis-highlight, legend-toggle | Elements; a group field for the group presets | Clicks or hovers to bring out marks and mute the rest |
| Inspection | inspect, inspect-index, click-annotate | Elements; an index axis for inspect-index | Reads values of the nearest mark or every series at one x |
| Selection | select, lasso-select, brush-x, brush-y, brush-angle, linked-brush, context-menu | A cartesian or angular region | Drags a region; linked-brush echoes groups across charts |
| Navigation and order | brush-zoom, navigate, drag-reorder, filter-controls | Navigation axes, a reorderable axis, or filterable fields | Zooms, pans, reorders categories, filters rows |
| Activation and access | long-press, double-activate, context-activate, accessible-navigation | Elements | Hands the host a target; walks the chart by keyboard |
05 — Reading FiltersFilter or highlight: the denominator question
The 1.0 filter-controls preset draws one row of controls per field under the chart, a segmented bar for a few values, pills for several, a searchable dropdown for many, sliders for ordered values, a switch for booleans. The changelog describes two modes. In the default mode the controls remove the rows that fail the filter and the chart lays itself out again for the rows left. In highlight mode the failing rows are muted instead and the chart's frame stays put.
That choice affects the question a chart answers, but the mode alone does not determine its denominator. Suppose a stacked chart recomputes channel shares from ticket rows after filtering. Removing other regions then makes the percentages shares of the selected region. If percentages were calculated upstream, however, hiding rows does not automatically recalculate them. Inspect the data transform as well as the interaction preset.
Highlighting can preserve the original comparison by muting marks rather than removing their data. That works only where the selected field is represented at the mark's granularity: a monthly aggregate cannot expose a regional share that the chart never retained. Choose the question first, inspect how aggregation and filtering interact, and label whether percentages refer to the original total or the filtered subset.
06 — Keyboard AccessKeyboard access as a preset, not a default
A chart implemented only with click and drag handlers can leave keyboard users without an equivalent way to operate it. Flint's catalogue includes an accessible-navigation preset that lets a reader tab into the chart and walk its titles, axes and their labels, legends and their items, facet headers, series and marks with the keyboard, with each step naming the element and what it represents and emphasising its data. A lighter keyboard-targeting option moves between marks only; the documentation says the two are not combined, and the option is ignored when the preset is present.
The point for builders is that neither is on by default. A spec with click-highlight and nothing else produces a chart a keyboard user can see but not operate. The React component also exposes an aria label, and the semantic types that drive formatting mean the values the preset reads out are the values the chart prints, not raw numbers. The failure case is the dashboard that passes a visual check and ships with no keyboard path, which is the default outcome unless the agent's instructions ask for the preset.
A practical rule: include accessible-navigation in the agent's chart-authoring instructions for any chart a human will read, alongside whichever pointer presets the task needs. It is one line in the interaction spec, and then test keyboard operation, labels and screen-reader behaviour in the rendered output.
click-highlight and friends
Visual emphasis on click or hover. A keyboard user can read the chart but not operate the interaction.
keyboardTargeting option
Moves between marks with the keyboard. Ignored when the full navigation preset is present; the two do not combine.
accessible-navigation preset
Tabs into the chart and names each element and what it represents, emphasising its data as it goes. One line in the spec.
07 — SurfacesIn chat, in an app, in Excel
The research post describes three ways to use the interactive layer. In chat, through the Flint MCP server and MCP Apps, an agent generates an interaction spec alongside the chart spec and renders the chart in the conversation, where a selection can be passed as context into the next turn. The repository offers the server as a local package or as a hosted endpoint and names GitHub Copilot in VS Code, Claude, Claude Code, Codex and Cursor as clients. How MCP Apps render interactive surfaces inside a chat is a topic we covered in our MCP Apps guide.
In an application, the npm library compiles specs and provides React and vanilla JavaScript APIs. The application listens for semantic events to filter a table or update another chart, and sends update operators to drive the chart from its own widgets. The repository's agent skills, one for chart authoring and one for interaction authoring, are meant to be handed to a coding agent so it can add charts to an existing app. The changelog's unreleased section also signals a coming breaking change to the MCP server, which will keep nothing between calls and redraw from the spec on every show.
In Excel, Flint emits native, editable chart objects, eighteen templates since version 0.4.0. That output has no interaction runtime, which is the right expectation: it is for reports and documents, where the deliverable is a chart a colleague can edit in the application they already use. For live dashboards built on connectors rather than static specs, our live client dashboards guide covers the other approach.
08 — FitWhen a compiled chart spec helps
The decision is not Flint versus a chart library; Flint compiles to the libraries. It is whether to let an agent write interaction code directly or to give it a vocabulary of events and operators and let a compiler handle the rendering. The router below is our reading of the documentation, not a benchmark, and the right answer depends on which backend your product already renders.
Two of our own earlier posts frame the surrounding questions. Any chart an agent produces still needs a human to check what it measures, a point our usage-chart inventory made about a vendor's own dashboards, and the semantic-type idea in Flint helps here because the units and domains are written down. And a dashboard is only as good as the data behind it, which is the part our analytics engagements spend most of their time on.
09 — ConclusionLet the agent say what a click means, not how to draw it
Render interactive charts on Vega-Lite through Flint, choose filter or highlight by the claim the chart makes, and add keyboard navigation to the spec.
Microsoft Research's Flint-interactive, described on October 22, 2026 and shipped in Flint 1.0 a few days earlier, moves the fragile part of interactive charts out of agent-written code and into a compiler. An agent declares a preset or maps a semantic event to update operators; the compiler resolves triggers, finds the marks and renders the change. The catalogue runs to 23 presets on an MIT-licensed library with an MCP server for chat and an npm package for applications.
The constraints are documented and worth repeating. Interactivity runs on Vega-Lite only as of October 26; the other four backends render static. Filter controls can remove or mute rows; the aggregation and any precomputed percentages determine the denominator. Label that meaning explicitly. Keyboard navigation is a preset the spec has to ask for.
None of this needs a new model. It needs the agent's instructions to include the two authoring skills, the accessibility preset and a rule about denominators. Test that the generated chart preserves the intended meaning and works for its readers.