Snowflake logoSnowflake integration

Your Snowflake warehouse holds the numbers. KPI Tree explains the movement, names the owner and proves the fix.

Connect Snowflake with a role that can only read. Write a metric in SQL, draft one from plain English with Cortex Analyst, or sync a Semantic View so Snowflake computes every measure.

Governed in Snowflake. Explained in KPI Tree. One read-only role, three ways in.

A Snowflake connection is a role with USAGE and SELECT and nothing more. On it, a metric can be written as SQL, drafted from a question by Cortex Analyst against one of your Semantic Views, or synced straight from a Semantic View so that Snowflake itself computes the measure. Whichever way in, KPI Tree treats Snowflake as the source of truth: one aggregation query per metric at day grain, returned as Arrow, with every comparison, rollup and driver test computed in memory rather than as another warehouse query. dbt metrics that build into Snowflake run on the same connection.

What your warehouse does not know is why Revenue fell, who owns Conversion, or whether Monday's release moved it. That is the layer KPI Tree adds: a causal metric tree re-tested every night, RACI ownership on every node, action plans measured against a forecast, and Canopy, the business context layer that hands all of it to your people and to the agents they already use over MCP. Your warehouse stays the single source of truth for how a metric is calculated. KPI Tree becomes the source of truth for what to do about it.

Three ways to define a metric, one governed connection

Write the SQL yourself, ask Cortex Analyst to draft it from plain English against a Semantic View, or sync a Semantic View and let Snowflake compute each measure. Every route ends in the same tracked metric with the same owner and the same nightly driver tests.

New metric

SQLCortex
Net revenue per day for completed orders, excluding refunds
Semantic view · SALES_SVCortex Analyst

SELECT order_date AS date,

SUM(order_total) - SUM(refund_total) AS value

FROM marts.fct_orders

WHERE status = 'complete' GROUP BY 1

Drafted by Cortex, run on your warehouse, reviewed here before it is saved as a metric.

One query per metric, everything else in memory

Each metric is one aggregation query at day grain, returned as Apache Arrow and cached for a TTL you set. Comparisons, rollups, breakdowns and the nightly correlation and causality sweep run in KPI Tree’s own engine, so the credit bill stays flat as the tree grows.

Warehouse queries · last sync

4 total
Revenue1 query · 1.8s · 412 rows
Orders1 query · 1.2s · 412 rows
Average order value1 query · 1.6s · 412 rows
Active customers1 query · 2.3s · 412 rows

0 warehouse queries for

period comparisons, weekly and monthly rollups, dimension breakdowns, nightly correlation and causality tests. All computed in memory from those four results.

Dimension metrics, created automatically

Sync a Semantic View with Create Dimension Metrics on and every dimension you chose becomes a child metric per value: Revenue (Region: EMEA), Revenue (Region: APAC), and so on. Each child gets its own owner, baseline and nightly driver tests, within a cardinality limit you control.

Revenue

Create Dimension Metrics · on

dimensions: region, channel · 5 child metrics created

Revenue (Region: EMEA)£612k4%
Revenue (Region: APAC)£318k21%
Revenue (Region: UK)£350k2%
Revenue (Channel: Web)£880k1%
Revenue (Channel: App)£400k9%

Each child has its own owner, baseline and nightly driver tests. No YAML changes.

Read-only by construction, your controls stay on

The wizard writes the SQL for a dedicated user, a least-privilege role and an optional network policy that admits one static IP. Row access policies, masking policies and RBAC apply to every query because KPI Tree reads through your governance, never around it.

Snowflake

Connected · SELECT 1 ok
Account identifieracme-analytics
User · roleKPITREE_USER · KPITREE_ROLE
Warehouse · databaseKPITREE_WH · ANALYTICS
AuthRSA key-pair · •••••
Network policy · one static IPRead-only roleFuture grants covered

Connected in three steps. The wizard writes the SQL. You review it and run it.

No agent to install and no data to export. The connection is tested with a live SELECT 1 before it is saved, and the private key or password is encrypted at rest and never logged.

Run the generated setup SQL

The wizard writes copy-and-paste SQL for a dedicated user, a role with USAGE and SELECT including future grants, and SELECT on your Semantic Views. Choose a password or an RSA key pair, and add a network policy that admits KPI Tree’s single static IP if your account requires one. Paste it into a worksheet, review it, run it.
  • Password or RSA key-pair authentication, your choice
  • Least-privilege role with future grants, so new tables are covered
  • Optional network policy scoped to one static IP
