Snowflake ExecModule
Overview
SnowflakeModule connects ValkyrAI workflows to the Snowflake SQL API through the native map I/O ExecModule ABI. Workflow Studio discovers it as SnowflakeModule; the account identifier and bearer token are resolved only from a bound encrypted IntegrationAccount.
The initial connector covers warehouse discovery, parameterized read queries, confirmed single-statement SQL, bounded row insert/update operations, and statement status, partition, and cancellation operations. It normalizes Snowflake row arrays by their returned column names, caps responses, constructs only a Snowflake account host, and never retries an ambiguous mutation automatically.
Usage
- Create a least-privilege Snowflake service user and role with access only to the required warehouse, database, schema, and objects.
- Configure OAuth, key-pair JWT, or a role-restricted programmatic access token (PAT).
- Store the Snowflake account identifier in
IntegrationAccount.accountIdand the bearer token in the encryptedapiKeySecureField. - Set the account to
READY, bind it throughExecModuleConfig.authConfig.integrationAccount, and select the matchingtokenType. - Prefer the typed discovery, query, insert, and update operations. Use
execute_statementonly for a deliberate single DDL/DML statement. - Supply a caller-owned UUID
requestIdandconfirmWrite: truefor every mutation.
Workflow input cannot provide credentials, an arbitrary hostname, an authorization header, or multiple SQL statements.
Inputs
| Name | Type | Requirement | Default | Description and constraints |
|---|---|---|---|---|
operation | string | Required | None | One of the ten documented operations. |
tokenType | string | Required | PROGRAMMATIC_ACCESS_TOKEN | OAUTH, KEYPAIR_JWT, or PROGRAMMATIC_ACCESS_TOKEN. |
database / schema / warehouse / role | string | Optional context | Account defaults | Case-sensitive Snowflake identifiers, up to 255 characters. |
statement | string | Query/statement operations | None | One SQL statement, maximum 100,000 characters. Semicolon-separated statements are rejected. |
bindings | array | Optional query bindings | None | Up to 1,000 {type,value} objects. Values must be JSON scalars. |
table | string | Row/describe operations | None | Valid unquoted Snowflake identifier. Database/schema context is applied separately. |
rows | array | insert_rows | None | 1–500 objects with identical columns and scalar values. |
values | object | update_rows | None | Non-empty changed-column map, at most 50 columns. |
where | object | update_rows | None | Required equality predicates, at most 20 columns; prevents an unbounded update. |
statementHandle | UUID string | Status/cancel | None | Snowflake statement handle. |
partition | integer | Optional status read | 0 | Result partition from 0 through 10,000. |
requestId | UUID string | Required writes | Generated for reads | Caller-owned Snowflake request-deduplication identifier. |
async | boolean | Optional submission mode | false | Returns a pending statement receipt when accepted asynchronously. |
statementTimeoutSeconds | integer | Optional | 60 | Snowflake execution timeout from 1 through 3,600 seconds. |
maxRows | integer | Optional | 1000 | Maximum normalized rows from one result partition, up to 10,000. |
confirmWrite / confirmCancel | boolean | Mutation guard | false | Explicit acknowledgement for writes or statement cancellation. |
Supported binding types are FIXED, REAL, DECFLOAT, TEXT, BINARY, BOOLEAN, DATE, TIME, TIMESTAMP_TZ, TIMESTAMP_LTZ, and TIMESTAMP_NTZ. Snowflake SQL API binding values are serialized as strings.
Outputs
| Name | Type | When present | Description |
|---|---|---|---|
status | string | Always | success, pending, or error. |
operation | string | Always | Normalized operation. |
httpStatus / attempts | integer | Provider request | Provider status and total attempts. |
items / count | array / integer | Result-set success | Rows mapped to returned Snowflake column names. |
data | object | Receipt/non-row success | Sanitized provider response. |
statementHandle | UUID string | Provider returns it | Handle for status, partition, or cancellation operations. |
hasMore / nextPartition | boolean / integer | Partitioned query | Bounded continuation state. |
error | object | Failure | Safe {code,message,httpStatus?,retryable} details. |
Tokens and authorization values are redacted from errors, outputs, and workflow events.
IntegrationAccount Requirements
| Setting | Requirement |
|---|---|
| Provider | Snowflake account with the SQL API reachable through its account hostname |
accountName | Human-readable automation identity |
accountId | Snowflake account identifier, for example myorg-myaccount |
apiKey | Encrypted SecureField containing an OAuth token, key-pair JWT, or PAT |
status | Exactly READY |
Use a role-restricted PAT or short-lived OAuth/key-pair JWT and a network policy that permits the ValkyrAI execution environment. The selected role needs only the warehouse USAGE, database/schema USAGE, and object privileges required by the chosen operations. Token issuance and rotation remain IntegrationAccount lifecycle responsibilities.
Configuration
{
"version": "1.0.0",
"authConfig": {
"authStrategy": 1,
"integrationAccount": "integration-account:snowflake-analytics"
},
"retryPolicy": {
"maxAttempts": 3,
"backoffStrategy": "EXPONENTIAL",
"initialDelayMs": 1000,
"maxDelayMs": 60000
},
"payloadConfig": {
"parameters": "{\"operation\":\"execute_query\",\"tokenType\":\"PROGRAMMATIC_ACCESS_TOKEN\",\"database\":\"ANALYTICS\",\"schema\":\"PUBLIC\",\"warehouse\":\"COMPUTE_WH\"}"
}
}
The integration-account reference is symbolic. Persisted workflows use the generated relationship and never plaintext tokens.
Operations
| Operation | Snowflake behavior | Side effect |
|---|---|---|
execute_query | Runs one SELECT, SHOW, DESCRIBE, DESC, or EXPLAIN statement with optional bindings. | Read-only; conservative retries. |
execute_statement | Runs one caller-supplied DDL/DML statement after confirmation. | Write/DDL; single attempt. |
insert_rows | Builds one quoted parameterized INSERT for 1–500 same-shape rows. | Write; single attempt. |
update_rows | Builds one quoted parameterized UPDATE with required equality predicates. | Write; single attempt. |
list_databases | Executes fixed SHOW DATABASES. | Read-only. |
list_schemas | Executes fixed SHOW SCHEMAS, optionally in a database. | Read-only. |
list_tables | Executes fixed SHOW TABLES, optionally in a database/schema. | Read-only. |
describe_table | Executes a quoted DESCRIBE TABLE. | Read-only. |
get_statement | Gets statement status or one result partition by UUID. | Read-only. |
cancel_statement | Cancels a statement UUID after explicit confirmation. | Control mutation; single attempt. |
Errors and Failure Modes
| Code | Typical cause | Retryable | Resolution |
|---|---|---|---|
VALIDATION_ERROR | Missing credential/context, invalid identifier/UUID/binding, multiple statements, unsafe read SQL, absent predicate, or missing confirmation. | No | Correct the named input; no request was sent. |
UNSUPPORTED_OPERATION | Unknown operation. | No | Select a documented operation. |
INTEGRATION_ACCOUNT_REQUIRED | No bound account. | No | Bind a Snowflake IntegrationAccount. |
INTEGRATION_ACCOUNT_NOT_READY | Account is not READY. | No | Repair or reconnect the account. |
SNOWFLAKE_HTTP_400 / 422 | Invalid SQL, binding, context, or provider constraint. | No | Correct the statement or typed inputs. |
SNOWFLAKE_HTTP_401 / 403 | Invalid token, network policy, role, or privilege. | No | Rotate credentials or grant minimum required access. |
SNOWFLAKE_HTTP_429 / 5xx | Concurrency/rate limit or transient provider failure. | Reads only | Retry a read; reconcile a write by request ID/handle first. |
NETWORK_ERROR | Timeout, DNS, TLS, or connectivity failure. | Reads only | Verify connectivity; never blindly repeat an ambiguous mutation. |
RESPONSE_TOO_LARGE | Response exceeded 10 MiB. | No | Narrow the query or retrieve smaller partitions. |
Example
Query qualified accounts with a bound value:
{
"operation": "execute_query",
"database": "ANALYTICS",
"schema": "PUBLIC",
"warehouse": "COMPUTE_WH",
"statement": "SELECT ID, NAME FROM ACCOUNTS WHERE SCORE >= ?",
"bindings": [
{"type": "FIXED", "value": "80"}
],
"maxRows": 100
}
Expected result:
{
"status": "success",
"operation": "execute_query",
"httpStatus": 200,
"count": 2,
"items": [
{"ID": "42", "NAME": "Northstar"},
{"ID": "77", "NAME": "Valkyr"}
],
"hasMore": false,
"attempts": 1
}
Notes
- Pagination: Snowflake determines result partitions. The initial/status response exposes partition metadata; resume with
get_statementandpartition. This version returns one bounded partition per operation and never follows provider-supplied absolute URLs. - Rate limits: read-only requests may retry HTTP 408, 429, 500, 502, 503, and 504 with bounded exponential backoff while honoring integer or HTTP-date
Retry-After.execute_statement, inserts, updates, and cancellation are always single-attempt. - API limits: request bodies are capped at 1 MiB, responses at 10 MiB, inserts at 500 rows, bindings at 1,000, and normalized output at 10,000 rows per partition.
- Idempotency: every mutation requires a caller-owned UUID
requestId. Snowflake uses it for request reconciliation, but a timeout is still ambiguous; inspect statement history/status before manual retry. - Destructive behavior:
execute_statementcan perform DDL or DML and therefore requiresconfirmWrite. This version has no typed delete, truncate, drop, user, role, grant, warehouse, task, stream, or pipe mutation. - SQL safety: use bind variables for all values. Identifiers are validated and quoted by typed operations.
execute_queryis prefix-allowlisted and rejects multiple statements; it is not a substitute for provider-side least privilege. - Authentication: OAuth, key-pair JWT, and PAT bearer tokens are supported. Password authentication and workflow-supplied tokens are intentionally unsupported.
- External verification: local tests verify validation, request construction, fixed-host routing, bindings, response mapping, retries, redaction, and metadata discovery. Live Snowflake authentication, network policies, privileges, query execution, partition compression, and warehouse behavior require separately authorized provider credentials and are not exercised in repository tests.
- Deferred operations: bulk array binding, staged file load/unload, PUT/GET, multi-statement transactions, stored procedure result sets, Arrow results, automatic partition fan-out, query history, and administrative object lifecycle.
- Functional references: n8n Snowflake node source, Snowflake SQL API reference, and Snowflake authentication.