A traditional dashboard is a wine list.
It has structure: categories, regions, vintages, prices. Everything the restaurant has is organized, accurate and technically available to you. If you already know wine, that might be enough.
Most people sit down without that context. They're trying to make a good choice with partial knowledge and a table full of other things competing for their attention. The list is correct, and it still doesn't tell them what to order.
Then the sommelier walks over and points to a line you skimmed past. The wine comes from a family that has farmed the same hillside for four generations. The grape is one almost nobody grows anymore, from vines older than the winemaker. That year a late frost took half the crop, so the grapes that survived came in small and intense, and the family aged the wine in old concrete instead of oak so nothing would cover that up. It's bright enough to cut through the short rib you just ordered, and it costs less than the bottles around it because hardly anyone knows to ask for it.
Nothing on the list changed. The region, the vintage and the price were printed there the whole time. What changed is that someone who knows the wine connected those facts to your dinner, and a long list of possible choices became one bottle you actually want to open.
That's the difference between a report that displays data and one that explains it. For a long time, we handed stakeholders wine lists and called it business intelligence. We made the information filterable, sortable and visually clean, and left the meaning as an exercise for the reader.
The dashboard that can't see the release
Pull up almost any support dashboard and you'll see the same tiles: tickets opened, tickets by category, resolution time, open versus closed, tickets by priority.
I built one for this post. It runs live below on synthetic data from a fictional B2B software company, and it follows the pattern most of us have shipped:
It's accurate and complete, and it even compares every tile with the thirty days before. The arrows are turning red. The backlog is up 207%. The team is opening more tickets than it closes, resolution times are drifting up, and SLA compliance is slipping.
Look closer and it gets worse. Ticket volume is up just 2%. A growing backlog against flat volume reads, to every instinct a dashboard trains, like a staffing problem: the team is slow, so hire more agents.
Underneath those tiles, a new API release is quietly breaking custom integrations for the largest customers. The dashboard's best guess points at the support team instead.
Can you see the release on it? I can't, and I'm the one who planted it there.
The dashboard shows a number. What it's missing is the sentence that explains the number:
- The number: backlog is up 207%.
- The sentence: backlog is up 207% while ticket volume is up only 2%, so the queue isn't flooded; it's jammed. The jam starts after an API release, concentrates in enterprise integration tickets, and points to a product fix before any support hiring.
That sentence is what a stakeholder needed. So when I look at a chart now, I ask what it's being compared with, whether the headline number is hiding a concentration underneath it, and what changed upstream: a release, a pricing change, a new customer segment. A bar chart becomes useful when someone can say what changed, why, and what to do next.
We stopped at the number for honest reasons. Data teams are usually asked to move data, not to understand the business it describes, and stakeholders often can't name the measures that matter until they see them. The request arrives as "show tickets by category," so that's what gets built. The explanation was always the real deliverable, and there was rarely anyone with the time to write it.
The answer was never only in the numbers
Dashboards are built from what can be counted. Every tile is an aggregate of structured fields: a status, a category, a timestamp. That's what made them practical, and it's also their blind spot.
The explanation for the support backlog lives mostly in text. Customers describe what broke in their own words in ticket conversations. The release that caused it is a code change in a repository. The failures show up in delivery logs. Engineers diagnose it in a Slack thread, and account managers hear about the business impact in email. None of that fits in a tile, and reading it used to mean a person working through hundreds of tickets, threads and log files by hand. So reports stayed with the counts.
Agents read text as readily as they read tables. That's the change that matters most for reporting. An agent can sort through ticket conversations for the complaint they share, read the diff of the release that went out, scan the logs for the error that started that week, and connect all of it to the numbers.
Hand a good sommelier a bottle they've never seen and watch what happens. They turn it over and read the region, the producer, the year, the alcohol printed in small type at the bottom. Before the cork is out, they'll tell you it's going to be lighter than you expect, a little earthy, and better with the mushrooms than the steak. They've never tasted this bottle. They've tasted thousands like it. A model does something similar with a dataset or a codebase it has never seen: it recognizes what kind of data it's looking at and what tends to matter in it.
The more valuable skill is the pairing: knowing what goes with what. The insight in this example sits in the connection between a flat ticket count, a growing backlog, a payload change, a spike in failed deliveries and a handful of accounts going quiet. No single source holds it.
So I gave the agent the same company, connected to every source, with a brief written the way support leadership would ask the question:
There's no prewritten finding and no hint about May. The agent still has to compare baselines, find the concentration, read what customers and engineers wrote, and connect the support symptom back to the product change.
The same data, served as a story
Here's what came back:
Backlog is up 207% while ticket volume is only up 2%, so the queue is not flooded; it is jammed. Enterprise integration tickets increased 48% after the May 6 API v2/webhook release, take 2.3x longer to resolve than other categories, and now drive 62% of breached SLAs. The likely action is to prioritize webhook and custom-mapping defects before adding more support staffing.
The text explains why. The release changed the shape of custom fields in the webhook payload, so integrations built on the old shape stopped syncing without any error on the customer's side. Failed deliveries rose almost fourfold. Engineering traced it in Slack within a week, and retries were making it worse. By the time an account manager wrote that two enterprise customers had paused their rollouts, the problem had moved from the support queue to revenue.
The pairing makes that concrete. The accounts filing those tickets are the ones whose usage dropped: eighteen enterprise accounts and about $106,000 in monthly revenue, still below their normal activity weeks later. A support metric has become a revenue risk, and the backlog finally makes sense. More agents wouldn't clear a jam that's waiting on engineering. Fixing the integration would.
Here's the same company's data, built as a page that leads with that story and shows the evidence underneath it, numbers and text together:
Same company, same quarter. One version ends with a red arrow. The other ends with a decision.
A report is a narrow web app
Strip the branding off a BI dashboard and what's left is a narrow, hosted web application for reports.
That was a real breakthrough. BI tools solved two problems data teams badly needed solved: publishing and access. You could build a report, put permissions around it and give people a link instead of a spreadsheet attachment, without becoming a front-end engineer.
The trade was control. A BI report lives inside someone else's frame: a canvas, a filter pane, a set of visuals and interactions the vendor decided should exist. You shape it by clicking through an editor. That bargain made sense when building a custom web page for every report was expensive.
Agents change that cost. The page above is ordinary web code, and so is the dashboard before it. Once the report is a web page you control, the rest of the web comes back. You can lead with the narrative and put the evidence underneath it. You can hold detail back until someone needs it, quote a customer next to the chart their ticket belongs to, and lay the page out around the decision instead of around a grid of tiles. The definition lives in code, so it can be reviewed, tested and versioned like any other software.
A data app in this sense can be modest. It can be read-only, built on a fixed dataset and made for a single meeting. It doesn't need to call a model when someone opens it; the agent's work happened while it was being built. That separates it from the operational applications I described in Building Business Applications, which run a process and change the business's records. How often a report's data needs refreshing is its own question, separate from how the report is built.
Beware the sommelier who invents the vineyard
A confident story that isn't in the data is worse than no story at all.
Every sentence in the narrative has to trace back to something you can check: a query you can re-run, a ticket you can open, a commit you can read. That matters even more with text than with numbers, because a summary of a hundred tickets can sound right and misrepresent all of them. In the demo, every number on the story page is computed from the same data as the dashboard, and each quote is labeled with the source it came from.
The agent can read faster than any analyst and connect more sources than any dashboard. Someone still has to decide whether the story is true. I wrote about how I check an agent's work separately, and reports deserve the same scrutiny as features.
Keep a few wine lists
Some numbers should stay exactly as they are: locked down, versioned and identical for everyone who looks at them. Monthly revenue for the board, the compliance figure a regulator sees. That's the job dashboards still do best, and it's a real one.
For everything else, the number is where the report should start. The data underneath has always been richer than a grid of tiles, and much of what explains it was sitting in text no report could read. Now an agent can read it, and the report can be built around what it found: what changed, why, and what to do next.
The list is table stakes. The service is what people came for.