setup.sqlgenerated by the wizard

-- Generated by the wizard, reviewed by you, run in a worksheet

CREATE USER IF NOT EXISTS KPITREE_USER

RSA_PUBLIC_KEY = 'MIIBIjANBg…';

CREATE ROLE IF NOT EXISTS KPITREE_ROLE;

GRANT ROLE KPITREE_ROLE TO USER KPITREE_USER;

GRANT USAGE, MONITOR ON WAREHOUSE KPITREE_WH TO ROLE KPITREE_ROLE;

GRANT USAGE, MONITOR ON DATABASE ANALYTICS TO ROLE KPITREE_ROLE;

GRANT SELECT ON ALL TABLES IN DATABASE ANALYTICS TO ROLE KPITREE_ROLE;

GRANT SELECT ON FUTURE TABLES IN DATABASE ANALYTICS TO ROLE KPITREE_ROLE;

GRANT SELECT ON ALL SEMANTIC VIEWS IN DATABASE ANALYTICS TO ROLE KPITREE_ROLE;

-- Optional: admit one static IP and nothing else

CREATE OR REPLACE NETWORK RULE KPITREE_ALLOW_RULE MODE = INGRESS TYPE = IPV4 VALUE_LIST = ('34.89.0.12');

CREATE OR REPLACE NETWORK POLICY KPITREE_POLICY ALLOWED_NETWORK_RULE_LIST = ('KPITREE_ALLOW_RULE');

ALTER USER KPITREE_USER SET NETWORK_POLICY = KPITREE_POLICY;

Connect and validate

Enter the account identifier, user, role, warehouse and default database, then the private key or password. KPI Tree runs a SELECT 1 and only saves the connection once it succeeds. Point it at a small dedicated warehouse if you want the sync traffic on its own line of the bill.
  • Validated with a live query before it is saved
  • Credentials encrypted at rest, never logged
  • Every sync query deep-links to Snowflake’s query history

Snowflake

Connected · SELECT 1 ok
Account identifieracme-analytics
User · roleKPITREE_USER · KPITREE_ROLE
Warehouse · databaseKPITREE_WH · ANALYTICS
AuthRSA key-pair · •••••
Network policy · one static IPRead-only roleFuture grants covered

Write, draft or sync

Write SQL against your tables and views, one query per metric at day grain. Or switch the editor to Cortex mode, choose a Semantic View, and describe the metric in plain English: Cortex Analyst drafts the SQL, KPI Tree runs it on your warehouse, and you review the result before saving it as a metric. Or sync a whole Semantic View and let Snowflake compute every measure.
  • SQL metrics against any table or view the role can read
  • Cortex Analyst drafts from a question, against a Semantic View you choose
  • Semantic View sync turns every metric in the view into a tracked metric

New metric

SQLCortex
Net revenue per day for completed orders, excluding refunds
Semantic view · SALES_SVCortex Analyst

SELECT order_date AS date,

SUM(order_total) - SUM(refund_total) AS value

FROM marts.fct_orders

WHERE status = 'complete' GROUP BY 1

Drafted by Cortex, run on your warehouse, reviewed here before it is saved as a metric.

SQL and Cortex, or a Semantic View. Same connection, same layer above. Start where your definitions live.

Both paths run on the same read-only role and produce the same trees and ownership. The difference is who owns the definition: you, in a query, or Snowflake, in a Semantic View.

SQL metrics and Cortex Analyst

This page

Metrics you write, or draft from a question, against any table or view the role can read.

Definition
A SQL query per metric, written or drafted by Cortex
Runs
On your warehouse, one query per metric at day grain
Rollups
Chosen per metric in KPI Tree
Needs
A role with USAGE and SELECT

Snowflake Semantic Views

Governed metrics synced from a Semantic View, computed by Snowflake through SEMANTIC_VIEW().

Definition
The Semantic View, read with DESCRIBE SEMANTIC VIEW
Runs
On your warehouse, one SEMANTIC_VIEW() query per metric
Rollups
Inferred from each metric’s expression, adjustable
Needs
SELECT on the view, in the connection’s default database

What a Snowflake metric is. One query at day grain, however it was defined.

Every metric on a Snowflake connection resolves to a single aggregation query that returns a daily series. KPI Tree keeps that series, never the rows behind it, and computes everything else itself.

