Google Sheets ExecModule
Overview
GoogleSheetsModule connects ValkyrAI workflows to the Google Sheets API v4 through the native map I/O ExecModule ABI. Workflow Studio discovers it as GoogleSheetsModule; the OAuth access token comes only from an encrypted IntegrationAccount.
The initial release provides eleven spreadsheet, range, and tab operations:
get_spreadsheet,create_spreadsheetget_values,append_values,update_values,clear_valuesbatch_update_values,batch_clear_valuescreate_sheet,update_sheet,delete_sheet
Reads use bounded responses and are eligible for policy-controlled transient retries. Writes run once so an ambiguous timeout cannot repeat an append, create, clear, or delete operation. The module accepts standard A1 notation and limits each value request to 10,000 scalar cells.
Usage
- Enable the Google Sheets API in the Google Cloud project that owns the integration.
- Create an OAuth client or service-account exchange appropriate for the target workspace.
- Grant only the Google Sheets scopes required by the workflow.
- Store the resulting access token in the encrypted
apiKeyfield of anIntegrationAccount. - Bind that account through
ExecModuleConfig.authConfig.integrationAccount. - Add
GoogleSheetsModuleto a workflow, select an operation, and provide the spreadsheet ID and operation-specific range, values, or tab fields.
Workflow inputs can select resources, A1 ranges, value interpretation, render options, and bounded cell data. They cannot supply credentials or redirect requests away from the trusted Google Sheets API origin.
Inputs
| Name | Type | Requirement | Default | Description | Constraints |
|---|---|---|---|---|---|
operation | string | Required | None | Operation to execute. | One of the eleven operations above. |
spreadsheetId | string | Required except create | None | Google spreadsheet identifier. | 10–256 URL-safe ID characters. |
range | string | Range operations | None | A1 notation such as Leads!A:E. | 1–500 characters; quote tab names containing spaces. |
values | array | Append/update | None | Two-dimensional cell values. | Maximum 10,000 scalar cells and 1 MiB request body. |
data | array | Batch update | None | Objects containing range and values. | 1–100 ranges; 10,000 cells total. |
ranges | array | Batch clear | None | A1 ranges to clear. | 1–100 ranges. |
sheetId | integer | Tab update/delete | None | Numeric sheet/tab identifier. | 0–2,147,483,647. |
title | string | Create/update | None | Spreadsheet or tab title. | 1–100 characters. |
sheetTitles | array | Optional create | None | Initial tabs for a spreadsheet. | 1–100 titles. |
majorDimension | enum | Optional | ROWS | Row- or column-oriented values. | ROWS or COLUMNS. |
valueInputOption | enum | Optional writes | USER_ENTERED | How Google interprets values. | RAW or USER_ENTERED. |
valueRenderOption | enum | Optional reads | UNFORMATTED_VALUE | How returned cells are rendered. | FORMATTED_VALUE, UNFORMATTED_VALUE, or FORMULA. |
dateTimeRenderOption | enum | Optional reads | SERIAL_NUMBER | How returned dates are rendered. | SERIAL_NUMBER or FORMATTED_STRING. |
insertDataOption | enum | Optional append | INSERT_ROWS | Append placement behavior. | INSERT_ROWS or OVERWRITE. |
includeGridData | boolean | Optional metadata read | false | Include grid values in get_spreadsheet. | Responses remain capped at 5 MiB. |
locale | string | Optional create | en_US | Spreadsheet locale. | Language or language-country code. |
autoRecalc | enum | Optional create | ON_CHANGE | Volatile formula recalculation interval. | ON_CHANGE, MINUTE, or HOUR. |
hidden | boolean | Optional tab write | false | Hide a created or updated tab. | Explicit update field only. |
rightToLeft | boolean | Optional tab write | false | Use right-to-left tab layout. | Explicit update field only. |
confirmDelete | boolean | Required for deletion | false | Permanent-delete acknowledgement. | Must be true for delete_sheet. |
Cell values may be strings, numbers, booleans, or null. Nested objects and arrays are rejected before any request is sent. A single text cell may contain at most 50,000 characters.
Outputs
| Name | Type | When present | Description |
|---|---|---|---|
status | string | Always | success or error. |
operation | string | Always | Normalized operation name. |
attempts | integer | Always | Google API attempts consumed. |
httpStatus | integer | Provider response received | Last HTTP status. |
data | object | Success | Bounded normalized Google response. |
spreadsheetId | string | Response includes it | Spreadsheet identifier. |
values, rowCount | array, integer | get_values success | Returned cells and top-level row/column count. |
updatedRange | string | Value write success | Range changed by Google. |
updatedRows, updatedColumns, updatedCells | integer | Value write success | Provider-reported mutation counts. |
requestId | string | Provider supplies one | Google correlation identifier. |
error | object | Failure | Safe {code, message, httpStatus?, retryable} details. |
OAuth tokens and authorization headers never enter outputs. Provider messages pass through the shared workflow sensitive-data policy and explicit token redaction.
IntegrationAccount Requirements
| Setting | Google Sheets requirement |
|---|---|
| Provider | Google OAuth 2.0 or a service account with shared spreadsheet access |
| Authentication | OAuth bearer access token |
accountName | Human-readable Google identity or automation label |
apiKey | Preferred encrypted SecureField containing the current access token |
password | Legacy token fallback only; prefer apiKey |
status | ready or unset legacy status; closed and error fail closed |
Use https://www.googleapis.com/auth/spreadsheets.readonly for read-only workflows. Use https://www.googleapis.com/auth/spreadsheets only when value or sheet mutations are required. A service account must be granted access to the target spreadsheet and its short-lived bearer token must be minted before execution. Token refresh happens in the integration layer; workflow payloads cannot replace credentials.
Configuration
{
"version": "1.0.0",
"authConfig": {
"authStrategy": 1,
"integrationAccount": "integration-account:google-revenue-ops"
},
"retryPolicy": {
"maxAttempts": 3,
"backoffStrategy": "EXPONENTIAL",
"initialDelayMs": 1000,
"maxDelayMs": 60000,
"jitter": false
},
"executionConfig": {"timeoutMs": 30000},
"payloadConfig": {
"parameters": "{\"operation\":\"get_values\",\"spreadsheetId\":\"1AbCdEf...\",\"range\":\"Pipeline!A2:G500\",\"valueRenderOption\":\"UNFORMATTED_VALUE\"}"
}
}
The integration account value is symbolic. Persisted workflows use the generated relationship, never a plaintext token.
Operations
| Operation | Google Sheets behavior | Side effect |
|---|---|---|
get_spreadsheet | Reads spreadsheet properties and tab metadata; optionally includes bounded grid data. | Read-only; safe retries. |
create_spreadsheet | Creates one spreadsheet with optional initial tab titles, locale, and recalculation policy. | New spreadsheet; single attempt. |
get_values | Reads one A1 range with explicit value/date rendering. | Read-only; safe retries. |
append_values | Appends values to the provider-detected table in an A1 range. | Adds cells/rows; single attempt. |
update_values | Replaces values in the specified A1 range. | Mutates cells; single attempt. |
clear_values | Clears values while preserving formatting and validation. | Destructive cell mutation; single attempt. |
batch_update_values | Updates up to 100 ranges and 10,000 cells in one request. | Mutates cells; single attempt. |
batch_clear_values | Clears up to 100 A1 ranges in one request. | Destructive cell mutation; single attempt. |
create_sheet | Adds one tab with optional hidden or right-to-left settings. | New tab; single attempt. |
update_sheet | Renames a tab or changes hidden/right-to-left properties. | Tab metadata mutation; single attempt. |
delete_sheet | Permanently deletes one tab by numeric sheetId. | Irreversible; confirmation required. |
Errors and Failure Modes
| Code | Typical cause | Retryable | Resolution |
|---|---|---|---|
VALIDATION_ERROR | Missing/invalid ID, range, title, value shape, enum, scope field, or delete confirmation. | No | Correct the input; no unsafe request was sent. |
UNSUPPORTED_OPERATION | Unknown operation. | No | Select a documented operation. |
INTEGRATION_ACCOUNT_REQUIRED | No account bound. | No | Bind a Google Sheets IntegrationAccount. |
INTEGRATION_ACCOUNT_NOT_READY | Account status is closed/error. | No | Repair or reconnect the account. |
CREDENTIAL_MISSING | Bound account lacks an access token. | No | Refresh the OAuth integration. |
authError, HTTP 401/403 | Token, sharing, or scope is insufficient. | No | Verify the identity, spreadsheet share, and least-privilege scopes. |
rateLimitExceeded, userRateLimitExceeded | Google quota is exhausted. | Yes for reads | Honor backoff and reduce read frequency or range size. |
GOOGLE_SHEETS_HTTP_429, 5xx | Transient provider failure. | Yes for reads | Retry reads; reconcile writes before repeating. |
NETWORK_ERROR | Timeout, DNS, TLS, or connectivity failure. | Yes for reads | Verify connectivity and inspect writes before retry. |
PAYLOAD_TOO_LARGE | JSON request exceeded 1 MiB. | No | Split values into smaller ranges or workflow steps. |
RESPONSE_TOO_LARGE | Response exceeded 5 MiB. | No | Narrow the A1 range or disable includeGridData. |
Example
Append one qualified pipeline row:
{
"operation": "append_values",
"spreadsheetId": "1AbCdEfGhIjKlMnOpQrStUvWxYz",
"range": "Pipeline!A:G",
"valueInputOption": "USER_ENTERED",
"insertDataOption": "INSERT_ROWS",
"values": [
["Acme Manufacturing", "Dana Rivera", "VP Operations", "qualified", 42000, "2026-08-14", "owner:john"]
]
}
Expected result:
{
"status": "success",
"operation": "append_values",
"attempts": 1,
"httpStatus": 200,
"spreadsheetId": "1AbCdEfGhIjKlMnOpQrStUvWxYz",
"updatedRange": "Pipeline!A42:G42",
"updatedRows": 1,
"updatedColumns": 7,
"updatedCells": 7
}
Notes
- Pagination: the Google Sheets values endpoints do not expose page tokens. Bound reads with precise A1 ranges; the module rejects responses over 5 MiB. Split large sheets into deterministic ranges across workflow steps.
- Rate limits: only
get_spreadsheetandget_valuesretry HTTP 408, 429, 500, 502, 503, 504 and Google rate-limit/backend reasons according to the workflow retry policy. - API limits: value requests allow at most 10,000 scalar cells, 100 batch ranges, a 1 MiB request body, and a 5 MiB response. Google may impose additional per-project and per-user quotas.
- Idempotency: reads are idempotent. Writes are single-attempt. Use a durable business key and
get_valuesreconciliation before repeating an ambiguous append or create. - Value interpretation:
USER_ENTEREDcan parse formulas, dates, and locale-specific numbers. UseRAWwhen exact string or numeric preservation matters. - Destructive behavior:
clear_valuesandbatch_clear_valuesremove cell contents without confirmation.delete_sheetpermanently removes an entire tab and requiresconfirmDelete=true. - Security: formulas beginning with
=are evaluated when usingUSER_ENTERED. Treat untrusted spreadsheet values as data, useRAWwhere appropriate, and sanitize downstream CSV/export consumers against formula injection. - Privacy: spreadsheets commonly contain customer and revenue data. Apply downstream minimization, retention, ACL, and audit rules.
- Authentication: OAuth tokens remain in IntegrationAccount SecureFields and are redacted from errors and outputs.
- External verification: request construction, value normalization, bounds, rate-limit retry, mutation safety, redaction, and metadata discovery are tested locally. Live Google Workspace sharing and quotas require real provider credentials and are deferred.
- Deferred operations: named ranges, filters, charts, pivot tables, formatting, protected ranges, developer metadata, comments, Drive file deletion, triggers, and arbitrary raw batch-update requests.
- Functional reference: n8n's Google Sheets node models document creation/deletion plus append-or-update, append, clear, create/delete tab, delete dimensions, get rows, and update row workflows. This module carries the highest-value spreadsheet and tab semantics into ValkyrAI's secure native ABI while deliberately bounding cells, ranges, response size, retries, and destructive actions.