Tool design for an analytics agent
The quality of an AI assistant over your data is decided by the tools, not the model. Nine rules learned from building twelve of them over music data sources.
Danny Starr
Co-founder, Backline · 4 August 2026 · 3 min read
In short
- Tools should return answers to questions people ask, not tables of rows. One well-shaped tool beats three primitives the model has to join.
- The empty case is part of the interface. A tool with no data must say which source is missing and why, in structured form.
- Put units and caveats in the response, not only in the description. The model sees the response at the moment it writes.
- Where an ambiguous answer would be misleading, return a request for clarification instead of a number.
- Never make a tool the only thing standing between a caller and another tenant's data. Scope comes from the session.
We have twelve tools sitting over a music project's connected sources. Rewriting several of them taught us more about answer quality than any prompt change.
1. Shape tools around questions, not tables
The instinct from API design is small, composable primitives. For an agent it is usually wrong, because every join the model has to do is a chance to do it differently than the dashboard did.
Compare two designs for live shows. Primitives would be list-shows, get-capacity and get-ticket-sales, leaving the model to compute sell-through. One tool returns each show with its ticket pacing summary already computed: latest sold, sell-through against capacity, first and last data date, number of points.
The second is better on three counts. The arithmetic matches the dashboard because it is the same function. The model spends its attention on the answer rather than the join. And it takes one call instead of three, which matters when a loop is bounded.
2. Make the empty case structured
The most common state for any given source on any given project is not connected. That is not an error and it is not silence.
A good empty response says which source is missing, that this is expected rather than broken, and what connecting it would add. The model then writes something useful, and the manager learns something about their setup.
Three responses to a project with no ticketing connected
Illustrative| What the tool returns | What the assistant then says | |
|---|---|---|
| Bad: an error | A thrown exception | An apology, or worse, a retry loop |
| Bad: an empty array | [] | There are no ticket sales, which reads as zero sales |
| Good: a structured empty | available: false, reason: no ticketing source connected, what_it_adds: per-show pacing and sell-through | No ticketing source is connected for this project, so I cannot comment on ticket sales. Connecting one would add per-show pacing and sell-through |
3. Put the caveats in the response
Tool descriptions are read once when the model plans. The response is what it has in front of it while writing.
So units, cadence and warnings belong in the returned data. Our ticket sales tool returns a notes field explaining that bulk box-office uploads and per-show pacing are two different sources that must never be silently combined. Our short-form tool returns a note saying own-account metrics are not the same as videos using the song. Those notes materially change the answers.
4. Return a refusal when ambiguity would mislead
Covered in the assistant article, and it is a tool design rule: when a project has several ad accounts and the call does not say which, the tool returns the account list and no figures.
The general form is to identify the cases where a plausible answer would be wrong and make the data for that answer unavailable, rather than adding another sentence to a prompt.
5. One computation, two consumers
Every number a tool returns should come from the same function the interface uses. When they diverge, the customer sees two numbers and stops trusting both.
The practical discipline is that the shared function lives in its own module with no framework or database imports, so it is unit-testable and can be called from a page, an API route and a tool without duplication.
6. Scope at the boundary, not in the tool
The project identifier comes from the authenticated session and is passed in. A tool must never accept a project list from the conversation, because the conversation contains whatever the user typed.
For token-authenticated access, the same rule applies one level up: the token grants access, and every read is scoped by it. A tool is not an access control layer, it is a reader operating inside one.
7. Bound everything
A hard iteration cap on the tool loop. Timeouts on every outbound call. Caps on rows returned. A model asking for a year of daily data across five sources will happily fill a context window with numbers it cannot use, and the answer gets worse rather than better.
One question, four tools, one bounded loop
IllustrativeGive me a two paragraph summary of how Nine Mile Tide did in July for the label.
Data readget_streaming_statsget_audience_geographyget_smart_link_statsget_live_shows
July was a growth month driven by one market. Streams across Spotify, SoundCloud and YouTube totalled 318,000, up 22 percent on June, with monthly listeners ending the month at 74,900 and followers at 21,400. Follower conversion ran at 26 new followers per thousand new listeners, which is the strongest three consecutive weeks the project has recorded.
Most of the movement is in the Netherlands, where listeners roughly doubled and now represent 19 percent of the total against 11 percent in June. Two upcoming shows have ticket data: Amsterdam is at 84 percent of capacity with four weeks to go, and Rotterdam is at 46 percent and has not moved for eight days. Landing page clicks were 9,200 with Spotify taking 66 percent.
Illustrative example using a fictional project. Four tool calls, one bounded loop, and every figure in the answer traceable to one of them.
8. Name tools for what they answer
get_ticket_sales beats query_sales_table. The name is read by the model as documentation, and a name describing the question it answers gets chosen correctly more often than one describing a data structure.
The same goes for fields. sell_through_pct is unambiguous. ratio is not.
9. Test the tools without the model
Tool logic belongs in pure functions tested directly against synthetic inputs: a project with no data, a project with one day, a project with a gap, a project with several accounts, a project where one source errors.
Testing through the model is slow, non-deterministic and tests the wrong thing. The model's job is judgement about which tool to call. The tool's job is to be correct, and correctness is testable.
What we would do differently
We started with tools shaped like our database and moved towards tools shaped like questions, and every one of those moves improved answers. If we were starting again, the first design question would be: what does a manager actually ask on a Monday, and what would one call have to return to answer it completely.
Common questions
- Should AI tools be small primitives or high-level answers?
- High-level, for analytics. Primitives force the model to join data itself, which is where it diverges from the dashboard's arithmetic and where the iteration budget goes. A tool that returns shows with their sell-through already computed produces better answers than three tools the model has to combine.
- What should a tool return when a data source is not connected?
- A structured response saying it is unavailable, why, and what connecting it would add. An empty array is dangerous because it is indistinguishable from a genuine zero, and a confident zero about ticket sales or streams is worse than admitting the gap.
- How do you test AI tools?
- Test the tool logic as pure functions against synthetic inputs: no data, one day of data, a gap in the middle, several accounts, one source failing. Testing through the model is slow and non-deterministic, and it tests the model's judgement rather than the tool's correctness.
Sources
- 1Anthropic, Reviewed August 2026. Tool use with Claude
- 2Model Context Protocol, Reviewed August 2026. Introduction to MCP
Danny Starr
Co-founder, Backline
Danny Starr is a co-founder of Backline and builds the platform. He writes about the data engineering behind music analytics: ingestion, identity, honesty in charts, and the AI layer on top of it.
Backline does this for the projects you run
Streaming, audience, social, advertising, website, search, ticketing and press data in one dashboard per project, with an AI assistant that answers questions about your own connected data. Invite-only.
Keep reading
AI and automation
Why an AI assistant must refuse to guess
An AI chatbot that invents plausible numbers is worse than having no assistant. Why constraint by architecture matters more than instruction.
Danny Starr · 2 min read
AI and automation
Why analytics data should be reachable by any AI client
A platform that only works with its own AI assistant is limiting. Why exposing analytics to external AI clients matters, and what the risk model is.
Danny Starr · 2 min read
Analytics foundations
The honest empty state
A dashboard is judged on how it behaves when it has nothing to say. Four kinds of nothing, why they must look different, and the interpolation that quietly destroys trust.
Danny Starr · 3 min read