SQL metrics your query, your tables

Any SELECT the role can run, returning a date and a value. Results come back as Arrow and are cached for a TTL you set on the connection. Weekly, monthly and quarterly rollups are computed by KPI Tree, with the rollup method you choose.

Cortex Analyst drafts from a question, on a Semantic View

Describe the metric in plain English, pick the Semantic View that governs the terms, and Cortex Analyst drafts the SQL. It runs on your warehouse under your role, and you review the query and the result before saving it. KPI Tree is a consumer of Cortex here, never a replacement.

Semantic View sync Snowflake computes every measure

Pick a Semantic View and every metric in it becomes a tracked metric queried through SEMANTIC_VIEW(), so the number here is the number Snowflake gives everyone else. Dimension metrics are created for the dimensions you choose. The Semantic Views page has the detail.
The layer above

Snowflake governs the calculation. KPI Tree adds causation, ownership and proof.

Above your governed definitions sits one causal model of the business, with the org chart, the recorded context and the outcome of every action attached. People read it as a tree. Agents read the same graph over MCP.

For humans

Answers, briefings and pushes

KPI Tree web appSlack@

Read and write over MCP

Anthropic: 21% → ~95% with curated context

ClaudeOpenAIGeminiCopilot

Canopy Agentic Workflows the metrics start them, humans gate them

Canopy Agents four out of the box, any model, your keys

Canopy

The business context layer

Structural context The causal tree, the org chart

Temporal context What was true when, plan against actual

Behavioural context What people did, what worked

Operational context RACI, workflows, approvals

Strategic context Objectives, key results, initiatives

Map & Measure

Metric Trees

Business Models

Prove & Act

Root Cause

Ownership

Verified Impact

Strategy

Grounded in proven causality

Verified proof

Meta spend → Revenue, +£32k vs forecast, q < 0.01

Personalised Action Plans 31 experiments running

hypothesis → a real person’s plan → measure the change

Causation the test cascade

ADF p 0.02 → Granger p 0.003 → q < 0.05, 87 of 1,204 survive

Correlation

22,791 pairs tested nightly, NPS – Churn r 0.71

Data warehouses

The numbers

SnowflakeBigQueryDatabricksRedshiftAzure SQLPostgreSQLGoogle Sheets

Semantic layers

The definitions

dbtLookerSnowflake Semantic ViewsDatabricks Unity Catalog metricsOpen Semantic Interchange

Business apps

Launches, decisions, blockers

SlackNotionHubSpotSalesforceJiraLinearGitHubAsanaMicrosoft TeamsGoogle WorkspaceIntercom

Org structure

Directory-synced

David MitchellSarah ChenMei-Lin WongJames Harrington

Causal drivers, tested every night

Your dbt metrics become nodes on a tree. Every edge between them is re-tested nightly, from correlation through Granger causality with false-discovery control, so a driver carries a confidence level rather than a line someone drew.
causal · q < 0.05lag 3dq < 0.01Revenue-15%Conversion-23%Traffic+2%AOV-4%Checkout-31%PricingPaidOrganicBasket sizeDiscountsPayment errorsPage speed

RACI ownership, on every metric

Each metric gets Responsible, Accountable, Consulted and Informed assignments tied to real people in your directory. When it breaches its baseline the Accountable owner hears first, in Slack or by email, with escalation if nobody acts.

Conversion rate

Marketing · daily

R
A
C
+4
I

Verified impact, not self-reported

Actions are tracked against the metric they target and measured against a counterfactual forecast when the window closes. What held becomes a driver the model trusts. What did not is retracted.

Fix checkout flow

Verified · +£32k

Linked to Revenue · measured by the actuals pipeline

Pause underperforming ad sets

Measuring…

Ask an agent the same question twice. Once on Snowflake, once on Canopy above it.

You already point an agent at Snowflake over MCP, or ask Cortex Analyst, and it comes back with a governed number. The fair question is what Canopy adds. The pair below shows the shape of the difference, and the benchmark beneath it measures it, on Snowflake, on eight real business questions.

The semantic layer alone

A correct number, and a dead end.

An agent on Snowflake over MCP writes SQL from scratch every time. Cortex Analyst on a semantic model gets the definition right. Neither gets the cause, the owner or the follow-up, so the question goes back to the data team.

Why is revenue down this month?
Revenue is £1.28m month to date, 15% below last month. The metric is defined as the sum of order_total where status is complete.
I do not have information about what caused the change or who is responsible. Would you like me to break it down by region?

