Connect Snowflake (Warehouse)
Expose Snowflake tables as governed AI Assistant skills via federated reads. Key-pair JWT auth, ~10 minutes through the wizard.
This guide sets up the federated reads stream for Snowflake — the AI Assistant queries your Snowflake account live as governed skills, with no copy of your data.
The Snowflake setup follows the same 6-step wizard as Databricks; only the credential flow differs. Snowflake federated reads use the SQL REST API with key-pair JWT authentication.
Prerequisites
- A Snowflake account (any AWS / Azure / GCP region — the SQL REST API is universally available).
- Permission on the Snowflake side to:
- Create a service user, role, warehouse, and grants.
- Run
ALTER USER … SET RSA_PUBLIC_KEY=….
- Local CLI:
openssl(for key generation). - Admin role in your Factory Labs workspace.
Step 1 — Generate a key pair (one-time)
Snowflake's SQL REST API authenticates with RSA key-pair JWT — no shared secret, no rotating PAT. Generate the pair locally:
openssl genrsa -out factory_key.pem 2048
openssl rsa -in factory_key.pem -pubout -out factory_key.pub
# Strip the PEM headers — Snowflake's ALTER USER expects just the body:
grep -v -- "-----" factory_key.pub | tr -d '\n'Keep factory_key.pem (the private key) on your laptop — you'll upload it to Factory in Step 3. The public key body goes into Snowflake in the next step.
Step 2 — Provision the Snowflake side
In Snowsight (or any Snowflake client), run:
USE ROLE ACCOUNTADMIN;
CREATE WAREHOUSE IF NOT EXISTS COMPUTE_WH
WITH WAREHOUSE_SIZE = 'XSMALL' AUTO_SUSPEND = 60;
CREATE ROLE IF NOT EXISTS FACTORY_ANALYST;
CREATE USER IF NOT EXISTS SVC_FACTORY
DEFAULT_ROLE = FACTORY_ANALYST
DEFAULT_WAREHOUSE = COMPUTE_WH;
GRANT ROLE FACTORY_ANALYST TO USER SVC_FACTORY;
GRANT USAGE ON WAREHOUSE COMPUTE_WH TO ROLE FACTORY_ANALYST;
GRANT USAGE ON DATABASE ANALYTICS TO ROLE FACTORY_ANALYST;
GRANT USAGE ON SCHEMA ANALYTICS.PUBLIC TO ROLE FACTORY_ANALYST;
GRANT SELECT ON ALL TABLES IN SCHEMA ANALYTICS.PUBLIC TO ROLE FACTORY_ANALYST;
-- Paste the stripped public key body from Step 1:
ALTER USER SVC_FACTORY SET RSA_PUBLIC_KEY='<paste pubkey body>';Verify the public key is registered:
DESCRIBE USER SVC_FACTORY;
-- Expect: RSA_PUBLIC_KEY_FP = SHA256:...Replace ANALYTICS.PUBLIC with the database/schema you actually want to expose. Use least privilege — grant SELECT only on the tables you intend to register.
Step 3 — Run the wizard
Go to Settings → Integrations → Snowflake (Warehouse) → Connect, or directly to:
/settings/integrations/warehouse/snowflakeFill in Step 1 of the wizard:
| Field | Value |
|---|---|
| Name | Snowflake pilot (or any label) |
| Account locator | xy12345.us-east-1.aws (or the full URL https://xy12345.us-east-1.aws.snowflakecomputing.com) |
| Warehouse | COMPUTE_WH |
| Default database | ANALYTICS |
| Default schema | PUBLIC |
| Role | FACTORY_ANALYST |
| Username | SVC_FACTORY |
| Private key | Upload factory_key.pem from Step 1 |
Click Save & continue. Factory:
- Encrypts the private key at rest with AES-256-GCM + per-tenant HKDF-derived key. The key is never round-tripped to the browser. See Governance → Encrypted credentials.
- Creates a row in
warehouse_connectionswithprovider = 'snowflake', statusuntested.
Step 4 — Test the connection
Click Run test. The platform:
- Builds and signs a JWT with the private key (issuer =
<account>.<user>, expiry = 60s). - Calls the Snowflake SQL REST API with
Authorization: Bearer <jwt>and aSELECT 1. - Captures latency and the principal (
SVC_FACTORY). - Flips status from
untested→ok(activein DB).
Expected wall-clock: < 5 seconds.
If the test fails:
| Code | Likely cause | Fix |
|---|---|---|
AUTH_FAILED | Public key fingerprint mismatch — wrong key uploaded, or ALTER USER not run | Re-run DESCRIBE USER SVC_FACTORY and confirm the fingerprint matches the local key |
WAREHOUSE_OFFLINE | COMPUTE_WH is SUSPENDED and AUTO_RESUME is off | Run ALTER WAREHOUSE COMPUTE_WH RESUME or set AUTO_RESUME = TRUE |
INSUFFICIENT_PRIVILEGES | Role lacks USE on the warehouse or SELECT on the schema | Re-grant per Step 2 |
HOST_NOT_FOUND | Account locator typo (e.g. wrong region suffix) | Copy the locator exactly from Snowsight URL |
Step 5 — Pick a table & define the skill
Steps 4–7 of the wizard are identical to the Databricks flow:
- Pick a table from the catalog → schema → table picker. Snowflake's
SHOW DATABASES / SCHEMAS / TABLESpowers the dropdowns. Preview shows 3 sample rows. - Define the Assistant skill — description (with Suggest with AI), allow-listed columns, optional row filter (e.g.
region = 'NA'). - Get an AI semantic-link suggestion — heuristic-first, AI fallback. Accept to enable JOINs against CRM entities.
- Activate as Assistant skill — generates a typed AI tool keyed
warehouse_table__<uuid>.
See the Databricks setup walkthrough for full detail on each sub-step — the wizard UI and behavior are 1:1 across providers.
Repeat for more tables
Each Snowflake connection can host any number of data sources; each becomes its own Assistant skill. Adding another table is < 2 minutes.
Verify the new tools registered correctly:
curl -H "Cookie: <session>" \
https://app.factorylabs.ai/api/v1/admin/agents/tool-catalog \
| jq '.data.entries | map(select(.group=="warehouse_table"))'What the Assistant sees
When the Assistant calls a Snowflake skill, query-guard enforces the same rules as for Databricks: single SELECT, allow-listed columns, row filter merged in, LIMIT clamp, payload cap. The query is then submitted to the Snowflake SQL REST API as a fresh JWT-authenticated call. Every call is logged to warehouse_query_log with bytes scanned and latency.
Cross-provider patterns
Snowflake-native customers commonly run two Lakehouse streams together:
- Federated reads (this guide) — the Assistant queries Snowflake tables live.
- Delta Sharing publish — Factory publishes CRM facts as a Delta share, which Snowflake natively reads via
CREATE CATALOG INTEGRATION … TYPE = DELTA_SHARING.
The result: the Snowflake account can JOIN warehouse tables with CRM facts inside Snowflake, without either side egressing data. See Delta Sharing → Consume from Snowflake.
Troubleshooting
JWT signature fails after the public key was just rotated
Snowflake caches the public key fingerprint for ~30 seconds. Wait 60 seconds after ALTER USER … SET RSA_PUBLIC_KEY=… before re-testing. If it still fails, run DESCRIBE USER SVC_FACTORY and confirm the fingerprint matches openssl rsa -in factory_key.pem -pubout | openssl rsa -pubin -outform DER | openssl dgst -sha256 -binary | openssl base64.
SQL_REJECTED on every query
Same as Databricks — query-guard rejected the SQL the model emitted. Check warehouse_query_log.reason for the structured rejection code (COLUMN_NOT_ALLOW_LISTED, MULTI_STATEMENT, DDL_FORBIDDEN, etc.).
Snowflake bills add up faster than expected
Set AUTO_SUSPEND = 60 on COMPUTE_WH so it sleeps after 60s idle. The first Assistant call after a sleep will incur a ~5s warm-up; subsequent calls in the same minute reuse the warm cluster.
Related guides
- Connect Databricks — same wizard, different auth.
- Delta Sharing publish — mirror CRM facts back to Snowflake.
- Governance — query-guard, encryption, audit.
Connect Databricks (Warehouse)
Expose Databricks SQL warehouse tables as governed AI Assistant skills via federated reads. OAuth M2M or PAT, ~5 minutes through the wizard.
Delta Sharing Publish
Stream CRM facts (accounts, contacts, leads, opportunities, activities, cases) back to your Databricks, Snowflake, or PyIceberg lake every 15 minutes as Delta tables.