This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated. # Releases ## @chat-adapter/discord@4.35.0 ### Minor Changes -26c0522: Add an opt-in channel allowlist for treating non-bot Discord messages as directed to the bot without requiring a mention. Configure via `respondToChannelIds` or the `DISCORD_RESPOND_TO_CHANNEL_IDS` env var (comma-separated). ### Patch Changes -b605cf6: Preserve Discord's angle-bracket syntax for suppressing link previews when rendering markdown. - Updated dependencies [80def3a] - Updated dependencies [4cb7e5d] - Updated dependencies [46681f5] - Updated dependencies [93a58af] - Updated dependencies [25f3099] - chat@4.35.0 - @chat-adapter/shared@4.35.0 ## @chat-adapter/slack@4.35.0 ### Minor Changes -bb7cd12: Expose sender email addresses on normalized incoming Slack message authors. `message.author.email` is populated from the same cached `users.info` lookup used for display names and requires the `users:read.email` scope; without it the field stays undefined. -907450d: Enterprise Grid fixes: - `handleOAuthCallback` now handles org-wide installs (`is_enterprise_install`): Slack returns `team: null` for these, and the installation is now keyed by the enterprise ID — the same key webhook token resolution looks up — instead of failing. The result includes `enterpriseId` and `isEnterpriseInstall`, and `SlackInstallation` records both. - Socket mode now resolves per-installation tokens for events, slash commands, and interactive payloads in multi-workspace deployments (matching the HTTP webhook path), and no longer drops `enterprise_id` / `is_enterprise_install` / `is_ext_shared_channel` from event payloads. - The user profile cache and display-name mention reverse index are now scoped by installation in multi-workspace deployments, so profiles fetched with one workspace's token no longer bleed into another and mentions can no longer resolve to a same-named user from a different workspace. Existing cache entries repopulate on first lookup (single-workspace keys are unchanged). `withBotToken` accepts an optional `{ installationId }` so proactive/cron posts outside webhook handling scope these caches too. - API calls made while handling an event from an org-wide install now pass the event's `team_id` explicitly, as Slack requires for workspace-scoped methods (`conversations.list`, `usergroups.*`, …) on org tokens. When an event carries a `context_team_id` (shared channels hosted on an "away" workspace), channel-addressed calls echo it back as `client_context_team_id`. - Retried event deliveries (`x-slack-retry-num`, socket `retry_num`) are dropped when the original delivery was already dispatched, using an `event_id` marker in the state adapter (24-hour TTL). Events whose first delivery never arrived are still recovered via the retry. - Bare `@W…` mentions in outgoing messages are now recognized as raw Enterprise Grid user IDs (previously only `@U…` was), so they render as real mentions instead of being treated as display names. - Event token resolution now prefers the envelope's `authorizations[0]` — Slack's documented location for the event's installation identity — over the top-level `team_id`/`enterprise_id`, which can name a different workspace for Slack Connect shared-channel events. Top-level fields remain as a fallback. ### Patch Changes -80def3a: Add optional `isSystem` field to the normalized message `Author` type to distinguish platform-generated messages from humans and bots. The Slack adapter now sets `isSystem: true` for messages authored by Slack's reserved `USLACK` user (e.g. "@user archived the channel" notifications in DMs), so consumers no longer need to hard-code Slack-specific user IDs. -92530dd: Return a replyable Slack thread ID from `channel.post()` by using the posted top-level message's timestamp as the thread root. - Updated dependencies [80def3a] - Updated dependencies [4cb7e5d] - Updated dependencies [46681f5] - Updated dependencies [93a58af] - Updated dependencies [25f3099] - chat@4.35.0 - @chat-adapter/shared@4.35.0 ## @chat-adapter/teams@4.35.0 ### Minor Changes -5eb8b84: Add support for adding and removing reactions from Microsoft Teams messages. -46681f5: Expose Microsoft Graph email addresses on normalized incoming Teams message authors. Resolved user profiles are cached in the state adapter (1 hour, failed lookups 5 minutes) so the lookup doesn't add a Graph call per message. -160140e: Add native Microsoft Teams targeted message support via `thread.postEphemeral()` and `channel.postEphemeral()`. -e06b4b6: Add a `token` config option to `TeamsAdapterConfig` for supplying a custom token factory, forwarded to the Teams SDK's `AppOptions.token`. This lets bots authenticate on runtimes that can't reach Azure IMDS (so `federated` managed identity isn't reachable) but can still mint access tokens through an external mechanism, without needing a static client secret. ### Patch Changes -3895ab3: Fall back to Microsoft Graph's user principal name when a Teams user has no mail address. -93a58af: Show explicitly configured progress as a native Teams DM status while preserving native streaming. - Updated dependencies [80def3a] - Updated dependencies [4cb7e5d] - Updated dependencies [46681f5] - Updated dependencies [93a58af] - Updated dependencies [25f3099] - chat@4.35.0 - @chat-adapter/shared@4.35.0 ## @chat-adapter/telegram@4.35.0 ### Minor Changes -54eea71: Add an optional Telegram user allowlist via `allowedUserIds` or the comma-separated `TELEGRAM_ALLOWED_USER_IDS` environment variable. ### Patch Changes -0701679: Cache the compiled bot-mention regex in `isBotMentioned` instead of recompiling it per message, and make the protected `sleep` helper accept an optional `AbortSignal` so `stopPolling()` interrupts the polling backoff delay immediately. - Updated dependencies [80def3a] - Updated dependencies [4cb7e5d] - Updated dependencies [46681f5] - Updated dependencies [93a58af] - Updated dependencies [25f3099] - chat@4.35.0 - @chat-adapter/shared@4.35.0 ## chat@4.35.0 ### Minor Changes -4cb7e5d: Add a `chat/workflow` subpath with `requestApproval()`: durable human-in-the-loop approvals built on Workflow SDK. It posts an approval card with Approve/Deny buttons, suspends the workflow until a user decides (or an optional timeout elapses), validates approvers, finalizes the card with the outcome, and returns `{ approved, timedOut, user }`. Also exports the `buildApprovalCard` and `buildResolvedCard` builders. Requires the new optional `workflow` peer dependency. -46681f5: Expose Microsoft Graph email addresses on normalized incoming Teams message authors. Resolved user profiles are cached in the state adapter (1 hour, failed lookups 5 minutes) so the lookup doesn't add a Graph call per message. ### Patch Changes -80def3a: Add optional `isSystem` field to the normalized message `Author` type to distinguish platform-generated messages from humans and bots. The Slack adapter now sets `isSystem: true` for messages authored by Slack's reserved `USLACK` user (e.g. "@user archived the channel" notifications in DMs), so consumers no longer need to hard-code Slack-specific user IDs. -93a58af: Show explicitly configured progress as a native Teams DM status while preserving native streaming. -25f3099: `toAiMessages` no longer drops messages that have no text. A message with an empty text body is now kept when it has links or attachments the converter can include: images and text files (`text/*`, JSON, XML, YAML, etc.) with a working `fetchData()`. Messages whose only attachments are unsupported (video, audio, other file types, or attachments without `fetchData()`) are still skipped, and `onUnsupportedAttachment` now fires for video/audio attachments on these previously filtered messages. Note: multipart `content` no longer always starts with a text part. When a kept message had no text, its `content` array contains only attachment parts. ## @chat-adapter/gchat@4.35.0 ### Patch Changes -270b1c2: fix(gchat): accept `endpointUrl` as a direct-webhook verifier and verify each token type correctly When a Google Chat app's connection setting **Authentication audience** is set to **HTTP endpoint URL** — Google's recommended option for HTTP-hosted apps not behind Cloud Run IAM, and the only mode available for Workspace Add-on Chat apps — incoming tokens are Google OIDC ID tokens whose `aud` is the endpoint URL rather than the GCP project number. Previously the adapter only verified against `googleChatProjectNumber`, so URL-audience tokens always failed with 401 Unauthorized. The adapter now accepts `endpointUrl` as a direct-webhook verifier (including in the constructor's fail-closed check), validating the OIDC token's audience plus the Google Chat issuer email claims (`chat@system.gserviceaccount.com`, or the `service-{projectNumber}@gcp-sa-gsuiteaddons.iam.gserviceaccount.com` service identity for Workspace Add-on Chat apps) with `email_verified: true` — a public endpoint URL audience alone is not sufficient to forge a request. Project-number-audience tokens are now verified per Google's reference implementation: they are JWTs self-signed by `chat@system.gserviceaccount.com`, so the adapter checks them against that service account's X.509 certificates with issuer `chat@system.gserviceaccount.com` (previously it used `verifyIdToken`, which only accepts Google OIDC issuers and certs and therefore rejected every real project-number token). When both verifiers are configured, either token type is accepted. The adapter still infers an endpoint URL from incoming requests for button-click action routing only — that inferred value is never used as a JWT verification audience, and inference now only happens after a request has passed verification (or verification was explicitly disabled), because `request.url` derives from the attacker-controllable `Host` header in serverless runtimes. - Updated dependencies [80def3a] - Updated dependencies [4cb7e5d] - Updated dependencies [46681f5] - Updated dependencies [93a58af] - Updated dependencies [25f3099] - chat@4.35.0 - @chat-adapter/shared@4.35.0 ## @chat-adapter/github@4.35.0 ### Patch Changes - Updated dependencies [80def3a] - Updated dependencies [4cb7e5d] - Updated dependencies [46681f5] - Updated dependencies [93a58af] - Updated dependencies [25f3099] - chat@4.35.0 - @chat-adapter/shared@4.35.0 ## @chat-adapter/linear@4.35.0 ### Patch Changes - Updated dependencies [80def3a] - Updated dependencies [4cb7e5d] - Updated dependencies [46681f5] - Updated dependencies [93a58af] - Updated dependencies [25f3099] - chat@4.35.0 - @chat-adapter/shared@4.35.0 ## @chat-adapter/messenger@4.35.0 ### Patch Changes - Updated dependencies [80def3a] - Updated dependencies [4cb7e5d] - Updated dependencies [46681f5] - Updated dependencies [93a58af] - Updated dependencies [25f3099] - chat@4.35.0 - @chat-adapter/shared@4.35.0 ## @chat-adapter/shared@4.35.0 ### Patch Changes - Updated dependencies [80def3a] - Updated dependencies [4cb7e5d] - Updated dependencies [46681f5] - Updated dependencies [93a58af] - Updated dependencies [25f3099] - chat@4.35.0 ## @chat-adapter/twilio@4.35.0 ### Patch Changes - Updated dependencies [80def3a] - Updated dependencies [4cb7e5d] - Updated dependencies [46681f5] - Updated dependencies [93a58af] - Updated dependencies [25f3099] - chat@4.35.0 - @chat-adapter/shared@4.35.0 ## @chat-adapter/web@4.35.0 ### Patch Changes - Updated dependencies [80def3a] - Updated dependencies [4cb7e5d] - Updated dependencies [46681f5] - Updated dependencies [93a58af] - Updated dependencies [25f3099] - chat@4.35.0 - @chat-adapter/shared@4.35.0 ## @chat-adapter/whatsapp@4.35.0 ### Patch Changes -09b72e9: fix whatsapp card media duplication - Prevent card titles and body content from appearing twice when sending cards with files on WhatsApp. - Avoid adding the full card fallback text as an image caption when an interactive message follows. - Keep interactive WhatsApp messages responsible for rendering card titles, bodies, and actions. - Updated dependencies [80def3a] - Updated dependencies [4cb7e5d] - Updated dependencies [46681f5] - Updated dependencies [93a58af] - Updated dependencies [25f3099] - chat@4.35.0 - @chat-adapter/shared@4.35.0 ## @chat-adapter/x@4.35.0 ### Patch Changes - Updated dependencies [80def3a] - Updated dependencies [4cb7e5d] - Updated dependencies [46681f5] - Updated dependencies [93a58af] - Updated dependencies [25f3099] - chat@4.35.0 - @chat-adapter/shared@4.35.0 ## @chat-adapter/state-ioredis@4.35.0 ### Patch Changes - Updated dependencies [80def3a] - Updated dependencies [4cb7e5d] - Updated dependencies [46681f5] - Updated dependencies [93a58af] - Updated dependencies [25f3099] - chat@4.35.0 ## @chat-adapter/state-memory@4.35.0 ### Patch Changes - Updated dependencies [80def3a] - Updated dependencies [4cb7e5d] - Updated dependencies [46681f5] - Updated dependencies [93a58af] - Updated dependencies [25f3099] - chat@4.35.0 ## @chat-adapter/state-pg@4.35.0 ### Patch Changes -d88789c: Fix `setIfNotExists()` so it can claim a cache key whose existing row has expired. Previously the query used `ON CONFLICT DO NOTHING`, so an expired row in `chat_state_cache` still blocked acquisition until opportunistic cleanup deleted it — diverging from the memory and Redis adapters, which treat expired entries as absent. Keys stored without a TTL remain permanent and are never overwritten. - Updated dependencies [80def3a] - Updated dependencies [4cb7e5d] - Updated dependencies [46681f5] - Updated dependencies [93a58af] - Updated dependencies [25f3099] - chat@4.35.0 ## @chat-adapter/state-redis@4.35.0 ### Patch Changes - Updated dependencies [80def3a] - Updated dependencies [4cb7e5d] - Updated dependencies [46681f5] - Updated dependencies [93a58af] - Updated dependencies [25f3099] - chat@4.35.0 ## @chat-adapter/tests@4.35.0 Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
@chat-adapter/gchat
npm package:
@chat-adapter/gchat
Google Chat adapter for Chat SDK. Configure with service account authentication and optional Pub/Sub.
Documentation: chat-sdk.dev/adapters/official/gchat · Guides: vercel.com/kb/chat-sdk
Installation
pnpm add @chat-adapter/gchat
Scaffold with the CLI
To scaffold a new Google Chat bot with this adapter preselected:
npx create-chat-sdk@latest my-bot --adapter gchat memory
Visit the adapters directory to see other available official and vendor-official adapters.
Usage
The adapter auto-detects credentials from GOOGLE_CHAT_CREDENTIALS or GOOGLE_CHAT_USE_ADC environment variables:
import { Chat } from "chat";
import { createGoogleChatAdapter } from "@chat-adapter/gchat";
const bot = new Chat({
userName: "mybot",
adapters: {
gchat: createGoogleChatAdapter(),
},
});
bot.onNewMention(async (thread, message) => {
await thread.post("Hello from Google Chat!");
});
Google Chat setup
1. Create a GCP project
- Go to console.cloud.google.com
- Click the project dropdown then New Project
- Enter project name and click Create
2. Enable required APIs
Go to APIs & Services then Library and enable:
- Google Chat API
- Google Workspace Events API (for receiving all messages)
- Cloud Pub/Sub API (for receiving all messages)
3. Create a service account
- Go to IAM & Admin then Service Accounts
- Click Create Service Account
- Enter name and description
- Click Create and Continue
- Skip the optional steps, click Done
4. Create service account key
- Click on your service account
- Go to Keys tab
- Click Add Key then Create new key
- Select JSON and click Create
- Copy the entire JSON content as
GOOGLE_CHAT_CREDENTIALS
Note: If your organization has the
iam.disableServiceAccountKeyCreationconstraint enabled, you need to relax it or add an exception for your project in IAM & Admin then Organization Policies.
5. Configure Google Chat app
- Go to the Chat API configuration
- Click Configuration and fill in:
- App name: Your bot's display name
- Avatar URL: URL to your bot's avatar
- Description: What your bot does
- Interactive features: Enable Receive 1:1 messages and Join spaces and group conversations
- Connection settings: Select App URL
- App URL:
https://your-domain.com/api/webhooks/gchat - Visibility: Choose who can discover your app
- Click Save
6. Add bot to a space
- Open Google Chat
- Create or open a Space
- Click the space name then Manage apps & integrations
- Click Add apps, search for your app, and click Add
Pub/Sub for all messages (optional)
By default, Google Chat only sends webhooks for @mentions. To receive all messages in a space, set up Workspace Events with Pub/Sub.
createGoogleChatAdapter({
pubsubTopic: process.env.GOOGLE_CHAT_PUBSUB_TOPIC,
impersonateUser: process.env.GOOGLE_CHAT_IMPERSONATE_USER,
});
GOOGLE_CHAT_PUBSUB_TOPIC and GOOGLE_CHAT_IMPERSONATE_USER are also auto-detected from env vars, so you can omit them from config if the env vars are set.
1. Create Pub/Sub topic
- Go to Pub/Sub then Topics
- Click Create Topic
- Enter topic ID (e.g.,
chat-events) - Uncheck Add a default subscription
- Click Create
- Copy the full topic name as
GOOGLE_CHAT_PUBSUB_TOPIC(format:projects/your-project-id/topics/chat-events)
2. Grant Chat service account access
- Go to your Pub/Sub topic
- Click Permissions tab
- Click Add Principal
- Enter
chat-api-push@system.gserviceaccount.com - Select role Pub/Sub Publisher
- Click Save
3. Create push subscription
- Go to Pub/Sub then Subscriptions
- Click Create Subscription
- Select your topic
- Set Delivery type to Push
- Set Endpoint URL to
https://your-domain.com/api/webhooks/gchat - Click Create
4. Enable domain-wide delegation
Domain-wide delegation is required for creating Workspace Events subscriptions and initiating DMs.
Step 1 — Enable delegation on the service account:
- Go to IAM & Admin then Service Accounts
- Click on your service account
- Check Enable Google Workspace Domain-wide Delegation and save
- Copy the Client ID (a numeric ID, not the email)
Step 2 — Authorize in Google Admin Console:
- Go to Google Admin Console
- Go to Security then Access and data control then API controls
- Click Manage Domain Wide Delegation then Add new
- Enter the numeric Client ID from Step 1
- Add OAuth scopes (comma-separated, on one line):
https://www.googleapis.com/auth/chat.spaces.readonly,https://www.googleapis.com/auth/chat.messages.readonly,https://www.googleapis.com/auth/chat.spaces,https://www.googleapis.com/auth/chat.spaces.create - Click Authorize
Step 3 — Set environment variable:
Set GOOGLE_CHAT_IMPERSONATE_USER to an admin user email in your domain (e.g., admin@yourdomain.com).
Configuration
Most options are auto-detected from environment variables when not provided.
endpointUrl must be passed in config.
| Option | Required | Description |
|---|---|---|
credentials |
No* | Service account credentials JSON. Auto-detected from GOOGLE_CHAT_CREDENTIALS |
useApplicationDefaultCredentials |
No | Use Application Default Credentials. Auto-detected from GOOGLE_CHAT_USE_ADC |
pubsubTopic |
No | Pub/Sub topic for Workspace Events. Auto-detected from GOOGLE_CHAT_PUBSUB_TOPIC |
pubsubAudience |
No† | Expected JWT audience for Pub/Sub webhook verification. Auto-detected from GOOGLE_CHAT_PUBSUB_AUDIENCE |
googleChatProjectNumber |
No† | GCP project number for direct webhook JWT verification when the Chat app's authentication audience is "Project number". Auto-detected from GOOGLE_CHAT_PROJECT_NUMBER |
endpointUrl |
No† | Public webhook URL for button click routing and direct webhook JWT verification when the Chat app's authentication audience is "HTTP endpoint URL". Must be passed in config |
disableSignatureVerification |
No† | Disable JWT verification entirely (development only). Auto-detected from GOOGLE_CHAT_DISABLE_SIGNATURE_VERIFICATION=true |
impersonateUser |
No | User email for domain-wide delegation. Auto-detected from GOOGLE_CHAT_IMPERSONATE_USER |
auth |
No | Custom auth object (advanced) |
apiUrl |
No | Override the Google Chat API base URL. Auto-detected from GOOGLE_CHAT_API_URL |
logger |
No | Logger instance (defaults to ConsoleLogger("info")) |
*Either credentials, GOOGLE_CHAT_CREDENTIALS env var, useApplicationDefaultCredentials, or GOOGLE_CHAT_USE_ADC=true is required.
†One of googleChatProjectNumber, endpointUrl, pubsubAudience, or disableSignatureVerification: true is required — the constructor throws otherwise. Configure the verifier(s) for each transport you actually receive; requests of a shape whose verifier is unconfigured are rejected with HTTP 401.
Environment variables
GOOGLE_CHAT_CREDENTIALS={"type":"service_account",...}
# Optional: for receiving all messages
GOOGLE_CHAT_PUBSUB_TOPIC=projects/your-project/topics/chat-events
GOOGLE_CHAT_IMPERSONATE_USER=admin@yourdomain.com
# Webhook verification — at least one verifier or the explicit opt-out is required
GOOGLE_CHAT_PROJECT_NUMBER=123456789 # Direct webhooks with project-number audience
GOOGLE_CHAT_PUBSUB_AUDIENCE=https://your-domain.com/api/webhooks/gchat # For Pub/Sub JWT verification
# GOOGLE_CHAT_DISABLE_SIGNATURE_VERIFICATION=true # Escape hatch for local dev only
# Optional: override the Google Chat API base URL
GOOGLE_CHAT_API_URL=...
Webhook verification
The adapter supports JWT verification for both webhook types. When configured, the adapter validates the Authorization: Bearer <JWT> header on incoming requests using Google's public keys. Requests with missing or invalid tokens are rejected with HTTP 401.
Verification is required. The constructor throws ValidationError unless one of the following is set:
googleChatProjectNumber(orGOOGLE_CHAT_PROJECT_NUMBER) — direct webhooks when the Chat app's authentication audience is "Project number"endpointUrl— direct webhooks when the Chat app's authentication audience is "HTTP endpoint URL"; also required for routing card button clicks in HTTP endpoint appspubsubAudience(orGOOGLE_CHAT_PUBSUB_AUDIENCE) — Pub/Sub push deliveriesdisableSignatureVerification: true(orGOOGLE_CHAT_DISABLE_SIGNATURE_VERIFICATION=true) — explicit opt-out, intended for local development only
The two transports share one HTTP endpoint, so each verifier only covers its own request shape. If you only configure a direct-webhook verifier, incoming Pub/Sub-shaped requests are rejected with HTTP 401, and vice versa — configure both if you receive both.
Direct webhooks (Google Chat API)
Google Chat sends a signed token with every webhook request. The expected JWT audience (aud claim) depends on the Chat app's Authentication audience setting:
createGoogleChatAdapter({
googleChatProjectNumber: "123456789",
});
Use googleChatProjectNumber when the setting is Project number. Find your project number in the GCP Console dashboard (it's different from the project ID).
createGoogleChatAdapter({
endpointUrl: "https://your-domain.com/api/webhooks/gchat",
});
Use endpointUrl when the setting is HTTP endpoint URL. Workspace Add-on Chat apps always use URL audience tokens. When both googleChatProjectNumber and endpointUrl are set, either token type is accepted.
The two modes carry different token types, and the adapter verifies each per Google's reference implementation: endpoint-URL tokens are standard Google OIDC ID tokens (checked against Google's public certs, plus the Chat service-account email claim with email_verified), while project-number tokens are JWTs self-signed by chat@system.gserviceaccount.com (checked against that service account's X.509 certificates with issuer chat@system.gserviceaccount.com). The configured endpointUrl must exactly match the URL registered in the Chat API console — a trailing-slash or scheme mismatch fails verification.
Pub/Sub push messages
Google Cloud Pub/Sub sends a signed OIDC JWT with push deliveries. The JWT audience is whatever you configured on the push subscription.
createGoogleChatAdapter({
pubsubAudience: "https://your-domain.com/api/webhooks/gchat",
});
To enable authenticated push on your Pub/Sub subscription:
- Go to Pub/Sub then Subscriptions
- Edit your push subscription
- Enable Authentication
- Select a service account with the Service Account Token Creator role
- Set the Audience to your webhook URL
- Use the same URL as
GOOGLE_CHAT_PUBSUB_AUDIENCE
Features
Messaging
| Feature | Supported |
|---|---|
| Post message | Yes |
| Edit message | Yes |
| Delete message | Yes |
| File uploads | No |
| Streaming | Post+Edit fallback |
Rich content
| Feature | Supported |
|---|---|
| Card format | Google Chat Cards |
| Buttons | Yes |
| Link buttons | Yes |
| Select menus | Yes |
| Tables | ASCII |
| Fields | Yes |
| Images in cards | Yes |
| Modals | No |
Conversations
| Feature | Supported |
|---|---|
| Slash commands | No |
| Mentions | Yes |
| Add reactions | Yes (via Workspace Events) |
| Remove reactions | Yes (via Workspace Events) |
| Typing indicator | No |
| DMs | Yes (requires delegation) |
| Ephemeral messages | Yes (native) |
Message history
| Feature | Supported |
|---|---|
| Fetch messages | Yes |
| Fetch single message | No |
| Fetch thread info | Yes |
| Fetch channel messages | Yes |
| List threads | Yes |
| Fetch channel info | Yes |
| Post channel message | Yes |
Limitations
- Typing indicators: Not supported by Google Chat API.
startTyping()is a no-op. - Adding reactions: The Google Chat API doesn't support service account (app) authentication for adding reactions. To use
addReaction()orremoveReaction(), you need domain-wide delegation withimpersonateUserconfigured — but the reaction appears as coming from the impersonated user, not the bot.
Message history (fetchMessages)
Fetching message history requires domain-wide delegation with the impersonateUser config option set. The impersonated user must have access to the spaces you want to read from. See the Pub/Sub setup above for configuring delegation and OAuth scopes.
Troubleshooting
401 Unauthorized on webhooks
- For direct webhooks: verify
GOOGLE_CHAT_PROJECT_NUMBERmatches your GCP project number (not project ID) - For Pub/Sub: verify
GOOGLE_CHAT_PUBSUB_AUDIENCEmatches the audience configured on your push subscription - Check that authentication is enabled on your Pub/Sub push subscription
- Ensure the service account used for push authentication has the Service Account Token Creator role
No webhook received
- Verify the App URL is correct in Google Chat configuration
- Check that the Chat API is enabled
- Ensure the service account has the necessary permissions
Pub/Sub not working
- Verify
chat-api-push@system.gserviceaccount.comhas Pub/Sub Publisher role - Check that the push subscription URL is correct
- Verify domain-wide delegation is configured with correct scopes
- Check
GOOGLE_CHAT_IMPERSONATE_USERis a valid admin email
"Permission denied" for Workspace Events
- Ensure domain-wide delegation is configured
- Verify the OAuth scopes are exactly as specified
- Check that the impersonated user has access to the spaces
"Insufficient Permission" for DMs
- DMs require domain-wide delegation with
chat.spacesandchat.spaces.createscopes - Scope changes can take up to 24 hours to propagate
Button clicks not received
- Verify Interactive features is enabled in the Google Chat app configuration
- Check that the App URL is correctly set and accessible
- Button clicks go to the same webhook URL as messages
AI Coding Agents
If you use an AI coding agent such as OpenAI Codex, Claude Code, or Cursor, install the Chat SDK skill so it knows the SDK APIs, adapter patterns, and project conventions before writing code.
npx skills add vercel/chat
The skill references bundled documentation in node_modules/chat/docs, plus adapter guides and starter templates in the published package.
You can also install the Vercel Plugin for a broader agent toolkit — it includes the Chat SDK skill alongside specialist agents, agent slash commands, and more:
npx plugins add vercel/vercel-plugin
The plugin is optional; the skill alone is enough to build with Chat SDK.
For agent-readable documentation, see chat-sdk.dev/llms.txt (page index) or chat-sdk.dev/llms-full.txt (full text).
License
MIT