Malcolm Angus

โ† All essaysยทJuly 10, 2026ยท10 min read

The context layer is the product

Everyone is building a chat-with-your-data agent. Most are demos that break the week after the meeting. The model was never the hard part. The context layer is, and it is three kinds of intelligence: schema, semantic, and business context, all of which have to become version-controlled code.


Field guide diagram of the context layer as three stacked kinds of intelligence: schema intelligence (what shape the data is in), semantic intelligence (what the numbers mean), and business context (the judgment that lives nowhere in the database), all encoded as version-controlled code in Git. Caption: the model is rented, the context is owned.

Every data team I talk to is building the same thing right now: an agent you can ask a question in plain English and get an answer from the warehouse. "Chat with your data." The demo always works. Someone types "what drove churn last quarter," the agent writes SQL, a number comes back, the room nods.

Then it ships, and it breaks the week after. The agent answers a slightly different question wrong and nobody notices. An exec makes a call on a number that was quietly incorrect. A non-technical stakeholder stops trusting it after the second bad answer and goes back to asking an analyst. The demo was real. The product wasn't.

The reason is almost always the same, and it's worth saying plainly: the agent is the easy part. The model that writes the SQL is commoditized and getting better on its own. What determines whether the thing works is everything around the model. Call it the context layer. It is the product. And it is not one thing, which is exactly where most teams go wrong.

Three kinds of intelligence

The context layer is three distinct kinds of intelligence, and an agent needs all three to answer a real question.

Schema intelligence: what shape the data is in. The tables, the columns, the JSON structures, how they join, which field is a real timestamp and which is a string that only looks like one. Without it, the agent invents column names and hallucinates paths into nested JSON. This is the most basic layer, and the one everyone remembers to build.

Semantic intelligence: what the numbers mean. Metrics, dimensions, the governed definition that makes "revenue last quarter" resolve to the same number every time, no matter who asks. This is the layer a semantic tool like dbt gives you, and the one most teams gesture at but never finish.

Business context: the judgment that lives nowhere in the database. What "active user" actually means at your company. Which table is the source of truth and which is a deprecated graveyard nobody deleted. What a good answer looks like, and which questions are traps. This knowledge lives in PRDs, Slack threads, and one senior analyst's head, and it is the layer almost nobody encodes.

That third layer is why these projects fail. On clean, well-modeled schemas the agents score in the eighties. Point them at a real warehouse and frontier models collapse into the twenties and thirties, not because the SQL is wrong but because the question was ambiguous and the business context was missing. The SQL comes back syntactically perfect and semantically wrong, and confident about it.

So the job is to encode all three, and the one decision that determines whether the agent survives contact with real users is where that encoding lives. Put it in version control, as code. Every schema you document, every metric you define, every piece of business judgment you write down becomes plain text in a Git repo: reviewed in a pull request, tested in CI, with a full history of who changed what and why.

That is also what lets one agent serve two very different people. The engineer wants to drop to raw SQL and check the query. The operator wants a trustworthy answer in the tool they already live in. Both are served by the same encoded intelligence, because it is code, not tribal knowledge or a vendor's UI.

Read by everyone, written by the right few

Encoding the three intelligences as code splits consumption from contribution, and that split is the whole reason it works.

Consumption is universal. Once a schema is documented, a metric is defined, or a piece of business judgment is written down, it is readable by anyone and usable by any agent, on any surface. The engineer in Claude Code, the operator in Slack, the analyst in a notebook, every agent in between: all read the same encoded intelligence. Nobody is gatekept from an answer.

Contribution is scoped by altitude. Each layer is authored by the people who actually hold that knowledge. Schema intelligence comes from the technical users who know the tables and the JSON shapes. Business context comes from the operators and domain owners who know what "active user" means and which table to trust. Semantic intelligence sits in the middle, contributed by both, because a metric's SQL is a technical artifact but its definition is a business decision, and it takes both to get right.

And the agent contributes too, which is what makes broad authorship real instead of aspirational. A business user does not open a pull request. They tell the agent, in plain English, "active users should exclude internal accounts," and the agent drafts the change as a version-controlled PR for someone to approve. The person supplies the judgment; the agent supplies the plumbing.

One rule holds all of it together: every contribution, whoever or whatever makes it, flows through Git. Reviewed, tested against the golden questions, merged, redeployed. That is the governance backbone, and it is why you can hand contribution rights to non-engineers and to the agent itself without the context layer rotting. Nothing changes the shared intelligence except through a reviewed, versioned, reversible commit.

The contribution model: schema intelligence is written by technical users, business context by business users, and semantics by both, with the agent able to draft any of them as a pull request, all passing through Git for review, test, and redeploy, then read by everyone, every agent, and every surface. Caption: nothing changes the shared intelligence except a reviewed, versioned commit.

The stack, in five layers

You do not need a single magic product. You need a handful of layers to encode and serve those three intelligences, and the discipline that every one of them keeps its definitions in Git.

A data answer agent stack in layers: a Claude harness on top, a dbt semantic layer, a guarded BigQuery access layer, and the gold-mart warehouse at the base, with a single Git repo threading every layer as version-controlled context. Caption: five layers, every one keeps its definitions in Git.

The harness: meet people where they work. Use Claude as the harness, because its context is just files. Claude Code for engineers reads skills, a CLAUDE.md, and MCP config straight off the repo. Cowork puts the same capability in front of non-technical users. A Slack bot built on the Agent SDK reads the same skills from the same checkout, so your daily "ask the data" loop lives where your team already talks. One honest caveat: custom skills do not automatically sync across claude.ai, the API, and Cowork, so treat Git as the source of truth and let the filesystem-native surfaces (Code, the SDK) read it directly.

