Give an AI access to your data and it will happily answer any question you ask. The harder question is whether its answer matches the one everyone else in the company would give.
The problem a semantic layer actually solves
Ask three people in a company for the win rate and you will often get three numbers. Not because anyone is wrong, but because one counts opportunities, another counts logos, and the third excludes deals that never reached a real stage. The metric was never defined in one place, so it gets redefined every time someone needs it. This is the oldest problem in RevOps, and it has nothing to do with the data being dirty. The data is fine. The definitions are scattered.
Now point an AI at that same warehouse and ask it for the win rate. It will write a query, pick an interpretation, and return a confident number. That is a fourth definition, invented on the spot, indistinguishable from the other three unless you read the SQL. The easier it becomes to query data in plain language, the more this matters. An AI that recomputes your metrics its own way only adds a fifth opinion.
A semantic layer is the fix. You define each metric once, in one place, as the single agreed version. Everything that asks for that metric, a dashboard, a report, or an AI, reads the same definition. The number stops depending on who asked.
Why my own training data was the right sandbox
I wanted to actually understand this rather than read about it, so I built one. Not over a work dataset, over my own training data: years of cycling and running, recovery, sleep, and load, the same data that feeds my AI coach.
It was the right sandbox for three reasons. The dataset is real and messy in the ways real data is. The stakes are zero, so I could get it wrong repeatedly without consequence. And I know the domain deeply, which meant I could tell immediately when a number was off, something you cannot do when you are experimenting on data you do not understand. Working through the modern data stack on a subject I already knew let me focus entirely on the modelling instead of second-guessing the figures.
I used Cube for the semantic layer, running locally in a Docker container on my own machine, and deliberately left dbt aside for now. dbt models and transforms the data upstream. Cube defines the metrics at the point of query. For what I wanted to test, the metric definitions, only one of those mattered.
Define once, slice a thousand ways
The core idea is smaller than it sounds. Take power zones and heart-rate zones. Every source draws the boundaries slightly differently. Strava, intervals.icu, and WHOOP each decide for themselves where one zone ends and the next begins, often from a different threshold value to start with. So “time spent in zone 4 this week” quietly means three different things depending on which one answered. Each tool computing zones its own way is exactly the scattered-definition problem, in miniature.
In the semantic layer, the zone boundaries are written once, as one agreed definition. Every question about zones reads that single version, and the number stops depending on which source happened to calculate it.
The filtering does not live in the definition. “Time in zone 4 this week on the bike” is still the same zone metric, just with a date range and a filter on cycling added at the moment of the question. One governed definition answers a thousand different questions depending on how you slice it. The definition is fixed, the slicing is free.
That separation is the whole point, and it changes how the AI reaches an answer. Instead of sending the agent into the raw data to recompute zones from scratch, a different way each time, it queries the semantic layer, where the zone is already defined. Change the boundaries once and every question that touches zones updates with it. There is no second copy of the definition sitting in a tool or a script, quietly disagreeing.
Letting an AI query it safely
This is where it becomes genuinely useful with AI. I connected the semantic layer to Claude through a small bridge, so I can ask “what was my efficiency factor on the bike in June?” in plain language and get a governed answer back.
Neon Postgres in the cloud, the raw training data
│
▼
Cube (local) the semantic layer, every metric defined once
│
▼
MCP bridge (local) exposes only the defined metrics, never raw SQL
│
▼
Claude a plain-language question, a governed answer back
The important part is what the AI cannot do. It can only return metrics that exist in the model. Ask for something that was never defined and it gets an error, “that metric does not exist”, not an invented value and not a raw query it wrote itself. The AI never reaches the database directly and never writes its own SQL down that path. It can only ask for the metrics I defined, in the terms I defined them.
That constraint sounds limiting. It is exactly what you want. “I do not have that metric” is a far better answer than a confident number computed a way nobody agreed to. The semantic layer turns natural-language questions into governed answers, and refuses everything outside its own definitions. The AI becomes a safe way to query the business, not a fifth opinion on what the business measures.
Where this connects back to Fred
My AI coach, Fred, already answers questions about my numbers today. He does it with tools that compute each metric in Python, tuned to be fast and cheap in production. That works, and I am not replacing it.
The semantic layer is the governed version of the same idea. Instead of the metric definition living inside the app’s code, it lives in one place that both the app and any AI can read. For now this stays an experiment, deliberately downstream of the live system rather than serving it. But it points at where the definitions should eventually sit: written once, not once in the app and again in prose and a third time in a query. The single source of truth is the goal, and this is where I proved to myself what reaching it actually takes.
What it demonstrates
The pattern transfers directly to work. Replace training load with pipeline, win rate, or ARR, and replace my coach with a sales assistant querying the CRM, and it is the same architecture. Define the metric once, let everything read that definition, and give the AI a governed way in rather than direct access to recompute as it pleases.
Single source of truth has always been the RevOps ideal. What changed is the scope. The old goal was dashboards agreeing with each other. The new one adds the AI answering a question in Slack, which has to agree with the dashboard too. A semantic layer is how you make one definition serve both. I tested that on my own data, the cheapest possible place to try it.