Skip to content
mercury framework
GitHub

Google Chat

Package
@mercury-fw/channel-google-chat
Role
Channel
Version
0.11.1
Terminal window
bun add @mercury-fw/channel-google-chat
VariableWhat it is
GOOGLE_CHAT_PUBSUB_SUBSCRIPTIONPub/Sub subscription the Chat app's events arrive on (projects/<p>/subscriptions/<s>); empty leaves Google Chat inert
GOOGLE_CHAT_APP_CLIENT_EMAILService account the Chat app authenticates as
GOOGLE_CHAT_APP_PRIVATE_KEYThat service account's private key (PEM)

With this channel the agent is a Chat app in your Google Workspace: people find it in Google Chat, message it directly or add it to a space, and it answers there. While it works it shows a card with what it’s doing, and an action that needs confirmation comes with a button. What it shows people itself (the cards, the buttons, the replies to a confirmation) is in their language: the one they asked the agent for, else their Chat client’s when the message says.

Each message reaches the agent as google-chat:users/<id>, the sender’s Chat account, with their email when Google vouches for it, which a directory can use to recognize them.

Google Chat doesn’t call your server directly. It publishes each event (a message, a button click) on a Pub/Sub topic, Google Cloud’s message queue, and the agent reads them from a subscription to that topic. It answers through the Chat API, as a service account (an account for programs, with a key instead of a password). So the agent needs no public address, only the three settings above: the subscription, and the service account’s email and key.

You need a Google Workspace account that can create Chat apps, and a Google Cloud project. The setup creates the topic and the subscription, the service account and its key, and the Chat app itself in the Cloud Console. The channel’s README walks through it step by step.

Once you have the key file, mfw writes the settings into .env without printing the key:

Terminal window
mfw google-chat set-key key.json --subscription projects/my-project/subscriptions/mercury-chat-sub

Delete the key file afterwards, and mfw start.

An app created with mfw create --channels google-chat has this already. Otherwise, bun add @mercury-fw/channel-google-chat, add protobufjs (which Google’s Pub/Sub client uses) to trustedDependencies in the app’s package.json, and declare it:

mercury.config.ts
import { googleChatChannel } from "@mercury-fw/channel-google-chat";
channels: [googleChatChannel],

Google Chat has no Esc key, so the channel gives two ways to stop an answer that’s taking too long or going the wrong way: the Stop button on every card still in progress, or a message saying /stop. Either one ends the answer and throws away the messages the person had sent behind it, still waiting their turn. Nothing of the half answer is sent, and the card says it stopped. The agent remembers the question with a note that the answer was stopped, so “never mind, do this instead” makes sense to it. A command a tool already ran stays done, though: the stop cuts the model, not the command.

Only the person who asked can stop their answer. In a shared space, someone else’s Stop finds nothing of theirs to stop.

/stop works as a plain message already. Registering it as a slash command in the Chat app’s configuration (step 7, item 8, of the README) puts it among the commands Chat suggests, and in a space it then reaches the agent without mentioning it.

When a plugin that acts as the person needs them to log in to a service, the channel sends a card with a button only that person sees. The service then sends their browser back to the HTTP channel’s /login/callback, so an app where people log in needs the HTTP channel too, with HTTP_SURFACE_PUBLIC_URL.