Factory Labs

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/snowflake

Fill in Step 1 of the wizard:

FieldValue
NameSnowflake pilot (or any label)
Account locatorxy12345.us-east-1.aws (or the full URL https://xy12345.us-east-1.aws.snowflakecomputing.com)
WarehouseCOMPUTE_WH
Default databaseANALYTICS
Default schemaPUBLIC
RoleFACTORY_ANALYST
UsernameSVC_FACTORY
Private keyUpload 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_connections with provider = 'snowflake', status untested.

Step 4 — Test the connection

Click Run test. The platform:

  1. Builds and signs a JWT with the private key (issuer = <account>.<user>, expiry = 60s).
  2. Calls the Snowflake SQL REST API with Authorization: Bearer <jwt> and a SELECT 1.
  3. Captures latency and the principal (SVC_FACTORY).
  4. Flips status from untestedok (active in DB).

Expected wall-clock: < 5 seconds.

If the test fails:

CodeLikely causeFix
AUTH_FAILEDPublic key fingerprint mismatch — wrong key uploaded, or ALTER USER not runRe-run DESCRIBE USER SVC_FACTORY and confirm the fingerprint matches the local key
WAREHOUSE_OFFLINECOMPUTE_WH is SUSPENDED and AUTO_RESUME is offRun ALTER WAREHOUSE COMPUTE_WH RESUME or set AUTO_RESUME = TRUE
INSUFFICIENT_PRIVILEGESRole lacks USE on the warehouse or SELECT on the schemaRe-grant per Step 2
HOST_NOT_FOUNDAccount 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:

  1. Pick a table from the catalog → schema → table picker. Snowflake's SHOW DATABASES / SCHEMAS / TABLES powers the dropdowns. Preview shows 3 sample rows.
  2. Define the Assistant skill — description (with Suggest with AI), allow-listed columns, optional row filter (e.g. region = 'NA').
  3. Get an AI semantic-link suggestion — heuristic-first, AI fallback. Accept to enable JOINs against CRM entities.
  4. 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:

  1. Federated reads (this guide) — the Assistant queries Snowflake tables live.
  2. 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.