On November 9, the Databricks Genie app for Microsoft Teams went generally available. Two days later, the Genie plugin for Microsoft 365 Copilot landed in public preview. So nobody needs a notebook, a SQL editor or a Power BI report anymore. They type "how many active customers did we have last month" into the same Teams window where they argue about the sprint, and something answers.

Here is the part that should make you uncomfortable.

Fabric data agents already answer that question from a Power BI semantic model. Genie now answers it from Unity Catalog. Both can sit on top of the same lakehouse, and since OneLake external locations hit public preview on November 2, they can sit on top of literally the same files.

Two agents. One copy of the data. Two definitions of "active customer". Both answers delivered with complete confidence, in a channel, in front of whoever happens to be reading.

This is not a model problem. Both engines write decent SQL and decent DAX. The problem is that your business definitions were never written down anywhere a machine could read them, and now there are two machines reading two different places.

What actually shipped in the last two weeks

Worth being precise here, because the dates matter:

  • Genie Ontology, GA on November 9. The context layer that combines knowledge you model in Unity Catalog semantics with knowledge Genie extracts from your assets and usage.
  • Genie Search, GA on November 9. Indexes Google Drive, Jira, Confluence and Workday, and indexes each document's permissions alongside its content.
  • Genie app in Microsoft Teams, GA on November 9. Direct message or @Databricks Genie in a channel.
  • Pages, GA on November 11. Governed definitions of business concepts, organized by domain, with certification, deprecation, a REST API, and a new MANAGE PAGES permission.
  • Genie plugin for Microsoft 365 Copilot, public preview on November 11. Copilot Chat talks to Genie One without an at-mention.
  • External knowledge sources, Beta on November 5. You can pull metadata from Power BI semantic models into Azure Databricks, and Genie can use your Power BI measure definitions when it answers.

Read that last one again. Databricks shipped a feature whose entire purpose is to read your Power BI measures. That is a fairly direct admission that for a lot of shops, the real semantic layer has been living in Microsoft's stack for years.

The model is not the bottleneck

Databricks published a benchmark for the Genie Ontology launch, built with Turing: Genie passed 91% of tasks, against 45% and 58% for two frontier agents, in roughly 100 seconds instead of 300 to 435, using fewer tokens. It is a vendor benchmark on a simulated workspace for a fictional energy supplier, so weigh it accordingly. But the caveat Databricks puts next to it is the honest and interesting part: the results "reflect an established deployment where teams have accumulated that knowledge."

That sentence is the whole article. The score is not a property of the model. It is a property of how much of your business somebody bothered to write down.

Genie Ontology splits that into two halves. Learned knowledge is mined from dashboards, queries and notebooks, turned into reusable snippets, ranked by authority, certification, popularity and recency, and it inherits the permissions of the asset it came from, so nobody gets context they could not already query. Modeled knowledge is what you author: metric views, domains, Pages.

Learned knowledge buys you coverage. Modeled knowledge buys you authority. Only the second one is yours, and only the second one can be tested.

The part you own, written down

A metric view is the smallest useful piece of that. One expression, versioned, in the catalog:

CREATE OR REPLACE VIEW main.sales.customer_metrics WITH METRICS LANGUAGE YAML AS $$ version: 1.1 source: main.sales.fact_orders filter: order_status <> 'CANCELLED' joins: - name: customers source: main.sales.dim_customers on: source.customer_id = customers.customer_id at_most_one_match: true fields: - name: order_month expr: DATE_TRUNC('MONTH', order_date) - name: region expr: customers.region measures: - name: active_customers expr: COUNT(DISTINCT customer_id) - name: net_revenue expr: SUM(amount - COALESCE(refund_amount, 0)) $$; 

And you query measures through MEASURE(), not as plain columns:

SELECT order_month, MEASURE(active_customers) AS active_customers, MEASURE(net_revenue) AS net_revenue FROM main.sales.customer_metrics WHERE order_month >= '2026-10-01' GROUP BY order_month ORDER BY order_month; 

Two lines in there are the actual business, not the engineering: the cancelled-order filter and the refund subtraction. Hand the same metric to two engineers in two notebooks and they will disagree about the refund line within a quarter. Here it exists once, it is diffable in git, and Genie treats it as the definition instead of guessing from a dashboard somebody built in 2024 and never deleted.

The trade-off is real, though. Every measure you model is something a human has to maintain and re-approve when the business changes. Databricks' own guidance is to model the comparatively small set of definitions that must be exact, and that is correct. Model everything and you end up with a semantic layer nobody updates, which is strictly worse than no semantic layer, because now the wrong answer carries a certification badge.

The same definition, in Microsoft's grammar

Now look at the Fabric side of the same question. A data agent over a semantic model generates DAX from the model's metadata and its Prep for AI configuration, and Microsoft's guidance is specific: add descriptions to tables, columns and measures, use business-friendly names, create explicit DAX measures, define a focused AI data schema, and put your terminology into AI instructions.

The example in the docs states the problem better than I could. Without an instruction, the agent "doesn't understand what 'top performer' means in your organization."

