Platform
One model between your warehouse and everyone who queries it.
Define your metrics once. Every dashboard, app, and MCP agent asks by name and gets the same governed answer — compiled to fan-out-safe SQL and run in your own warehouse. Built for teams shipping agents who can't afford confidently-wrong numbers.
The model
One definition per number
You map your warehouse tables to business terms once — entities, dimensions, measures, metrics — in YAML. "Average order value" is defined in exactly one place. Publish it and every dashboard, app, and MCP agent gets that definition, not their own guess at it.
model.yaml
entities:
- name: Order
table: public.orders
primary_key: id
measures:
- name: revenue
expr: amount
agg: sum
- name: order_count
expr: id
agg: count
metrics:
- name: avg_order_value
expr: revenue / order_count
unit: USD
format: currency The compiler
You never write the join
Declare how your entities relate once. From then on, ask for revenue by customer region and you get the right SQL back — the join path worked out for you, fan-out-safe so revenue isn't multiplied because one customer has many orders. LLM-invented joins and the double-counting that quietly wrecks hand-written dashboards can't happen here.
Order.revenue (measure)
└─ Order ─▶ Customer (many-to-one)
Customer.region (dimension)
join path resolved · no double-counting Access modes
A tight surface for agents, a wide one for analysts
Governed mode gives out named metrics and curated views only — the safe default for an agent or an embedded chart. Explore mode also opens up raw measures and dimensions for someone doing hands-on analysis. A credential is tied to one mode; nothing a client sends can widen it.
-
Governed
named metrics · curated views · the default for agents
-
Explore
raw measures × dimensions · hands-on analysis
Agents
Agents can't go rogue on your data
An agent connects over MCP and signs in with OAuth — no long-lived key sitting in a config file. It picks metric and dimension names from your catalog and sends the same structured query everyone else does. It never sees the warehouse, so it can't hallucinate a join, invent a column, or read a row a policy hides. The worst it can do is ask for something it's not allowed and get told no.
mcp · tools/call
{
"name": "run_semantic_query",
"arguments": {
"metrics": ["revenue"],
"dimensions": [
{ "name": "ordered_at", "entity": "Order",
"grain": "quarter" }
]
}
} Isolation
Your data stays yours
You connect your own warehouse; datahashi reads it with the access you granted and never widens it. Credentials are encrypted at rest. Row-level rules apply to every read, so one model can serve many teams — or many of your own customers — without anyone seeing another's rows.
- Credentials encrypted at rest
- Read-only, no privilege widening
- Row-level security on every read
- Nothing copied out of your warehouse
Portability
Bring the warehouse you already have
The same request compiles to correct SQL for whichever warehouse backs your model. Move to a different one later and nothing that queries you has to change.
Today every query runs against your source behind a rate limiter and a short-lived result cache. On the roadmap: pre-computed rollups for hot queries — not claimed as current.
- Snowflake
- BigQuery
- Postgres
- MySQL
- DuckDB