The semantic layer: definitions as YAML. If you are a dbt shop, this is the lowest-friction move. The dbt Semantic Layer defines metrics, dimensions, and entities as version-controlled YAML in the same repo as your transformations, and the dbt MCP server exposes them to the agent. This is the accuracy move, not a nicety: the model maps language to a governed metric object, not to free-form SQL against raw tables. In paired testing, semantic-layer grounding beats raw text-to-SQL by roughly 17 to 23 points, and within what you have modeled it does not return silently incorrect data. The catch worth budgeting for: the consumption surface (the hosted APIs and remote MCP) requires the paid dbt platform, now part of the merged Fivetran and dbt Labs, and its natural-language querying is metered by credits. The definitions stay open. The way an agent reaches them at scale does not.

The access layer: a guarded door to the warehouse. For anything beyond defined metrics, the agent needs raw SQL against your gold mart, and this is where an unsupervised agent can do real financial damage. Google's MCP Toolbox for Databases is the standard governed gateway: a single tools.yaml between the agent and BigQuery. Scope it hard. A read-only service account with IAM on the gold dataset only, table allowlists, a mandatory dry run before every query, and a maximumBytesBilled cap on all of them. BigQuery charges by bytes scanned, not returned, so one careless SELECT * on a wide table is a real bill. The cap is not a nicety; it is the thing standing between you and a four-figure query.

The routing layer: link, don't rebuild. Half the questions people ask already have a dashboard. Register your existing Retool and Replit dashboards as dbt exposures, version-controlled YAML naming each dashboard, its URL, and its upstream models, then teach the agent to check for a covering dashboard and return the link before it builds a new chart. Be honest that exposures were built for lineage, not routing, so this is a convention that works at ten to fifty well-maintained dashboards and frays past that. But at small scale it stops the agent from rebuilding what already exists.

The qualitative leg: your gold layer has text too. Most of these stacks quietly assume all your data is numbers. Real gold layers hold JSON, and raw text: support tickets, call transcripts, reviews. Two moves. Structure it upstream by putting BigQuery's AI functions inside dbt models, where AI.GENERATE_TABLE turns messy text into typed, queryable columns and your extraction prompts become reviewed, version-controlled SQL. And search it at query time with VECTOR_SEARCH over precomputed embeddings for the questions you did not anticipate. The reason this matters: the most valuable questions are cross-modal, "churn rose in these regions, what are those customers' tickets saying," and stitching a metric query to a text search to a synthesis is exactly what an agent does and a metrics tool cannot.

Where it breaks

Where the stack breaks: a solid zone for an internal team under 100 users with dataset-level permissions, next to four flips (row-level security, scale and latency, customer-facing, no dbt Cloud budget) that all point to Cube. Caption: build Git-first so you can layer it on later.

This stack is solid for an internal team asking real questions in Claude, with dataset-level permissions and tolerance for probabilistic answers. It stops fitting the moment any of these flip, and it is worth knowing the thresholds before you build:

  1. Different users must see different slices. BigQuery IAM gets you dataset and table permissions. It cannot enforce "the region manager sees only their region" at query time. A prompt asking nicely is not a security boundary.
  2. Scale and latency. The semantic layer has no cache. Every question is a cold warehouse hit, and one agent question fans into five or ten queries. Fine at twenty users. Ugly at a few hundred, or under any latency SLA.
  3. It goes customer-facing. Internal tolerance for a wrong answer evaporates the moment the answer is in front of a customer.
  4. You have no dbt Cloud budget. dbt Core alone cannot serve the semantic layer over the API an agent needs.

Notice that most of those exits point the same direction: Cube, whose open-source core gives you compile-time row-level security (the query that would return forbidden rows never compiles) and a pre-aggregation cache that serves answers without hitting BigQuery cold, and which reads your dbt models directly. You do not need it on day one. You need to not foreclose it.

Two failure modes are human, not technical, and no tool fixes them. The contribution model only works if you actually wire up the agent-drafts-the-PR pattern; skip it and every context change routes through two engineers who become the bottleneck. And the accuracy is probabilistic. The danger is not wrong SQL, which is easy to catch. It is a confidently wrong answer to an ambiguous question, which is the kind execs ask, and it is exactly the failure those benchmark numbers describe. So you need an eval harness: golden question-and-answer pairs run in CI against the semantic layer, gating every change. Nothing in the stack gives you that for free.

The model is rented. The context is owned.

Here is the through line, and the reason to build it Git-first from the first commit. The five layers do not have to arrive at once, and the exits all point the same way, so the pragmatic move is to encode everything as code now and layer the serving, security, and surface pieces on later without rework.

The context layer as a compounding loop: every metric defined, every JSON schema documented, every wrong answer turned into a golden test, and every dashboard registered accrues in the Git repo, and each one makes the next answer better. Caption: the model is replaced twice a year, the context is yours to keep.

Because the context layer is the part that compounds. Every metric you define, every JSON schema you document, every wrong answer you turn into a golden test, every dashboard you register makes the next answer better, and it accrues in your repo where you own it. The model underneath will be replaced twice a year by someone else's lab. You rent it. The context layer is the thing a competitor with a bigger model still cannot copy, because it is the encoded judgment of your business, in your history, under your review.

Build the chatbot and you have a demo. Build the context layer and you have a data product. Only one of them is still working next quarter.

Malcolm Angus

Malcolm Angus

I'm a data product manager. I write about data products, moats, flywheels, and business strategy, the loops that make companies harder to catch.

Follow on LinkedIn

The charts in this essay are free to reuse with credit.