Skip to main content

Google Contacts ExecModule

Overview

GoogleContactsModule connects ValkyrAI workflows to Google People API v1. It uses the native map I/O ExecModule ABI, appears in the annotation-backed Workflow Studio catalog as GoogleContactsModule, and resolves OAuth credentials only from an IntegrationAccount.

The connector implements the highest-value contact behavior from n8n's Google Contacts node and adds bounded contact-group discovery:

  • list_contacts
  • search_contacts
  • get_contact
  • create_contact
  • update_contact
  • delete_contact
  • list_contact_groups
  • get_contact_group

The Google People API origin and OAuth token cannot be overridden by workflow input.

Usage

  1. Enable Google People API in the Google Cloud project that owns the OAuth client.
  2. Authorize the minimum Contacts OAuth scope required by the workflow.
  3. Store the current OAuth access token in a Google IntegrationAccount SecureField and keep the account in READY status.
  4. Add GoogleContactsModule to a workflow and bind that account through ExecModuleConfig.authConfig.integrationAccount.
  5. Set operation and the operation-specific fields in module configuration or map them from upstream workflow state.

Mapped workflow input can override non-secret contact fields. Authentication, the Google API host, field allowlist, retry safety, response limits, etag enforcement, and destructive confirmation remain trusted module behavior.

Inputs

NameTypeRequired forDefaultConstraints
operationstringEvery executionNoneOne of the eight documented operations.
contactIdstringget_contact, update_contact, delete_contactNoneBare Google person ID or people/<id>; 1–256 ID characters.
contactGroupIdstringget_contact_groupNoneBare group ID or contactGroups/<id>.
querystringsearch_contactsNone1–256 characters.
personFieldsstringRead/list/search operationsnames,emailAddresses,phoneNumbers,organizations,membershipsComma-separated values from the module's People API field allowlist.
givenName / familyNamestringAt least one for create_contact; optional for updateNoneEach supplied value is at most 256 characters. Empty update values clear names when both are empty.
emailstringOptional create/update fieldNoneValid address, at most 320 characters; an empty update clears email addresses.
emailTypestringWhen email is non-emptyworkhome, work, or other.
phonestringOptional create/update fieldNone3–64 phone characters; an empty update clears phone numbers.
phoneTypestringWhen phone is non-emptymobilehome, work, mobile, main, or other.
organizationName / jobTitlestringOptional create/update fieldsNoneEach supplied value is at most 512 characters; empty values can clear organization data.
notesstringOptional create/update fieldNonePlain text up to 8,192 characters; an empty update clears biographies.
etagstringupdate_contactNoneRequired optimistic-concurrency token from a prior read.
pageTokenstringOptional list resume pointNoneOpaque; maximum 4,096 characters.
limitintegerOptional list/group bound1001–10,000; contact searches use provider pages of at most 30.
returnAllbooleanOptional list behaviorfalseContinues pagination, safety-capped at 10,000 items.
warmupCachebooleanOptional search_contacts behaviortruePerforms the Google-recommended empty-query cache warmup before search.
confirmDeletebooleandelete_contactfalseMust be true because deletion is permanent.

Outputs

Every execution returns stable status, operation, and attempts fields.

NameTypeWhen presentDescription
statusstringAlwayssuccess or error.
operationstringAlwaysNormalized operation name.
attemptsintegerAlwaysProvider HTTP attempts.
httpStatusintegerProvider response receivedLast Google People HTTP status.
dataobjectSingle-resource or mutation successNormalized Google person/group response; empty for HTTP 204.
resourceNamestringProvider resource contains oneCanonical people/<id> or contactGroups/<id> name.
contactIdstringPerson resource contains resourceNameConvenience person ID without the people/ prefix.
etagstringProvider resource contains oneConcurrency token for a later update.
itemsarrayList/search successBounded contacts or contact groups. Search result wrappers are normalized to person objects.
countintegerList/search successNumber of returned items.
hasMorebooleanList/search successWhether Google returned another page token.
nextPageTokenstringAnother page existsOpaque token for a later execution.
requestIdstringGoogle supplies oneProvider request reference for support.
errorobjectFailureSafe {code, message, httpStatus?, retryable} details.

OAuth tokens are never returned. Provider errors are bounded and redacted through the shared workflow sensitive-data policy.

IntegrationAccount Requirements

SettingRequirement
ProviderGoogle Contacts / Google Workspace
Auth mechanismOAuth 2.0 bearer access token
accountNameHuman-readable Google account or Workspace label
apiKeyPreferred encrypted SecureField containing the access token
passwordLegacy token fallback only; prefer apiKey
statusMust be READY; all other states fail closed

Use the minimum applicable scope:

See Google People API authorization. Never place tokens in parameters, mapped workflow input, examples, logs, or outputs. Use the platform OAuth refresh flow to rotate expired access tokens.

Configuration

Module-specific fields belong in ExecModulePayloadConfig.parameters; retries and timeouts use existing normalized configuration groups.

