> For the complete documentation index, see [llms.txt](https://v2.dataos.info/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://v2.dataos.info/consume/v1/recipes/answer-a-kpi-question.md).

# Answering KPI Questions in Natural Language

You have a vetted product and a key performance indicator (KPI) question: "what was quarterly revenue by customer segment?" This recipe turns that into a governed answer, with the metric and source model cited, so you can trust and reproduce the number. The journey is inspect schema → run the governed query → slice further → confirm it was governed.

**What this enables:**

* [ ] Inspect a product's schema before asking for numbers, so you query measures and dimensions that actually exist
* [ ] Get a governed answer computed from the product's own metric definition, not an ad-hoc recalculation
* [ ] Slice and refine the answer further without rebuilding the query
* [ ] Cite the exact metric and source model behind any number, so it's reproducible

{% hint style="info" %}
**Prerequisites:** a [connected client](/consume/v1/consume-with-ai/connect-a-client.md) and a product you already trust. If you have not vetted one, start with [Discovering the Right Data Product in Natural Language](/consume/v1/recipes/find-a-data-product.md).
{% endhint %}

## Steps

Example responses below are illustrative: exact wording, fields, and figures depend on your catalog, your data, and your permissions.

### 1. Inspect the schema

Before asking for numbers, find out what the product can answer, so you ask for measures that exist and slice by dimensions it supports:

```
What metrics and measures does orders360 expose?
```

<details>

<summary>Sample response</summary>

Orders360 (stg tenant) exposes 4 semantic models with 23 measures, 62 dimensions, 4 time dimensions, 7 segments, and 2 top-level business metrics.

**Metrics:** order\_volume (daily order volume by product category/customer segment), revenue\_trend (daily revenue trend by customer/product category).

**Key measures by model:**

* **orders**: total\_orders, total\_revenue, average\_order\_value, total\_quantity\_sold, total\_discount\_amount, total\_shipping\_cost, total\_tax\_collected
* **customer**: total\_customers, active\_customers, platinum\_customers, average\_loyalty\_score
* **customer\_orders\_enriched**: avg\_orders\_per\_customer, total\_orders\_metric, m\_count, m\_count\_distinct, max/min\_credit\_score
* **products**: total\_products, active\_products

**Segments:** high\_value\_customers, at\_risk\_customers, recent\_signups, discounted\_orders, high\_value\_orders, recent\_orders, high\_rated\_products.

Dimensions span customer attributes (segment, loyalty tier, signup date), order details (date, discount, tax, shipping), and product attributes (category, brand, price, rating), plus behavioral/fraud fields (device, risk\_score, is\_fraud, feedback\_rating).

</details>

```
What dimensions can I use with the revenue measure? Can I slice by customer segment?
```

<details>

<summary>Sample response</summary>

Yes: `orders.total_revenue` joins many-to-one to both `customer` and `products`, so you can slice by dimensions in any of the three.

**From orders itself:** order\_date, quantity, unit\_price, discount, tax, shipping\_cost, total\_amount, customer\_id, product\_id (plus order\_date\_timestamp for time granularity, and segments like discounted\_orders/high\_value\_orders/recent\_orders).

**From customer (joined):** customer\_segment, account\_status, loyalty\_score, signup\_date, full\_name, email; plus segments like high\_value\_customers, at\_risk\_customers, recent\_signups.

**From products (joined):** category, subcategory, brand, color, size, price, rating, stock\_quantity, discontinued; plus segment high\_rated\_products.

So yes: `orders.total_revenue` sliced by `customer.customer_segment` is a valid query (e.g., revenue by Platinum/Gold/Silver/Bronze).

Note the packaged `revenue_trend` metric only exposes `ts` (day) as its default dimension; for a customer\_segment slice you'd query the raw `orders.total_revenue` measure directly rather than the `revenue_trend` metric.

</details>

The assistant returns the queryable surface: the measures, the dimensions you can slice by, and which models join to which. Think of it as the menu before you order. This is the schema part of [Understand in natural language](/consume/v1/consume-with-ai/understand-in-natural-language.md).

### 2. Run the governed query

Ask the business question in plain language:

```
What was quarterly revenue by customer segment for 2025?
```

**Example response:**

<table><thead><tr><th width="206.243896484375">Quarter</th><th>Customer segment</th><th>Revenue</th></tr></thead><tbody><tr><td>Q1 2025</td><td>Platinum</td><td>$842,300</td></tr><tr><td>Q1 2025</td><td>Gold</td><td>$511,200</td></tr><tr><td>Q2 2025</td><td>Platinum</td><td>$901,150</td></tr><tr><td>Q2 2025</td><td>Gold</td><td>$529,800</td></tr></tbody></table>

The assistant translates it into a governed query against the semantic layer, applies the joins and access policies, and returns the result. Because it goes through the semantic layer, the number uses the product's own definition of revenue, not an ad-hoc recalculation. If the underlying result set is larger than the platform's row limit, the response states that output was capped, so you know to slice further rather than treat it as the full set.

### 3. Slice further

Follow up to refine, without rebuilding anything:

```
Now break that down by product category.
Limit it to the Platinum segment.
```

**Example response:**

| Quarter | Product category | Revenue (Platinum) |
| ------- | ---------------- | ------------------ |
| Q1 2025 | Electronics      | $410,900           |
| Q1 2025 | Home & Garden    | $267,400           |
| Q1 2025 | Apparel          | $164,000           |

> Same measure and joins as before, now filtered to `orders.CUSTOMER_SEGMENT = 'Platinum'` and grouped by `orders.PRODUCT_CATEGORY`.

Each follow-up reuses the same governed measures and joins, so the numbers stay consistent across slices.

### 4. Confirm it was governed

Trust comes from knowing where the answer came from. Ask the assistant to cite it:

```
Which metric and source model produced that revenue figure?
```

**Example response:**

> `orders.TOTAL_REVENUE = SUM(orders.TOTAL_AMOUNT)`, from the `orders` semantic model, joined to `customers` on `customer_id` for the segment dimension. Filters applied: `order_date` in 2025, `customer_segment = 'Platinum'`.

A governed answer names the measure and the source model, so you can reproduce it.

## Troubleshooting

<table><thead><tr><th width="272.60467529296875">Issue</th><th>Resolution</th></tr></thead><tbody><tr><td>The assistant returns a limitation instead of a number</td><td>The question cannot be answered from the product's semantic surface rather than a wrong number being invented. Re-check step 1's measures and dimensions and rephrase around what is actually exposed.</td></tr><tr><td>A measure or dimension you expect is missing</td><td>It is not exposed on this product's semantic model. Ask <code>What metrics and measures does &#x3C;product> expose?</code> again to confirm the current list, or check a different product with <a href="/pages/aqnK6oxh1f1Hu8mgp99l">Discovering the Right Data Product in Natural Language</a>.</td></tr><tr><td>Slicing by a dimension gives an error or no result</td><td>That dimension may not join to the measure you asked for. Ask <code>Which dimensions can I use with &#x3C;measure>?</code> before slicing.</td></tr><tr><td>The number doesn't match a figure from another source</td><td>Ask step 4's citation question. Differences usually trace to a different metric definition, filter, or time window, not a broken query.</td></tr><tr><td>The response says output was capped</td><td>The result set exceeded the platform's row limit. Narrow the question (a shorter date range, a specific segment) or slice further as in step 3, rather than treating the capped response as the complete answer.</td></tr><tr><td>The assistant returns an authentication or authorization error</td><td>Ask your administrator for the <code>mcp-tool-read</code> grant under <code>use-mcp-service</code>, or a tenant role such as <code>data_consumer</code> or <code>data_developer</code>. See <a href="/pages/Iv7IrhZxYMLqhTFHWRF2#governance-and-trust">Governance and trust</a>.</td></tr></tbody></table>

## References

* [Understand in natural language](/consume/v1/consume-with-ai/understand-in-natural-language.md): the full range of schema, quality, lineage, and run questions you can ask before querying
* [Save as Perspective](/consume/v1/evaluate/query-in-studio/save-as-perspective.md): save this query for reuse
* [APIs](/consume/v1/activate/apis.md): wire the governed answer into an application


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://v2.dataos.info/consume/v1/recipes/answer-a-kpi-question.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
