Our engine never sees your warehouse password
datahashi

BlogModeling & metrics

Your first metric: name it, do not hand-write SQL

Walk through defining a first certified metric by name and measure without pasting hand-written SQL into the agent path.

The datahashi team3 min read

The fastest way to undermine an agent-ready stack is to paste hand-written SQL into the agent path. It works once. Then someone edits a CTE, another consumer copies a different variant, and “revenue” means three things.

Your first certified metric should start with a name and a measure, not with a query the model is free to rewrite.

Start from the question, not the SELECT

Pick one question your team already argues about - for example, how many orders completed last week, or what net revenue was for a region. Write the metric name the way you want callers to say it: stable, readable, and free of implementation detail. Prefer orders_completed over orders_completed_v2_final_sql.

Decide the measure: count, sum, or another aggregation your model supports. Decide the grain: one row per order, per customer-day, or whatever the warehouse table already represents. The warehouse holds transforms. You are not rebuilding dbt inside the serving layer.

Model it in YAML, publish an immutable artifact

In datahashi, metrics live in a YAML model. You declare the metric name, the measure, the source binding your team trusts, and the dimensions and filters callers may use. Publish that model as an immutable artifact. Immutability matters: consumers pin to a published definition instead of chasing a mutable draft.

Keep the layer thin. Do not copy transform logic into the metric file. Point at warehouse objects that already embody the grain you need. If the grain is wrong, fix it upstream - then certify the metric.

Keep SQL out of the agent path

Agents should never receive a blob of SQL to “improve.” They should receive tools that speak the contract: list_catalog to see what exists, describe_metric to read the definition, and run_semantic_query to execute a request. Those MCP tools do not accept or return SQL. REST and the console use the same request shape, so a human in the UI and an agent in a chat are not on different dialects.

Hand-written SQL can still exist in your warehouse modeling practice. It just does not travel into the consumer contract. Once the metric is published, callers ask by name.

Wire dimensions and filters on purpose

A first metric needs a small, honest set of dimensions - time, region, product family - whatever the underlying model actually supports. Expose filters that are safe and meaningful. Resist the urge to expose every column. Every extra dimension is another way to ask a question the grain cannot answer cleanly.

Document in the metric description what the number includes and excludes. Agents read that description through describe_metric. Humans read it in the console. Same text, same contract.

Prove the first number two ways

Before you celebrate, run one request from a dashboard-style consumer and one from an agent-style consumer against the same metric, dimensions, and filters. You want the same number. Metering helps you see that both calls happened and what they asked for.

If the numbers diverge, the bug is in the setup or the consumer request - not in “the LLM being creative” - because neither path should be inventing SQL.

Scope for day one

One metric. Clear name. Published artifact. No SQL in the agent tools. Same request shape everywhere. That is enough to change how your team talks about truth. Rollups have shipped, and they are not required for this first win. Do not block certification on a p99 target.

Name the metric. Publish it. Let every consumer call it the same way.

Product notes

An occasional email when we ship something or write something worth reading.