dbt gets agents to your metrics. OM makes those metrics better.
50,000 teams use dbt to transform raw data into clean, tested, documented models. They write metrics in YAML. They version control their business logic. They run CI on every PR.
dbt's MCP server and Semantic Layer are real solutions for giving agents access to those metrics. MetricFlow generates SQL from governed definitions. That SQL is deterministic for a given metric and filter combination. It's not the same as an agent guessing SQL against raw tables.
So why would you also want OnlyMetrix?
Because access and correctness are different problems. dbt solves access: agents can query your metrics. OnlyMetrix solves what happens next: how those metrics improve over time, how you catch errors before production, and what you can learn from the data beyond simple queries.
What OM adds on top of dbt
Compile-time safety
dbt catches errors when you run dbt test. OnlyMetrix catches errors when you compile a metric: fan-out detection, PII validation, type safety, unreachable filter detection. These checks happen at definition time, before any query runs. If a metric can't decompose cleanly into the IR, you know immediately, not when an agent hits it in production.
Autoresearch
dbt has no equivalent. OnlyMetrix runs systematic IR mutations overnight, generates up to 29 variations of a metric, scores each against ground truth, and surfaces Pareto-optimal improvements for human review. Your churn prediction metric gets better while you sleep. This works because metrics are mutable IR objects, not static YAML strings.
Analysis layer
13 reasoning primitives that work on any metric: root cause decomposition, segment performance, sensitivity analysis, anomaly detection, trend analysis, contribution analysis, and more. Your agent doesn't just query total_revenue, it asks "why did revenue drop?" and gets a structured answer with drivers ranked by explanatory power.
No dbt required
A team without dbt gets nothing from dbt's MCP server. OnlyMetrix works on any warehouse: Postgres, Snowflake, ClickHouse, BigQuery. Connect, define metrics (or let the pattern detection engine suggest them), and agents query immediately. If you have dbt, omx dbt sync imports your existing metrics. If you don't, you lose nothing.
Introducing omx dbt sync
Today we're shipping omx dbt sync as part of the OnlyMetrix Python SDK v0.3.1. It reads your target/manifest.json after dbt run, compiles your metric definitions through our IR compiler, and layers compile-time safety, autoresearch, and the full analysis engine on top of your existing dbt project.
If you're already using dbt's MCP server for agent access, great. OM adds the next layer: your metrics get compiled, validated, and improved. If you're not on dbt Cloud, OM gives you the full stack: governed agent access, compile-time checks, and analysis, all from the CLI.
Six commands from zero
pip install onlymetrix
export OMX_API_KEY=omx_sk_...
omx dbt connect # reads profiles.yml
omx dbt sync # reads manifest.json
# That's it. Your agents can query now.
om.metrics.query("total_revenue")
# -> {"total_revenue": 2107, "execution_time_ms": 291}
No dashboard to click through. No credentials to re-enter. omx dbt connect reads the same profiles.yml that dbt uses. omx dbt sync reads the same manifest.json that dbt produces. You stay in the terminal.
How it works
When you run omx dbt sync, three things happen:
1. Parse. The manifest is read and every metric definition is extracted: name, description, type, type_params, tags, filters, and any meta.onlymetrix configuration.
2. Translate. MetricFlow type_params are translated to SQL templates. A simple metric with agg: sum, expr: total_cents / 100.0 becomes SELECT SUM(total_cents / 100.0) AS total_revenue FROM orders WHERE status = 2. Ratio metrics are flagged as Opaque and their components are synced as separate Structured metrics.
3. Compile. Each SQL template is compiled through the OnlyMetrix IR compiler. Structured metrics get full decomposition: filters work, dimensions work, time ranges work. Opaque metrics preserve the SQL as-is.
The sync is idempotent. Each metric definition is hashed (SHA256 of name + description + SQL + tags + meta). Unchanged metrics are skipped. Only modified metrics are re-synced.
Preview before syncing
$ omx dbt sync --dry-run
Found 5 metrics in manifest
total_revenue -> structured (tier: core) [create]
customer_count -> structured (tier: standard) [unchanged]
avg_order_value -> structured (tier: core) [update]
churn_rate -> opaque (tier: standard) [create, ratio]
enterprise_customer_count -> structured (tier: standard) [create]
Would sync: 4 metrics (3 structured, 1 opaque), skip 1 unchanged
Would update: 2 tiers
The --dry-run flag shows exactly what would change. Every metric gets a compile hint (structured or opaque), a tier classification, and an action tag. No API calls are made.
Configure from dbt YAML
OnlyMetrix behavior is configured via meta.onlymetrix in your schema.yml. You never leave dbt:
metrics:
- name: total_revenue
description: "Total paid revenue in USD"
type: simple
type_params:
measure: order_total
meta:
onlymetrix:
tier: core # core / standard / foundation
autoresearch: true # enable improvement loops
Tier controls visibility and search ranking. Core metrics are pinned to the top of the catalog and rank highest when agents search. Foundation metrics (auto-suggested) are collapsed by default. Standard is the default for anything authored or imported.
Autoresearch enables overnight improvement loops. OnlyMetrix runs systematic IR mutations, scores each variation against ground truth, and surfaces Pareto-optimal improvements for human review.
Metric type support
| dbt type | OnlyMetrix result | Notes |
|---|---|---|
| simple (sum, count, avg, min, max) | Structured | Full IR decomposition |
| count_distinct | Structured | |
| ratio | Opaque | Components synced as separate Structured metrics |
| derived | Opaque | Expression preserved |
| Legacy (dbt < 1.6) | Structured | type + sql + model translated |
Structured metrics are the goal. They support filters, dimensions, time ranges, and entity enrichment. Opaque metrics work but are limited to the raw SQL. The dry-run output clearly flags which metrics are which, so you know before syncing.
CI/CD integration
Add two lines to your GitHub Actions workflow:
- run: pip install onlymetrix
- run: omx dbt sync
env:
OMX_API_URL: ${{ secrets.OMX_API_URL }}
OMX_API_KEY: ${{ secrets.OMX_API_KEY }}
Every merged PR syncs metrics to OnlyMetrix automatically. Use --strict to fail the build if any metric compiles as Opaque.
We also ship a dbt test, compiles_as_structured, that validates metric compilation inside your dbt test suite. Install from github.com/dreynow/dbt-onlymetrix and add it to your schema.yml:
models:
- name: orders
columns:
- name: revenue
tests:
- onlymetrix.compiles_as_structured:
metric_name: total_revenue
What your agents see
After syncing, any MCP-compatible agent (Claude, GPT, Cursor) can call:
query_metric("total_revenue")
# -> deterministic result, entity-enriched, PII masked
# No SQL generated. Ever.
Or from the Python SDK:
from onlymetrix import OnlyMetrix
om = OnlyMetrix(url="https://api.onlymetrix.com", api_key="omx_sk_...")
# The same metric your dbt model defines
result = om.metrics.query("total_revenue")
print(result.rows) # [{"total_revenue": 2107}]
# Search by intent
metrics = om.metrics.list(search="how many enterprise customers")
# -> finds enterprise_customer_count via semantic search
The agent picks which metric to run. The SQL was written by your data team, compiled through the IR, and validated in CI. The agent never sees the SQL. It never generates SQL. It calls a metric by name and gets back a governed result.
The real e2e we ran
Before shipping this, we ran the full flow against a live ClickHouse Cloud instance with a SaaS B2B dataset: 10 customers, 15 orders, 6 products, 20 events.
omx dbt connect # read profiles.yml, connected to ClickHouse Cloud
omx dbt sync # 5 metrics synced, all Structured, 0 Opaque
omx metrics query total_revenue
# -> $2,107
omx metrics query customer_count
# -> 10
omx metrics query avg_order_value
# -> $162.08
omx metrics query enterprise_customer_count
# -> 3
omx dbt sync # re-run: "All 5 metrics unchanged. Nothing to sync."
Free tier. No dashboard. No manual configuration. Six terminal commands.
Get started
pip install onlymetrix
Sign up at app.onlymetrix.com (free), grab your API key, and run:
export OMX_API_URL=https://api.onlymetrix.com
export OMX_API_KEY=omx_sk_...
omx dbt connect
omx dbt sync --dry-run
See what your agents would get. Then drop the --dry-run.
Full documentation at /docs/integrations/dbt. Source code at github.com/dreynow/onlymetrix. dbt package at github.com/dreynow/dbt-onlymetrix.
The honest positioning
dbt + MetricFlow + MCP is a genuinely good solution for governed agent access to metrics. We're not here to replace that.
OnlyMetrix adds a different layer: compile-time safety that catches errors before queries run. Autoresearch that improves metrics overnight. An analysis engine that answers "why" not just "what." Entity resolution across data sources. And a self-serve path that works without dbt Cloud.
If you're on dbt, omx dbt sync brings your metrics into OM's compiler and analysis engine. If you're not on dbt, OM is the complete stack.
Author in dbt. Make them better with OnlyMetrix.