Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
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>
Comment on lines +5 to +7
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add a title to the caution aside

Line 5 uses <Aside type="caution"> without a title. Add one to keep component usage consistent and accessible.

Suggested fix
-<Aside type="caution">
+<Aside type="caution" title="Verification required">
   Google applications using scopes that permit access to user contact data must complete a verification process before going to production.
 </Aside>

As per coding guidelines, “Use <Aside> component with a title attribute for cautions, tips, and notes.”

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/templates/agent-connectors/_setup-googlecontacts.mdx` around
lines 5 - 7, The <Aside> component instance using type="caution" is missing a
title attribute; update the <Aside type="caution"> element in
_setup-googlecontacts.mdx to include a descriptive title (e.g., title="Caution")
so the component usage is consistent and accessible, ensuring the title text
conveys the warning about Google app verification and follows the project's
wording/style guidelines.


<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`.

![](@/assets/docs/agent-connectors/googlecontacts/use-own-credentials-redirect-uri.png)

- 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.

![](@/assets/docs/agent-connectors/googlecontacts/oauth-web-app.png)

- Under **Authorized redirect URIs**, click **+ Add URI**, paste the redirect URI, and click **Create**.

![](@/assets/docs/agent-connectors/googlecontacts/add-redirect-uri.png)

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**.

![](@/assets/docs/agent-connectors/googlecontacts/enable-people-api.png)

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**.

![](@/assets/docs/agent-connectors/googlecontacts/add-credentials.png)

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>
165 changes: 165 additions & 0 deletions src/components/templates/agent-connectors/_usage-googlecontacts.mdx
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.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Use full tool names in the caution text for consistency and copy/paste safety.

contact_get and group_get do not match the connector’s actual tool names used elsewhere on this page. Use googlecontacts_contact_get and googlecontacts_group_get to avoid confusion.

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
Verify each finding against the current code and only fix it if needed.

In `@src/components/templates/agent-connectors/_usage-googlecontacts.mdx` at line
164, Update the caution text to reference the connector's actual tool names:
replace occurrences of contact_get and group_get with googlecontacts_contact_get
and googlecontacts_group_get so the guidance consistently instructs users to use
the etag from the most recent googlecontacts_contact_get or
googlecontacts_group_get response; ensure the wording remains a caution about
stale etags causing API rejects and that both full tool names appear exactly as
used elsewhere in the connector docs.

</Aside>
2 changes: 2 additions & 0 deletions src/components/templates/agent-connectors/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export { default as SetupGoogleFormsSection } from './_setup-google-forms.mdx'
export { default as SetupGoogleMeetsSection } from './_setup-google-meets.mdx'
export { default as SetupGoogleSheetsSection } from './_setup-google-sheets.mdx'
export { default as SetupGooglecalendarSection } from './_setup-googlecalendar.mdx'
export { default as SetupGooglecontactsSection } from './_setup-googlecontacts.mdx'
export { default as SetupGoogleslidesSection } from './_setup-googleslides.mdx'
export { default as SetupHarvestapiSection } from './_setup-harvestapi.mdx'
export { default as SetupHeyreachSection } from './_setup-heyreach.mdx'
Expand Down Expand Up @@ -92,6 +93,7 @@ export { default as UsageGmailSection } from './_usage-gmail.mdx'
export { default as UsageGongSection } from './_usage-gong.mdx'
export { default as UsageGoogleAdsSection } from './_usage-google_ads.mdx'
export { default as UsageGooglecalendarSection } from './_usage-googlecalendar.mdx'
export { default as UsageGooglecontactsSection } from './_usage-googlecontacts.mdx'
export { default as UsageGoogledocsSection } from './_usage-googledocs.mdx'
export { default as UsageGoogledriveSection } from './_usage-googledrive.mdx'
export { default as UsageGoogleformsSection } from './_usage-googleforms.mdx'
Expand Down
65 changes: 65 additions & 0 deletions src/content/docs/agentkit/connectors/googlecontacts.mdx
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
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add required frontmatter metadata

Line 1–13 is missing description and sidebar.label, which are required for docs pages in this path.

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: title (≤60 chars), description (≤160 chars), and sidebar.label (1-3 words).”

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/content/docs/agentkit/connectors/googlecontacts.mdx` around lines 1 - 13,
The frontmatter for the Google Contacts doc (the YAML block starting with title:
Google Contacts) is missing the required description and sidebar.label fields;
update that frontmatter to include a concise description (≤160 characters) and a
sidebar.label of 1–3 words (and ensure title remains ≤60 chars), e.g., add
description: "..." and sidebar.label: "Google Contacts" near the top of the
existing frontmatter so the page meets the documentation guidelines.


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} />
Loading