And then there is this line, which belongs on a wall somewhere: AI instructions "are unstructured guidance that the LLM interprets, but there's no guarantee it follows them exactly."

So count where "active customer" lives now:

  1. A YAML expr in a Unity Catalog metric view. Deterministic.
  2. A DAX measure in a semantic model. Deterministic.
  3. A sentence in Prep for AI instructions. Interpreted.
  4. A Unity Catalog Page. Interpreted, but at least owned and certified.
  5. Whatever Genie learned from an old dashboard and ranked as authoritative.

Five surfaces, zero tests, and no alert when they drift apart.

Test it like the production code it now is

This is unglamorous and it works. Ask both stacks for the same number and fail the build when they disagree:

import os import requests DBX_HOST = os.environ["DATABRICKS_HOST"] DBX_TOKEN = os.environ["DATABRICKS_TOKEN"] WAREHOUSE = os.environ["DATABRICKS_WAREHOUSE_ID"] PBI_TOKEN = os.environ["POWERBI_TOKEN"] DATASET = os.environ["POWERBI_DATASET_ID"] MONTH = "2026-10-01" def unity_catalog_value(): r = requests.post( f"{DBX_HOST}/api/2.0/sql/statements", headers={"Authorization": f"Bearer {DBX_TOKEN}"}, json={ "warehouse_id": WAREHOUSE, "wait_timeout": "30s", "statement": ( "SELECT MEASURE(active_customers) AS v " "FROM main.sales.customer_metrics " "WHERE order_month = :month" ), "parameters": [{"name": "month", "value": MONTH, "type": "DATE"}], }, timeout=60, ) r.raise_for_status() return float(r.json()["result"]["data_array"][0][0]) def power_bi_value(): dax = ( 'EVALUATE ROW("v", CALCULATE([Active Customers], ' "'Date'[MonthStart] = DATE(2026, 10, 1)))" ) r = requests.post( f"https://api.powerbi.com/v1.0/myorg/datasets/{DATASET}/executeQueries", headers={"Authorization": f"Bearer {PBI_TOKEN}"}, json={"queries": [{"query": dax}]}, timeout=60, ) r.raise_for_status() row = r.json()["results"][0]["tables"][0]["rows"][0] return float(list(row.values())[0]) uc = unity_catalog_value() pbi = power_bi_value() drift = abs(uc - pbi) / max(uc, 1.0) print(f"unity_catalog={uc:.0f} power_bi={pbi:.0f} drift={drift:.4%}") if drift > 0.001: raise SystemExit("definition drift: your two agents will not agree in Teams") 

It is a smoke test, not architecture. What it buys you is a loud failure on the day somebody edits a DAX measure or tweaks that YAML filter, instead of a quiet one three weeks later when a director pastes two screenshots into a thread and asks which number is real.

In production I would change three things. Loop it over the last twelve months rather than one, because drift usually hides in a single reprocessed period. Run it nightly instead of per commit, since both calls burn real compute. And route the failure to the metric's owner, not to the platform channel where alerts go to die. The 0.1% tolerance is there for late-arriving rows. If you need exact equality, set it to zero and be ready to explain refunds that post after midnight.

Somebody has to own the sentence

The MANAGE PAGES permission that shipped with Pages on November 11 is a smaller feature than Genie Ontology, and I think it matters more. It is scoped to a domain, it controls who can publish and manage definitions, and Pages carry an owner, a certification state and the sources a definition was based on.

Which means the question "who is allowed to decide what active customer means" finally has an answer inside the platform, instead of inside a Confluence page from 2023 that three people have edit rights to and nobody has read.

Do not mistake the permission for the outcome, though. Certification is a social process wearing a feature's clothes. The grant tells you who may publish. It does not tell you whether the person who published actually asked finance.

What I would do now

Five things, in order:

  1. Pick one canonical home per definition. If your business already lives in Power BI, let the semantic model own it and let Genie pull it in as an external knowledge source. If the lakehouse is the center of gravity, let metric views own it and treat DAX as a projection. One direction of sync. Never two.
  2. Model only what must be exact. Certified metrics, the ten entities your company argues about in meetings, the acronyms that mean two things. Let the learned layer cover the long tail.
  3. Put a drift test in CI for every certified metric. If it is not tested, it is not certified, it is just decorated.
  4. Do not point two agents at the same question surface. If Genie is in that Teams channel, the Fabric agent is not. Choose, and tell people which one is the record.
  5. Give every definition a human owner. A person, not a team alias, with a review date.

The shift in November 2026 is not that agents got better at writing queries. It is that your semantic layer stopped being a BI convenience and became a production dependency with a public failure mode, in Teams, where everybody can watch it break.

So: if someone asked your company today, in Teams, how many active customers you had last month, how many places is that number defined in right now, and which one would you actually defend in a meeting? And would you rather maintain one canonical metric layer that both ecosystems read from, or keep two and test the gap between them? I go back and forth on that one more than I would like to admit.

Primary sources: Azure Databricks release notes, November 2026, Announcing GA of Genie Ontology, Unity Catalog Pages, Metric view YAML reference, Semantic model best practices for data agents.