Author in dbt. Serve through OnlyMetrix.

dbt builds your data. It doesn't serve it to AI agents. omx dbt sync bridges that gap: six terminal commands from zero to agent-queryable metrics.

dbt builds your data. It doesn't serve it.

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.

Then an AI agent needs to query that data, and everything falls apart.

The agent doesn't know about your dbt models. It doesn't know that "revenue" means SUM(total_cents / 100.0) WHERE status = 2. It doesn't know about your filters, your dimensions, your time columns. So it does what every agent does: it generates SQL from scratch, hopes it's right, and gives you a number that might or might not match what your dashboard says.

The irony is painful. You spent months building a governed, tested, documented data layer in dbt. And your AI agents ignore all of it.

The gap nobody talks about

dbt has a clearly defined scope: it transforms data. It doesn't serve data. The consumption paths are BI tools, reverse ETL, the Semantic Layer, or direct SQL by analysts.

None of these work for AI agents.

BI tools serve dashboards, not API calls. Reverse ETL pushes to SaaS, not to agent runtimes. The Semantic Layer requires dbt Cloud and is still early. Direct SQL means your agent is guessing.

There's no standard "last mile" that takes your carefully authored dbt metrics and makes them queryable by an AI agent with governance, determinism, and audit trails.

That's what we built.

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 registers them with the OnlyMetrix API.

Your agents call query_metric("total_revenue") and get back the exact same number your dbt model computes. Deterministic. Audited. PII-masked. No SQL generation.

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 typeOnlyMetrix resultNotes
simple (sum, count, avg, min, max)StructuredFull IR decomposition
count_distinctStructured
ratioOpaqueComponents synced as separate Structured metrics
derivedOpaqueExpression preserved
Legacy (dbt < 1.6)Structuredtype + 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.

Author in dbt. Serve through OnlyMetrix.

Ready to try deterministic data access?

Define your first metric. Let agents query safely.

Get Started