Post to Google Chat from an agent
The gchat_post_message tool posts a message to a Google Chat space, optionally
with rich link cards, authenticated as a Chat app. Use it for proactive
notifications, scheduled reports, and task updates, rather than only replying
when the agent is mentioned.
Before you begin
The tool authenticates as a Google Chat app using a service account, so:
- The service account must be configured as a Google Chat app, and the Google Chat API must be enabled for its Google Cloud project.
- The Chat app must already be a member of the target space. There is no API to join a space, so a person has to add the app to the space, or the app must have created it. Posting to a space the app does not belong to fails.
Posting uses the https://www.googleapis.com/auth/chat.bot scope, which the app
grants itself. No Google Workspace administrator approval is required for
posting.
Credentials
The tool takes its credentials from one of two places, and the agent never sees them: both are filled by configuration, not chosen by the model.
A gchat_service_account_key agent secret. Store the full service account
JSON key under that name and the tool picks it up automatically. No connector is
needed.
STORE A GOOGLE CHAT SERVICE ACCOUNT KEY
Code example with bash syntax.1
An attached Google Chat connector. A connector of type gchat carries the
same service account key and also lets the agent receive Chat events. Create one
with the service account JSON key:
CREATE A GOOGLE CHAT CONNECTOR
Code example with bash syntax.1
The service account key is encrypted at rest and never returned. The read view
of the connector returns client_email and project_id, parsed out of the key,
plus an audience_url. To receive inbound events, set the Chat app's HTTP
endpoint URL and Authentication audience to that audience_url in the
Google Cloud console: inbound Google Chat ID tokens are accepted only when their
aud matches it.
Credential precedence
When the tool runs, credentials resolve in this order:
- An explicit service account key argument. The shipped configuration fills
this from the
gchat_service_account_keyagent secret. - An explicit connector ID argument. The shipped configuration fills this from
session.metadata.connector_id, which the connector sets on sessions it triggers. A connector ID that resolves to a non-Google connector (a Slack-triggered session cross-posting to Chat, for example) falls through to the steps below; one that resolves to nothing is an error. - The connector that triggered the current loop, if it carries Google credentials.
- The first Google connector attached to the agent, ordered by connector ID.
If none of these produce credentials, the tool call fails with an error naming
the gchat_service_account_key secret.
gchat_post_message
Posts a message to a space or thread.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
space_name | string | Yes | The resource name of the space, such as spaces/AAAAAqas8kM. This is not the space's display name. |
text | string | Required unless cards is set | The message text, 1 to 32,000 characters. |
cards | array | Required unless text is set | Rich cards appended below the message text. |
thread_name | string | No | The resource name of an existing thread to reply in, such as spaces/AAAAAqas8kM/threads/UWknXX-lIB4. Omit to start a new thread. |
A message with neither text nor cards is rejected before any request is sent.
The whole message, text plus cards, is limited to 32,000 bytes.
Message text uses Google Chat text formatting: *bold*, _italic_,
~strikethrough~, `code`, ```code blocks```,
<https://example.com|link text> links, and <users/USER_ID> mentions. Use
<users/all> to mention everyone.
Response
| Field | Type | Description |
|---|---|---|
ok | boolean | Whether the message was posted. Always present. |
message_name | string | The resource name of the posted message, such as spaces/AAAAAqas8kM/messages/UWknXX-lIB4.UWknXX-lIB4. |
thread_name | string | The resource name of the message's thread. |
error | string | The error message when the post failed. |
When the Chat API rejects the post, the tool returns ok: false with error
set, rather than failing the agent's turn.
Threading
Pass the thread_name returned by an earlier post, or observed on an incoming
message, to reply in that thread. If the thread does not exist, the post fails
instead of silently starting a new one. Spaces that do not use threading, such
as direct messages and group chats, ignore thread_name.
Cards
Each entry in cards renders as a framed panel below the message text, with an
optional header and one or more sections. Cards suit content with links the user
should open: reports, alerts, and digests.
| Field | Type | Required | Description |
|---|---|---|---|
title | string | No | Card header title, rendered at the top of the card. |
subtitle | string | No | Card header subtitle. Ignored unless title is set. |
sections | array | Yes | The card body, rendered top to bottom. At least one section. |
Each section takes an optional header, a text body, and a list of links,
and must have text, links, or both. Sections are separated by a divider.
| Field | Type | Required | Description |
|---|---|---|---|
header | string | No | A small heading above the section content. |
text | string | Required unless links is set | Section body text. |
links | array | Required unless text is set | Link buttons rendered in a row below the section text. |
Each link is a button with a text label and a url, which must be http or
https. Clicking it opens the URL in the user's browser, so no card
interactivity support is needed in the Chat app.
Section text uses HTML-style formatting rather than Chat text markup:
<b>bold</b>, <i>italic</i>, <s>strikethrough</s>, <u>underline</u>,
<a href="https://example.com">inline links</a>, and <br> for line breaks.
{
"space_name": "spaces/AAAAAqas8kM",
"text": "*Nightly index run finished.*",
"cards": [
{
"title": "Index run 4821",
"subtitle": "Completed in 12m",
"sections": [
{
"header": "Summary",
"text": "<b>18,204</b> documents indexed, <b>3</b> failures.",
"links": [
{ "text": "Open report", "url": "https://example.com/runs/4821" }
]
}
]
}
]
}
Chat-triggered agents
When a Google Chat connector triggers an agent, the connector already posts the
agent's final reply to the triggering space and thread. An agent that also calls
gchat_post_message with the same content posts the message twice. Instruct
such agents to use the tool only for messages beyond the final reply: posts to
other spaces or threads, and mid-run progress updates.