Canopy on top of dbt

The driver, the owner, the build check and the next step.

Canopy reads the causal tree, the RACI, the build history from your dbt artifacts and the open tasks, so the first answer is the one people act on.

Why is revenue down this month?
Conversion rate is the driver, down 23%, Granger-causal at a three day lag. Traffic and order value are flat. The drop starts the day after Monday's checkout release.
The data is sound: fct_orders built at 06:12 and every source passed freshness. Sarah Chen is Accountable and a rollback task is already open. Shall I attach this analysis to it?
driver · q < 0.05owner · Sarah Chenbuild · freshtask · open

Common questions

What does the setup wizard generate?

SQL for a dedicated user with a password or an RSA public key, a role with USAGE on the database, schemas and warehouse and SELECT on current and future tables, views and Semantic Views, and, if you want it, a network rule and policy that admit KPI Tree’s single static IP. You review the SQL in a worksheet before running it, and the connection is validated with a live SELECT 1 before it saves.

What permissions does KPI Tree need?

USAGE and MONITOR on the database, its schemas and the warehouse, and SELECT on tables, views and Semantic Views, with future grants so new objects are covered. That is the whole grant surface, and it is read-only. Row access policies, masking policies and RBAC apply to every query because they run as your role.

Password or RSA key-pair authentication?

Either. The wizard generates a password by default and can generate the RSA statements instead. Snowflake supports two public keys at once, so a key pair can be rotated with no downtime. Whichever you choose is encrypted at rest and never logged.

How does Cortex Analyst work in KPI Tree?

The metric editor has a Cortex mode. Choose a Semantic View, describe the metric in plain English, and Cortex Analyst drafts the SQL. KPI Tree runs it on your warehouse under your role and shows you the query and the result, which you review before saving the metric. Cortex cross-region inference must be enabled on your account. KPI Tree is a consumer of Cortex here, not a replacement.

How do Semantic Views work in KPI Tree?

Pick a Semantic View from the ones in the connection’s default database and every metric in it becomes a tracked metric, queried through SEMANTIC_VIEW() so Snowflake computes the value. Dimension metrics are created for the dimensions you choose. The Snowflake Semantic Views page covers the sync in detail.

How does KPI Tree affect Snowflake costs?

One aggregation query per metric on your schedule, returned as Arrow and cached for a TTL you set. Every comparison, rollup, correlation and drill-down runs in KPI Tree’s own engine, so exploration adds no Snowflake load. A small dedicated warehouse keeps the sync traffic on its own line of the bill, and its own auto-suspend setting keeps it idle between syncs.

Does KPI Tree work with dbt on Snowflake?

Yes. Connect dbt Core or dbt Cloud through the dbt Semantic Layer integration and link this Snowflake connection as the execution warehouse. Definitions stay in dbt and the SQL runs here.

Does KPI Tree copy data out of Snowflake?

No. Each metric’s daily series is fetched, computed on in KPI Tree’s encrypted in-memory engine and cached only briefly. Raw rows are never persisted outside your account, and every Snowflake control stays enforced on each query.

Does KPI Tree use Snowflake Horizon, Snowflake CoWork or the Snowflake MCP server?

Not at present. KPI Tree reads Snowflake through SQL under your role, uses Cortex Analyst to draft SQL against a Semantic View, and syncs Semantic Views natively. Horizon metadata, Snowflake CoWork and the Snowflake-managed MCP server are not read.

Which agents can use the Snowflake metrics?

Any MCP-capable assistant such as Claude, ChatGPT, Gemini or Copilot, through Canopy, KPI Tree’s business context layer. An agent sees each metric with its drivers, owners and recorded context and, with editor access, can run read-only queries on this connection to test an explanation.

You built the warehouse. Now build the layer above it.

Connect Snowflake and see your own metrics as a causal tree with named owners and verified actions, in a demo on your data.

The guide

Semantic layer vs business context layer: what a definition settles, and what it cannot.

Read the guide

Experience That Matters

Built by a team that's been in your shoes

Our team brings deep experience from leading Data, Growth and People teams at some of the fastest growing scaleups in Europe through to IPO and beyond. We've faced the same challenges you're facing now.

Checkout.com
Planet
UK Government
Travelex
BT
Sainsbury's
Goldman Sachs
Dojo
Redpin
Farfetch
Just Eat for Business