{
"version": "1.0.0",
"authConfig": {
"authStrategy": 1,
"integrationAccount": "integration-account:google-contacts-primary"
},
"retryPolicy": {
"maxAttempts": 3,
"backoffStrategy": "EXPONENTIAL",
"initialDelayMs": 1000,
"maxDelayMs": 60000,
"jitter": false
},
"executionConfig": {
"timeoutMs": 30000
},
"payloadConfig": {
"parameters": "{\"operation\":\"search_contacts\",\"query\":\"avery@example.com\",\"limit\":30}"
}
}

The integrationAccount value is illustrative. Persisted workflows use the generated relationship, never a plaintext token.

Operations

OperationProvider behaviorSide effect and retry behavior
list_contactsLists the authorized principal's contacts, sorted by recent modification.Read-only; retries transient failures and paginates.
search_contactsWarms the search cache, searches contacts, and unwraps result persons.Read-only; retries transient failures; each provider page is at most 30.
get_contactReads one person with allowlisted fields.Read-only; retries transient failures.
create_contactCreates a person with typed name, email, phone, organization, title, and notes.Write; single attempt because an ambiguous response may have committed.
update_contactPatches only supplied field families and requires the current etag.Write; single attempt; empty supplied fields can clear provider arrays.
delete_contactPermanently deletes one contact.Irreversible; requires confirmDelete=true; single attempt.
list_contact_groupsLists visible contact groups with name, type, and member count.Read-only; retries transient failures and paginates.
get_contact_groupReads one group and a bounded member list.Read-only; retries transient failures.

Errors and Failure Modes

CodeTypical causeRetryableResolution
VALIDATION_ERRORMissing/invalid ID, search text, field mask, email, phone, etag, mutable field, or confirmation.NoCorrect inputs; no unsafe request was sent.
UNSUPPORTED_OPERATIONUnknown operation name.NoSelect a documented operation.
INTEGRATION_ACCOUNT_REQUIREDNo account is bound.NoBind a Google Contacts IntegrationAccount.
INTEGRATION_ACCOUNT_NOT_READYAccount status is not READY.NoReconnect or repair the account.
GOOGLE_CONTACTS_HTTP_401OAuth token is expired or invalid.NoRefresh the token.
GOOGLE_CONTACTS_HTTP_403Scope/resource access is missing, or a quota was exceeded.Depends on reasonGrant scope/access; rate-limit reasons retry only for reads.
GOOGLE_CONTACTS_HTTP_404Person or group ID is wrong or invisible.NoVerify the resource ID and authorized principal.
GOOGLE_CONTACTS_HTTP_409The supplied etag is stale or the provider detected a write conflict.NoRead the contact again, reconcile, and intentionally retry.
GOOGLE_CONTACTS_HTTP_429Request quota exceeded.Yes for readsHonor provider guidance and retry later.
RESPONSE_TOO_LARGEResponse exceeded 5 MiB.NoNarrow fields/query or lower limit.
NETWORK_ERRORDNS, TLS, timeout, or connectivity failure.Yes for readsVerify connectivity and retry.
INVALID_PROVIDER_RESPONSEGoogle returned a non-list collection field.NoCapture request ID and check API compatibility.

Example

Create an approved deal contact:

{
"operation": "create_contact",
"givenName": "Avery",
"familyName": "Chen",
"email": "avery@example.com",
"emailType": "work",
"phone": "+1 415 555 0100",
"phoneType": "mobile",
"organizationName": "Example Co",
"jobTitle": "VP Operations",
"notes": "Approved opportunity contact; follow up after the discovery call."
}

Expected result shape:

{
"status": "success",
"operation": "create_contact",
"attempts": 1,
"httpStatus": 200,
"resourceName": "people/c123_contact",
"contactId": "c123_contact",
"etag": "provider-etag",
"data": {
"resourceName": "people/c123_contact",
"contactId": "c123_contact",
"etag": "provider-etag"
}
}

Notes

  • Pagination: contact and group lists request at most 1,000 items per Google page; search requests at most 30. Opaque nextPageToken values are preserved, and returnAll is hard-capped at 10,000 items.
  • Rate limits: read operations retry HTTP 408/429/5xx and Google rateLimitExceeded, userRateLimitExceeded, or backendError reasons. Integer and RFC 1123 Retry-After values are honored. Writes are never automatically retried.
  • API limits: the module covers contacts and contact-group discovery, not directory profiles, other contacts, photos, batch mutations, or delegated domain-wide administration. personFields is allowlisted to prevent arbitrary field-mask injection.
  • Idempotency: create, update, and delete use one provider attempt. After a timeout, search/read by immutable resourceName and reconcile before replaying.
  • Concurrency: update_contact requires the current provider etag and sends an explicit updatePersonFields mask. A stale etag must be reconciled instead of overwritten.
  • Destructive behavior: delete_contact is permanent and requires confirmDelete=true; automatic retries are disabled.
  • Search cache: Google People search may need a warmup request. warmupCache=true follows the behavior used by n8n's Google Contacts node.
  • External verification: local tests use a deterministic mock provider. Live Google behavior remains unverified until an authorized Google Contacts credential is supplied.
  • Functional reference: n8n's current Google Contacts node supports create, delete, get, get-many/search, and update, including People API field masks, pagination, contact groups, etags, and cache warmup. ValkyrAI adds strict field allowlisting, bounded responses, explicit destructive confirmation, and read-only retry boundaries.