ObeliskDB docs Home Whitepaper Console

Metrics & semantic layer

The semantic layer is the meaning guarantee. A metric is one governed definition of a business quantity, defined once as code and invoked by name — so an agent (or a person) cannot misdefine revenue. The definition is executed, not recalled.

Why it matters for agents

Ask an agent for "average order value" over data where some orders have multiple line items, and three defensible SQL formulations return different numbers — most of them wrong. A governed metric collapses them to the one blessed answer, identical on every call. Failure looks like an error, not a plausible wrong number. See The guarantees.

Defining a metric

Metrics live in metrics/*.toml beside your models:

# metrics/sales.toml
[avg_order_value]
description = "Average order value"
table = "DEMO.SALES.ORDERS"
measure = "ROUND(SUM(AMOUNT) / COUNT(DISTINCT ORDER_ID), 2)"
dimensions = ["REGION", "ORDER_DATE"]

Querying

A metric is a table function — it composes in real SQL, sliced by any of its dimensions:

SELECT * FROM TABLE(METRIC('avg_order_value'));
SELECT * FROM TABLE(METRIC('avg_order_value', 'REGION'));

Obi and MCP agents reach the same definitions through list_metrics and query_metric, so an agent answers analytics questions through the governed vocabulary before ever writing SQL.

Compelled use

To make the metric a hard boundary rather than a preference, put a session in governed-only mode — raw table access is refused, and metrics and insights are the only way to read:

ALTER SESSION SET GOVERNED_ONLY = TRUE;

See compelled governance.

Metrics, insights, and the determinism dial

A metric is the defined setting of the determinism dial: the same definition every time, any dimension. An insight is the pinned setting: a specific answer frozen to a data version. Together they let each question choose the reproducibility it deserves.

Lakehouse interop

External tables read Parquet and Iceberg in place, and EXPORT TABLE writes a table out as Parquet plus a manifest — so ObeliskDB participates in a lakehouse without owning every byte.

CREATE EXTERNAL TABLE RAW.EVENTS LOCATION 's3://bucket/events/' FORMAT ICEBERG;
EXPORT TABLE MARTS.SUMMARY TO 'exports/summary/';