The useful test of an ontology is whether it helps an agent answer a business question using the right entities, relationships, and calculations. A diagram full of connected objects is only the beginning.
Microsoft’s updated Fabric ontology experience gives us more to work with: semantic-model measures, richer metadata, natural-language rules, namespaces, inheritance, and an agent that can help create and query the model. This walkthrough builds a small customer-operations ontology and checks it against a result we can calculate independently.
The question is deliberately specific: which customers have an open, high-priority service case at least seven days old, and how much open order value belongs to those customers? The example includes two qualifying cases for one customer, so a careless join can double the commercial amount. That makes the exercise useful for testing meaning as well as connectivity.
What we are building
The main route uses Power BI Desktop to prepare a small semantic model, then the Fabric portal to generate and enrich an ontology. Queries run through the built-in ontology agent. The separate Fabric data-agent integration currently has a documented issue with new-experience ontologies, so it is an optional extension rather than a dependency of this exercise. All ontology capabilities discussed here are preview features.
The example has three entities and two one-to-many relationships.
| Entity | Meaning | Identifier and connection |
|---|---|---|
| Customer | A commercial customer in this demonstration | CustomerID uniquely identifies each customer |
| Order | One customer order with a value and status | OrderID is unique and CustomerID connects it to Customer |
| ServiceCase | One recorded service issue | CaseID is unique and CustomerID connects it to Customer |
Keep the responsibilities clear. The semantic model owns the calculations and filtering behavior. The ontology supplies business definitions and source mappings. The agent interprets a question and uses an appropriate source query. Optional graph materialization is unnecessary for this example; current graph projection does not support entities bound to semantic models.
1 Prepare the workspace and sample data
Use a Fabric-enabled workspace and capacity that support the ontology and Copilot experiences in your region. You need permission to publish the semantic model and create an ontology, plus Read and Build access to the model. Ask the Fabric administrator to enable Users can create Fabric items and Users can create ontology preview items, along with the applicable Copilot settings. Contributor or higher is required for ontology-agent changes.
The sample is illustrative, with a fixed snapshot on October 17 2026. AgeDays is a stored snapshot value, so rerunning the exercise next month produces the same expected answer. In a production model, the data owner must define how that age is refreshed and whether it means calendar days, business days, or elapsed hours.
Save the following as three UTF-8 CSV files. The accompanying example folder contains the same files.
Customer.csv
CustomerID,CustomerNameC001,Harbor SupplyC002,Summit GoodsC003,Cedar Office
Order.csv
OrderID,CustomerID,AmountUSD,StatusO101,C001,120000,OpenO102,C001,30000,OpenO103,C002,80000,OpenO104,C003,50000,Closed
ServiceCase.csv
CaseID,CustomerID,Priority,Status,AgeDays,SnapshotDateS101,C001,High,Open,9,2026-10-17S102,C001,High,Open,7,2026-10-17S103,C002,High,Open,6,2026-10-17S104,C003,High,Closed,12,2026-10-17
In Power BI Desktop, import the files through Get data and Text or CSV. Keep identifiers as text, set AmountUSD to a suitable numeric type, AgeDays to whole number, and SnapshotDate to Date. Name the tables Customer, Order, and ServiceCase.
Create single-direction relationships from Customer[CustomerID] to Order[CustomerID] and ServiceCase[CustomerID], with Customer on the one side. Do not join Order directly to ServiceCase. Multiple orders and cases for a customer would otherwise create a multiplication problem if flattened carelessly.
2 Establish the calculations before adding AI
Create these two measures separately through New measure. Put the first on Order and the second on ServiceCase.
Open Order Value USD =COALESCE( CALCULATE( SUM('Order'[AmountUSD]), 'Order'[Status] = "Open" ), 0)
Aged High Priority Cases =COALESCE( CALCULATE( COUNTROWS(ServiceCase), ServiceCase[Status] = "Open", ServiceCase[Priority] = "High", ServiceCase[AgeDays] >= 7 ), 0)
Add descriptions explaining the snapshot, the inclusive seven-day threshold, and the exclusion of closed records. Create a table visual with customer name and the two measures. It should show:
| Customer | Open Order Value USD | Aged High Priority Cases |
|---|---|---|
| Harbor Supply | 150000 | 2 |
| Summit Goods | 80000 | 0 |
| Cedar Office | 0 | 0 |
These expected values come from the supplied rows and have been checked independently of Fabric. The walkthrough describes a reproducible build; it does not report a completed tenant deployment.
Publish the model to the target workspace as CustomerOperations. Retain this small report as the baseline. If the agent later returns a different number, you now have a defined calculation and a known result to investigate.
3 Generate and inspect the ontology
In Fabric, select Generate Ontology from the semantic-model ribbon or its more-actions menu. Name the item CustomerOperationsOntology. Generation carries tables, columns, relationships, and measures into the ontology structure. Inspect Properties, Relationships, and Metrics on each entity, and review keys and relationship bindings explicitly.
For this sample, the completed model should have three entities, with Customer linked separately to Order and ServiceCase. Confirm that OrderID and CaseID identify records, rather than selecting CustomerID as the key for either child entity. Repeated CustomerID values in those tables are intentional.
Open Ontology agent in Plan mode and use this review prompt:
Review CustomerOperationsOntology against the CustomerOperationssemantic model in this workspace. Make no changes.Expected entities are Customer, Order, and ServiceCase. CustomerIDis unique only in Customer. OrderID identifies Order and CaseIDidentifies ServiceCase. Each child references CustomerID.List each entity's source, identifier, properties, relationships,and metrics. Identify missing or ambiguous bindings. Confirm thatthe existing measures Open Order Value USD and Aged High PriorityCases remain available. Do not invent replacement calculations.Return a concise discrepancy list and a proposed correction foreach discrepancy. Stop for clarification if source evidence isinsufficient to establish a relationship.
Review the proposed changes in the canvas. If a correction is needed, switch to Act mode and request only the approved correction, then inspect the result. Plan mode permits exploration and queries; Act mode applies changes. The prompt supplies a contract the proposal can be checked against, instead of asking the agent to make the ontology generally better.
4 Add the language users actually use
Select Customer, open View Entity Type details, and use the Configure tab’s Metadata section. Add a description such as: A commercial customer identified by CustomerID in the demonstration source model. Add Client as an entity synonym. For ServiceCase, Ticket is a useful synonym. Save with Update. Properties and relationships support descriptions and additional metadata, but their metadata editor does not support synonyms.
Use the following proposed descriptions and metadata for this example:
| Object | Context to record |
|---|---|
| Customer.CustomerID | Stable demonstration customer identifier used to relate orders and cases |
| Order.AmountUSD | Order amount in USD before filtering by status; unit metadata is USD |
| ServiceCase.AgeDays | Calendar-day age recorded at the snapshot; threshold includes exactly seven days |
| ServiceCase.SnapshotDate | Date on which the recorded case age was calculated |
| Customer to ServiceCase relationship | Connects a customer to individual service cases; several cases can belong to one customer |
This is where a model starts to become useful beyond the team that created it. The descriptions explain units, grain, and time semantics that column names alone cannot establish. A tag such as owner or sensitivity is descriptive metadata; configure actual permissions separately.
5 Preserve the measures and record the business rule
Inspect the Metrics section on Order and ServiceCase. Each metric should point to the intended measure and source model. Ontology metrics retain a source connection rather than becoming a second independent implementation of DAX. Viewing the original expression through Resolve underlying DAX requires write permission on the source model, and source changes require an ontology refresh.
For this exercise, leave the formulas owned by CustomerOperations. If the organization changes what qualifies as an aged case, change the source measure under its normal review process and refresh the ontology before retesting.
Then open Explorer, Overview, and Rules. Create a rule called Customer service attention with this definition:
A customer requires service attention in this demonstration whenat least one linked ServiceCase has Status Open, Priority High,and AgeDays greater than or equal to 7 at the recorded snapshot.Closed cases do not qualify. Report open order value once percustomer using the governed Open Order Value USD measure.This condition identifies a review queue; it does not authorizecustomer communication or changes to source records.
Link it to Customer, ServiceCase, the relevant case properties, and their relationship. Add owner and effective-date metadata, then save. Rules are natural-language definitions available to consumers; ontology does not execute them.
There is an additional current limitation: Microsoft’s documentation says ask_ontology does not yet consider stored rules in its response, although rule listing is available through MCP. We therefore make the qualifying calculation explicit in the measure and test prompt. Saving the rule documents the agreed meaning; successful execution must still be demonstrated.
6 Ask a question with a result you can verify
Use Plan mode for the query. Supply this prompt:
Using CustomerOperationsOntology and its CustomerOperationssemantic model, return customers whose existing Aged High PriorityCases measure is greater than zero.For each qualifying customer, return CustomerID, CustomerName,Aged High Priority Cases, and Open Order Value USD. Use theexisting measures and identify their source model. Show the DAXquery and describe the applied filters.This sample uses the October 17 2026 snapshot. A qualifying caseis Open, High priority, and AgeDays >= 7. Count each order once;multiple service cases must not multiply order value. Do notchange the model, contact customers, or update any records.If a required binding or measure is unavailable, identify itinstead of substituting an inferred calculation.
The expected answer is Harbor Supply, customer C001, with two qualifying cases and USD 150000 in open order value. Summit Goods has an open high-priority case, but it is only six days old. Cedar Office’s case is closed.
One valid reference query against the source semantic model is:
EVALUATEFILTER( SUMMARIZECOLUMNS( Customer[CustomerID], Customer[CustomerName], "OpenOrderValueUSD", [Open Order Value USD], "AgedHighPriorityCases", [Aged High Priority Cases] ), [AgedHighPriorityCases] > 0)
The agent need not generate identical DAX. It must preserve the intended semantics. A USD 300000 answer for Harbor Supply is a useful failure signal: the two cases may have duplicated the order total. An answer that excludes the seven-day case has applied the wrong boundary.
Keep a small evaluation record containing the question, generated query, result, source model, test identity, ontology version, and observation time. Include an ambiguity test such as Which clients are at risk. The preferred behavior is to clarify what kind of risk is meant, or explicitly limit the answer to the defined service-attention condition.
7 Extend the model only where the domain needs it
Namespaces can separate concepts that have different owners or meanings. Select + Namespace, create CustomerOperations, and assign the relevant entities and relationships through their configuration pages. [9] For a larger implementation, sales and finance might retain distinct Customer concepts until the business agrees how they relate. Renaming them to match would not resolve the underlying disagreement.
Inheritance is useful when one type is genuinely a specialization of another. If your real domain includes CommercialCustomer and IndividualCustomer, each can derive from Customer through Add entity type, Additional configuration, and Choose entity to inherit from. Current documentation specifies single-parent inheritance. Derived types need their own bindings and entity-level metadata; ordinary relationships are not inherited.
The three sample entities do not need that hierarchy. Customer, Order, and ServiceCase are different kinds of things, so their connections should remain relationships. Also test inherited-instance queries explicitly: Microsoft currently lists problems returning child instances through parent queries in the ontology agent and MCP.
You can later ask the ontology agent to incorporate another related semantic model. Review any reconciliation of customer identities and preserve the source measures. A shared ontology does not imply that every consuming connector can execute a federated query. Establish a new expected result before introducing the second model.
8 Save a version and connect the intended consumer
Open Version history and create a named version such as Customer operations verified v1. Record the source model, snapshot, expected USD 150000 result, and any unresolved limitations. Versions are manually created definition checkpoints. Keep the baseline report and evaluation record with the release so another maintainer can reproduce the checks.
For an external MCP client, the ontology-specific endpoint uses the workspace and ontology item identifiers:
https://api.fabric.microsoft.com/v1/mcp/dataPlane/workspaces/<workspace-ID>/items/<ontology-item-ID>/ontologyEndpoint
Microsoft documents adding that URL as an HTTP MCP server in VS Code, then completing interactive sign-in. The ontology MCP path currently requires paid F2 or higher, or eligible P1 or higher capacity with Fabric enabled; service-principal access has a known issue. After connecting, inspect the available tools and repeat the same test before broadening the task.
The generally available endpoint at fabriciq.svc.cloud.microsoft serves Power BI reports and semantic models and currently excludes ontologies. It is a different integration. Select the endpoint according to the source the agent actually needs.
Foundry IQ provides another documented preview path: create a knowledge base, choose Fabric IQ, select the ontology through OneLake catalog, and attach the knowledge base to a Foundry agent. Use the same expected result there. Adding policy documents or Work IQ context is a separate design step, with its own access and evidence requirements.
Diagnose the failure at the right layer
| Symptom | First check |
|---|---|
| An entity or relationship is missing | Inspect generated definitions, identifiers, and bindings before changing the prompt |
| A governed number is wrong | Run the source measure and compare filters, grain, and duplicate rows |
| A rule appears to be ignored | Confirm the consumer retrieves and applies it; stored rules are not an execution engine |
| A model change is absent | Refresh ontology metrics and retest against the source |
| A Fabric data agent cannot add the ontology | Check the documented new-experience issue before redesigning the ontology |
| Different users receive different results | Examine source permissions and row-level restrictions with each user’s identity |
The last connection deserves particular care. Fabric data-agent ontology context routes questions to underlying sources; it does not promise cross-source joins. Its semantic-model grounding behavior also differs from the built-in ontology agent. Test the chosen consumer instead of assuming that a successful ontology-agent answer transfers unchanged.
The completed example gives you a source calculation, a maintained business definition, an ontology with explicit context, and a repeatable question with a known answer. Preserve those pieces as you extend the domain. The most useful ontology is one that another team can consume, test, and maintain without having to rediscover what the original author meant.