AI DevelopmentNew Release12 min readPublished October 25, 2026

A chart compiler for agents · not a model, not Recursive's Flint

Microsoft Flint: Build Interactive Charts with AI Agents

Microsoft Research published Flint-interactive on October 22, 2026, three days after its Flint 1.0 changelog entry. Flint is an open source visualisation language in which an agent writes a short chart spec and a list of interactions, and a compiler turns raw clicks and drags into semantic events and applies high-level update operators. The pitch is that this removes the fragile event-handling code that generated interactive charts usually break on. This guide explains what the compiler takes over, what it does not yet cover, and how to read a filtered chart honestly.

DA
Digital Applied Team
Senior strategists · Published October 25, 2026
PublishedOct 25, 2026
Read time12 min
SourcesMicrosoft Research · GitHub · npm
Research post
Oct 22, 2026
Flint 1.0 changelog dated Oct 19; npm 1.0.0 on Oct 21
Interaction presets
23presets
Vega-Lite backend only, as of Oct 26
Chart types
52× 5
Vega-Lite, ECharts, Chart.js, Plotly, Excel
Licence
MIT·
microsoft/flint-chart · npm flint-chart 1.0.1

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.

Key takeaways
  1. 01
    Flint 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.
  2. 02
    Interactions 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.
  3. 03
    Interactivity 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.
  4. 04
    Filter 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.
  5. 05
    Keyboard 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.

Hand-written

Event code against marks

what an agent produces without a compiler

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.

Flint-interactive

A preset or a handler on events

docs/interaction-api.md · read Oct 26, 2026

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.

Compiler owns
Triggers to events, operators to pixels
Visuallogic

Hit-testing, element resolution, rendering and layout. The author never manipulates renderer-specific marks.

research post
Author owns
Event to update operator
Intentmapping

A preset with options, or a trigger plus a handle function that returns updates such as set-style, set-annotation, set-viewport.

API guide
Spec holds
What is shown arrives as an update
Nostate

Emphasis, notes, viewport and order are chart updates applied through the surface, never fields in the spec.

interaction spec
Static cost
No interactions, no runtime
≈ 0runtime

A spec without interactions mounts nothing extra and costs about the same as a plain Vega-Lite embed, per the guide.

API 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.

Preset families from the repository's declarative spec documentation, read October 26, 2026. Preset names are the documented identifiers; the grouping is ours.
FamilyPresetsNeeds from the chartWhat the reader does
Emphasisclick-highlight, click-group-focus, hover-group-focus, axis-highlight, legend-toggleElements; a group field for the group presetsClicks or hovers to bring out marks and mute the rest
Inspectioninspect, inspect-index, click-annotateElements; an index axis for inspect-indexReads values of the nearest mark or every series at one x
Selectionselect, lasso-select, brush-x, brush-y, brush-angle, linked-brush, context-menuA cartesian or angular regionDrags a region; linked-brush echoes groups across charts
Navigation and orderbrush-zoom, navigate, drag-reorder, filter-controlsNavigation axes, a reorderable axis, or filterable fieldsZooms, pans, reorders categories, filters rows
Activation and accesslong-press, double-activate, context-activate, accessible-navigationElementsHands 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.

Write the denominator into the title
Whichever mode a filter uses, the chart should say what the percentages are of. Flint's chart spec carries a title and subtitle that an application can update from the same semantic event that applied the filter, so "share of all tickets" can become "share of EMEA tickets" the moment the rows change. A filtered chart with an unchanged title is the most common way an honest dashboard ends up misleading.

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.

Pointer only
click-highlight and friends
mouse · touch

Visual emphasis on click or hover. A keyboard user can read the chart but not operate the interaction.

default outcome
Targeting
keyboardTargeting option
marks only

Moves between marks with the keyboard. Ignored when the full navigation preset is present; the two do not combine.

lightweight
Full walk
accessible-navigation preset
titles · axes · legends · series · marks

Tabs into the chart and names each element and what it represents, emphasising its data as it goes. One line in the spec.

recommended

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.

Agents producing charts inside a chat or canvas for analysts
Add the Flint MCP server and let the agent emit an interaction spec. Selections become context for the next turn, which hand-written event code cannot offer.
MCP server
A product dashboard where charts, tables and widgets must stay in sync
Use the npm library on Vega-Lite, listen for semantic events, and drive charts with update operators. Hand the agent the two authoring skills.
flint-chart library
An existing ECharts, Chart.js or Plotly product that needs interactivity
Flint compiles static charts and themes for those backends but its presets do not run there as of October 26. Render the interactive charts on Vega-Lite or wait.
Static only today
Reports and documents a colleague will edit
Emit native Excel charts. No interaction runtime exists there, and none is needed; the deliverable is an editable object.
Excel output
Any chart a human reads in a browser
Add accessible-navigation to the spec and name the denominator in the title. Both are one line each and neither happens by default.
Always
Our readingFlint-interactive is the clearest attempt we have seen to give agents a vocabulary for chart interaction instead of an event model. The compiler owns the part that generated code breaks on, and the preset catalogue is broad. The limit is one line in the API guide: presets run on Vega-Lite only today. Adopt it where you can render on that backend, keep filter modes honest about their denominator, and treat the research post's cost and reliability framing as motivation, not measurement.

09 — ConclusionLet the agent say what a click means, not how to draw it

What to do, October 26, 2026

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.

Charts your agents can be trusted with

Declare the interaction, compile the chart.

We build agent-driven reporting where the charts are compiled from specs, the interactions are declared rather than hand-coded, and every filtered view says what its percentages are of.

Free consultationExpert guidanceTailored solutions
What we work on

Agent reporting and dashboards

  • →Chart specs with semantic types and named units
  • →Interaction presets chosen per chart claim
  • →Filter modes and titles that keep denominators honest
  • →Keyboard-navigable charts in agent outputs
  • →MCP and in-app rendering wired to your data layer
FAQ · Microsoft Flint interactive charts

The questions builders are asking.

Microsoft Flint is an open source, MIT-licensed visualisation language from Microsoft Research that compiles short chart specs into native specs for Vega-Lite, ECharts, Chart.js, Plotly or Excel. Version 1.0 added Flint-interactive, a layer of interaction presets, semantic events and an API for connecting charts to applications. It has no connection to Recursive's Flint coding model, which is a language model and shares only the name.
Digital Applied newsletter

Deep dives on AI, marketing and development.

Practical guides and fresh insights by email. No recycled takes.

Related dispatches

Continue exploring agent-built reporting.

Google Search

See more Digital Applied analysis in your Google results by adding us as a preferred source.

Add as a preferred source