-
Notifications
You must be signed in to change notification settings - Fork 10
Add Google Contacts connector docs #637
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,79 @@ | ||
| import { Steps, Aside, Tabs, TabItem } from '@astrojs/starlight/components' | ||
|
|
||
| Register your Scalekit environment with the Google Contacts connector so Scalekit handles the OAuth 2.0 flow and token lifecycle for you. The connection name you create is used to identify and invoke the connection in your code. | ||
|
|
||
| <Aside type="caution"> | ||
| Google applications using scopes that permit access to user contact data must complete a verification process before going to production. | ||
| </Aside> | ||
|
|
||
| <Steps> | ||
| 1. ## Set up auth redirects | ||
|
|
||
| - In [Scalekit dashboard](https://app.scalekit.com), go to **AgentKit** > **Connections** > **Create Connection**. Find **Google Contacts** and click **Create**. Click **Use your own credentials** and copy the redirect URI — it looks like `https://<SCALEKIT_ENVIRONMENT_URL>/sso/v1/oauth/<CONNECTION_ID>/callback`. | ||
|
|
||
|  | ||
|
|
||
| - Navigate to [Google Cloud Console](https://console.cloud.google.com/projectselector2/home/dashboard) → **APIs & Services** → **Credentials**. Select **+ Create Credentials**, then **OAuth client ID**. Choose **Web application** from the Application type menu. | ||
|
|
||
|  | ||
|
|
||
| - Under **Authorized redirect URIs**, click **+ Add URI**, paste the redirect URI, and click **Create**. | ||
|
|
||
|  | ||
|
|
||
| 2. ## Enable the People API | ||
|
|
||
| - In [Google Cloud Console](https://console.cloud.google.com/projectselector2/home/dashboard), go to **APIs & Services** → **Library**. Search for **People API** and click **Enable**. | ||
|
|
||
|  | ||
|
|
||
| 3. ## Get client credentials | ||
|
|
||
| - Google provides your **Client ID** and **Client Secret** after you create the OAuth client ID in step 1. Copy both values from the credentials detail panel. | ||
|
|
||
| 4. ## Add credentials in Scalekit | ||
|
|
||
| - In [Scalekit dashboard](https://app.scalekit.com), go to **AgentKit** > **Connections** and open the connection you created. | ||
|
|
||
| - Enter your Google **Client ID** and **Client Secret**, then click **Save**. | ||
|
|
||
|  | ||
|
|
||
| 5. ## Connect a user account | ||
|
|
||
| Your users must authorize access to their Google Contacts. Generate an authorization link and direct them through the OAuth flow. | ||
|
|
||
| **Via dashboard (for testing)** | ||
|
|
||
| - Open the connection and click the **Connected Accounts** tab → **Add Account**. | ||
| - Fill in **Your User's ID** (e.g. `user_123`) and follow the Google OAuth prompt. | ||
|
|
||
| **Via API (for production)** | ||
|
|
||
| <Tabs syncKey="tech-stack"> | ||
| <TabItem label="Node.js"> | ||
| ```typescript | ||
| const { link } = await scalekit.actions.getAuthorizationLink({ | ||
| connectionName: 'googlecontacts', | ||
| identifier: 'user_123', | ||
| }); | ||
| // Redirect your user to `link` — they complete OAuth on Google's side | ||
| console.log('Authorize Google Contacts:', link); | ||
| ``` | ||
| </TabItem> | ||
| <TabItem label="Python"> | ||
| ```python | ||
| link_response = scalekit_client.actions.get_authorization_link( | ||
| connection_name="googlecontacts", | ||
| identifier="user_123" | ||
| ) | ||
| # Redirect your user to link_response.link | ||
| print("Authorize Google Contacts:", link_response.link) | ||
| ``` | ||
| </TabItem> | ||
| </Tabs> | ||
|
|
||
| <Aside type="tip" title="Production usage tip"> | ||
| In production, generate the authorization link when a user wants to connect their Google Contacts account. After they complete the OAuth flow, Scalekit stores and automatically refreshes their tokens. | ||
| </Aside> | ||
| </Steps> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,165 @@ | ||
| import { Tabs, TabItem, Aside } from '@astrojs/starlight/components' | ||
|
|
||
| Once a connected account is set up, make API calls through the Scalekit proxy or call Google Contacts tools directly via `execute_tool`. | ||
|
|
||
| ## Proxy API calls | ||
|
|
||
| <Tabs syncKey="tech-stack"> | ||
| <TabItem label="Node.js"> | ||
| ```typescript | ||
| import { ScalekitClient } from '@scalekit-sdk/node'; | ||
|
|
||
| const scalekit = new ScalekitClient( | ||
| process.env.SCALEKIT_ENV_URL, | ||
| process.env.SCALEKIT_CLIENT_ID, | ||
| process.env.SCALEKIT_CLIENT_SECRET | ||
| ); | ||
| const actions = scalekit.actions; | ||
|
|
||
| // List contacts | ||
| const result = await actions.request({ | ||
| connectionName: 'googlecontacts', | ||
| identifier: 'user_123', | ||
| path: '/v1/people/me/connections', | ||
| method: 'GET', | ||
| query: { personFields: 'names,emailAddresses,phoneNumbers' }, | ||
| }); | ||
| console.log(result); | ||
| ``` | ||
| </TabItem> | ||
| <TabItem label="Python"> | ||
| ```python | ||
| import scalekit.client, os | ||
| from dotenv import load_dotenv | ||
| load_dotenv() | ||
|
|
||
| scalekit_client = scalekit.client.ScalekitClient( | ||
| client_id=os.getenv("SCALEKIT_CLIENT_ID"), | ||
| client_secret=os.getenv("SCALEKIT_CLIENT_SECRET"), | ||
| env_url=os.getenv("SCALEKIT_ENV_URL"), | ||
| ) | ||
| actions = scalekit_client.actions | ||
|
|
||
| # List contacts | ||
| result = actions.request( | ||
| connection_name="googlecontacts", | ||
| identifier="user_123", | ||
| path="/v1/people/me/connections", | ||
| method="GET", | ||
| query={"personFields": "names,emailAddresses,phoneNumbers"}, | ||
| ) | ||
| print(result) | ||
| ``` | ||
| </TabItem> | ||
| </Tabs> | ||
|
|
||
| ## Execute tools | ||
|
|
||
| Use `execute_tool` to call Google Contacts tools directly from your agent. | ||
|
|
||
| ### List contacts | ||
|
|
||
| ```python | ||
| connected_account = scalekit_client.connect.get_or_create_connected_account( | ||
| connection_name="googlecontacts", | ||
| identifier="user_123" | ||
| ).connected_account | ||
|
|
||
| contacts = actions.execute_tool( | ||
| tool_name="googlecontacts_contacts_list", | ||
| connected_account_id=connected_account.id, | ||
| tool_input={ | ||
| "person_fields": "names,emailAddresses,phoneNumbers", | ||
| "page_size": 10, | ||
| } | ||
| ) | ||
| ``` | ||
|
|
||
| ### Create a contact | ||
|
|
||
| ```python | ||
| new_contact = actions.execute_tool( | ||
| tool_name="googlecontacts_contact_create", | ||
| connected_account_id=connected_account.id, | ||
| tool_input={ | ||
| "given_name": "Jane", | ||
| "family_name": "Doe", | ||
| "email": "jane.doe@example.com", | ||
| "phone": "+1234567890", | ||
| "person_fields": "names,emailAddresses,phoneNumbers", | ||
| } | ||
| ) | ||
| person_id = new_contact["resourceName"].split("/")[1] | ||
| ``` | ||
|
|
||
| ### Search contacts | ||
|
|
||
| ```python | ||
| results = actions.execute_tool( | ||
| tool_name="googlecontacts_contacts_search", | ||
| connected_account_id=connected_account.id, | ||
| tool_input={ | ||
| "query": "Jane", | ||
| "read_mask": "names,emailAddresses", | ||
| } | ||
| ) | ||
| ``` | ||
|
|
||
| ### Create a group and add a member | ||
|
|
||
| ```python | ||
| group = actions.execute_tool( | ||
| tool_name="googlecontacts_group_create", | ||
| connected_account_id=connected_account.id, | ||
| tool_input={"name": "VIP Customers"} | ||
| ) | ||
| group_id = group["resourceName"].split("/")[1] | ||
|
|
||
| actions.execute_tool( | ||
| tool_name="googlecontacts_group_members_modify", | ||
| connected_account_id=connected_account.id, | ||
| tool_input={ | ||
| "group_id": group_id, | ||
| "resource_names_to_add": [f"people/{person_id}"], | ||
| } | ||
| ) | ||
| ``` | ||
|
|
||
| <Aside type="tip" title="person_fields is required"> | ||
| Most read tools require a `person_fields` or `read_mask` parameter. Pass a comma-separated list such as `names,emailAddresses,phoneNumbers,organizations`. | ||
| </Aside> | ||
|
|
||
| ### Update a contact | ||
|
|
||
| `googlecontacts_contact_update` and `googlecontacts_group_update` require a current `etag`. Google uses the etag as optimistic concurrency control — if the resource was modified since you last read it, the update is rejected to prevent silent overwrites. | ||
|
|
||
| In agentic workflows, your agent will typically call `googlecontacts_contact_get` first to read the current state of the contact, and the etag from that response is passed directly into the update call. | ||
|
|
||
| ```python | ||
| # 1. Get contact — etag is included in the response | ||
| contact = actions.execute_tool( | ||
| tool_name="googlecontacts_contact_get", | ||
| connected_account_id=connected_account.id, | ||
| tool_input={ | ||
| "person_id": "c8901234567", | ||
| "person_fields": "names,emailAddresses", | ||
| } | ||
| ) | ||
|
|
||
| # 2. Pass the etag from the get response into the update | ||
| actions.execute_tool( | ||
| tool_name="googlecontacts_contact_update", | ||
| connected_account_id=connected_account.id, | ||
| tool_input={ | ||
| "person_id": "c8901234567", | ||
| "etag": contact["etag"], | ||
| "update_person_fields": "names", | ||
| "given_name": "Jane", | ||
| "family_name": "Smith", | ||
| } | ||
| ) | ||
| ``` | ||
|
|
||
| <Aside type="caution" title="Do not cache etags"> | ||
| Always use the etag from the most recent `contact_get` or `group_get` response. A stale etag causes the API to reject the update. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use full tool names in the caution text for consistency and copy/paste safety.
Suggested fix- Always use the etag from the most recent `contact_get` or `group_get` response. A stale etag causes the API to reject the update.
+ Always use the etag from the most recent `googlecontacts_contact_get` or `googlecontacts_group_get` response. A stale etag causes the API to reject the update.🤖 Prompt for AI Agents |
||
| </Aside> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| --- | ||
| title: Google Contacts | ||
| tableOfContents: true | ||
| connectorIcon: https://cdn.scalekit.com/sk-connect/assets/provider-icons/googlecontacts.svg | ||
| connectorAuthType: OAuth 2.0 | ||
| connectorCategories: [productivity] | ||
| head: | ||
| - tag: style | ||
| content: | | ||
| .sl-markdown-content h2 { | ||
| font-size: var(--sl-text-xl); | ||
| } | ||
| --- | ||
|
Comment on lines
+1
to
+13
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add required frontmatter metadata Line 1–13 is missing Suggested frontmatter update ---
title: Google Contacts
+description: Connect Google Contacts to your agent and use proxy APIs or tools for contacts, groups, and directory operations.
+sidebar:
+ label: Google Contacts
tableOfContents: true
connectorIcon: https://cdn.scalekit.com/sk-connect/assets/provider-icons/googlecontacts.svg
connectorAuthType: OAuth 2.0
connectorCategories: [productivity]As per coding guidelines, “Every documentation page must include frontmatter with at least: 🤖 Prompt for AI Agents |
||
|
|
||
| import ToolList from '@/components/ToolList.astro' | ||
| import { tools } from '@/data/agent-connectors/googlecontacts' | ||
| import { SetupGooglecontactsSection } from '@components/templates' | ||
| import { UsageGooglecontactsSection } from '@components/templates' | ||
|
|
||
| ## What you can do | ||
|
|
||
| Connect this agent connector to let your agent: | ||
|
|
||
| - **Manage contacts** — create, read, update, and delete contacts; batch create, update, and delete up to 200–500 contacts in a single request | ||
| - **Search contacts** — search across names, emails, and phone numbers in the main contacts list or "Other contacts" | ||
| - **Handle contact groups** — create, update, delete, and modify membership of contact groups | ||
| - **Work with other contacts** — list and search auto-generated contacts from email history, and copy them into the main contacts list | ||
| - **Access directory** — list and search people in a Google Workspace domain directory (requires Workspace account) | ||
| - **Manage photos** — upload or remove contact profile photos | ||
|
|
||
| ## Authentication | ||
|
|
||
| This connector uses **OAuth 2.0**. Scalekit acts as the OAuth client: it redirects your user to Google, obtains an access token, and automatically refreshes it before it expires. Your agent code never handles tokens directly — you only pass a `connectionName` and a user `identifier`. | ||
|
|
||
| You supply your Google **OAuth app credentials** (Client ID + Secret) once per environment in the Scalekit dashboard. | ||
|
|
||
| <details> | ||
| <summary>Set up the connector</summary> | ||
|
|
||
| <SetupGooglecontactsSection /> | ||
|
|
||
| </details> | ||
|
|
||
| <details> | ||
| <summary>Code examples</summary> | ||
|
|
||
| <UsageGooglecontactsSection /> | ||
|
|
||
| </details> | ||
|
|
||
| ## Getting resource IDs | ||
|
|
||
| Most tools require IDs that must be fetched from the API — never guess or hard-code them. | ||
|
|
||
| | Resource | Tool to get ID | Field in response | | ||
| |----------|---------------|-------------------| | ||
| | Person ID | `googlecontacts_contacts_list` | `connections[].resourceName` (part after `people/`) | | ||
| | Contact etag | `googlecontacts_contact_get` | `etag` | | ||
| | Group ID | `googlecontacts_groups_list` | `contactGroups[].resourceName` (part after `contactGroups/`) | | ||
| | Group etag | `googlecontacts_group_get` | `etag` | | ||
| | Other contact person ID | `googlecontacts_other_contacts_list` | `otherContacts[].resourceName` (part after `people/`) | | ||
|
|
||
| ## Tool list | ||
|
|
||
| <ToolList tools={tools} /> | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a
titleto the caution asideLine 5 uses
<Aside type="caution">without atitle. Add one to keep component usage consistent and accessible.Suggested fix
As per coding guidelines, “Use
<Aside>component with atitleattribute for cautions, tips, and notes.”🤖 Prompt for AI Agents