google-chat-messages
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseGoogle Chat Messages
Google Chat 消息发送
Send messages to Google Chat spaces via incoming webhooks. Produces text messages, rich cards (cardsV2), and threaded replies.
通过传入webhook向Google Chat空间发送消息。支持生成文本消息、富卡片(cardsV2)和线程回复。
What You Produce
可生成的内容
- Text messages with Google Chat formatting
- Rich card messages (cardsV2) with headers, sections, widgets
- Threaded conversations
- Reusable webhook sender utility
- 带Google Chat格式的文本消息
- 包含标题、章节、组件的富卡片消息(cardsV2)
- 线程对话
- 可复用的webhook发送工具
Workflow
操作流程
Step 1: Get Webhook URL
步骤1:获取Webhook URL
In Google Chat:
- Open a Space > click space name > Manage webhooks
- Create webhook (name it, optionally add avatar URL)
- Copy the webhook URL
Store the URL as a secret (environment variable or Bitwarden), never hardcode.
在Google Chat中:
- 打开一个空间 > 点击空间名称 > 管理webhook
- 创建webhook(设置名称,可选择性添加头像URL)
- 复制webhook URL
将URL存储为机密信息(环境变量或Bitwarden),切勿硬编码。
Step 2: Choose Message Type
步骤2:选择消息类型
| Need | Type | Complexity |
|---|---|---|
| Simple notification | Text message | Low |
| Structured info (status, digest) | Card message (cardsV2) | Medium |
| Ongoing updates | Threaded replies | Medium |
| Action buttons (open URL) | Card with buttonList | Medium |
| 需求 | 类型 | 复杂度 |
|---|---|---|
| 简单通知 | 文本消息 | 低 |
| 结构化信息(状态、摘要) | 卡片消息(cardsV2) | 中 |
| 持续更新内容 | 线程回复 | 中 |
| 操作按钮(打开URL) | 带buttonList的卡片 | 中 |
Step 3: Send the Message
步骤3:发送消息
Use for the sender utility. Use for structured card construction.
assets/webhook-sender.tsassets/card-builder.ts使用作为发送工具。使用构建结构化卡片。
assets/webhook-sender.tsassets/card-builder.tsText Formatting
文本格式
Google Chat does NOT use standard Markdown.
| Format | Syntax | Example |
|---|---|---|
| Bold | | |
| Italic | | |
| Strikethrough | | |
| Monospace | | |
| Code block | | Multi-line code |
| Link | | |
| Mention user | | |
| Mention all | | |
Not supported: , headings (), blockquotes, tables, images inline.
**double asterisks**###Google Chat 不使用标准Markdown语法。
| 格式 | 语法 | 示例 |
|---|---|---|
| 粗体 | | |
| 斜体 | | |
| 删除线 | | |
| 等宽文本 | | |
| 代码块 | | 多行代码 |
| 链接 | | |
| 提及用户 | | |
| 提及所有人 | | |
不支持:、标题()、块引用、表格、行内图片。
**双星号**###Text Message Example
文本消息示例
typescript
await sendText(webhookUrl, '*Build Complete*\n\nBranch: `main`\nStatus: Passed\n<https://ci.example.com/123|View Build>');typescript
await sendText(webhookUrl, '*Build Complete*\n\nBranch: `main`\nStatus: Passed\n<https://ci.example.com/123|View Build>');cardsV2 Structure
cardsV2 结构
Cards use the cardsV2 format (recommended over legacy cards).
typescript
const message = {
cardsV2: [{
cardId: 'unique-id',
card: {
header: {
title: 'Card Title',
subtitle: 'Optional subtitle',
imageUrl: 'https://example.com/icon.png',
imageType: 'CIRCLE' // or 'SQUARE'
},
sections: [{
header: 'Section Title', // optional
widgets: [
// widgets go here
]
}]
}
}]
};卡片使用cardsV2格式(推荐替代旧版卡片)。
typescript
const message = {
cardsV2: [{
cardId: 'unique-id',
card: {
header: {
title: 'Card Title',
subtitle: 'Optional subtitle',
imageUrl: 'https://example.com/icon.png',
imageType: 'CIRCLE' // or 'SQUARE'
},
sections: [{
header: 'Section Title', // optional
widgets: [
// widgets go here
]
}]
}
}]
};Widget Types
组件类型
Text paragraph — formatted text block:
typescript
{ textParagraph: { text: '*Bold* and _italic_ text' } }Decorated text — label + value with optional icon:
typescript
{
decoratedText: {
topLabel: 'Status',
text: 'Deployed',
startIcon: { knownIcon: 'STAR' }
}
}Button list — action buttons:
typescript
{
buttonList: {
buttons: [{
text: 'View Dashboard',
onClick: { openLink: { url: 'https://dashboard.example.com' } }
}]
}
}Image — standalone image:
typescript
{ image: { imageUrl: 'https://example.com/chart.png', altText: 'Usage chart' } }Divider — horizontal separator:
typescript
{ divider: {} }See for all widget types with full examples.
See for all available knownIcon values.
references/widget-reference.mdreferences/icon-list.md文本段落 —— 格式化文本块:
typescript
{ textParagraph: { text: '*Bold* and _italic_ text' } }装饰文本 —— 标签+值,可带图标:
typescript
{
decoratedText: {
topLabel: 'Status',
text: 'Deployed',
startIcon: { knownIcon: 'STAR' }
}
}按钮列表 —— 操作按钮:
typescript
{
buttonList: {
buttons: [{
text: 'View Dashboard',
onClick: { openLink: { url: 'https://dashboard.example.com' } }
}]
}
}图片 —— 独立图片:
typescript
{ image: { imageUrl: 'https://example.com/chart.png', altText: 'Usage chart' } }分隔线 —— 水平分隔符:
typescript
{ divider: {} }查看获取所有组件类型及完整示例。
查看获取所有可用的knownIcon值。
references/widget-reference.mdreferences/icon-list.mdThreading
线程回复
Thread messages together using :
threadKeytypescript
// First message — creates thread
const response = await sendCard(webhookUrl, card, {
threadKey: 'deploy-2026-02-16'
});
// Reply to thread — append &messageReplyOption=REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD
const threadUrl = `${webhookUrl}&messageReplyOption=REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD`;
await sendCard(threadUrl, replyCard, {
threadKey: 'deploy-2026-02-16'
});The is a client-assigned string. Use consistent keys for related messages (e.g., , ).
threadKeydeploy-{date}alert-{id}使用将消息关联到同一线程:
threadKeytypescript
// 第一条消息 —— 创建线程
const response = await sendCard(webhookUrl, card, {
threadKey: 'deploy-2026-02-16'
});
// 回复线程 —— 追加&messageReplyOption=REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD
const threadUrl = `${webhookUrl}&messageReplyOption=REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD`;
await sendCard(threadUrl, replyCard, {
threadKey: 'deploy-2026-02-16'
});threadKeydeploy-{date}alert-{id}Common Patterns
常见模式
Notification Card
通知卡片
typescript
import { buildCard, sendCard } from './assets/card-builder';
import { sendWebhook } from './assets/webhook-sender';
const card = buildCard({
cardId: 'deploy-notification',
title: 'Deployment Complete',
subtitle: 'production - v2.1.0',
imageUrl: 'https://www.jezweb.com.au/wp-content/uploads/2020/03/favicon-100x100.png',
sections: [{
widgets: [
{ decoratedText: { topLabel: 'Environment', text: 'Production' } },
{ decoratedText: { topLabel: 'Version', text: 'v2.1.0' } },
{ decoratedText: { topLabel: 'Status', text: '*Healthy*', startIcon: { knownIcon: 'STAR' } } },
{ buttonList: { buttons: [{ text: 'View Deployment', onClick: { openLink: { url: 'https://dash.example.com' } } }] } }
]
}]
});typescript
import { buildCard, sendCard } from './assets/card-builder';
import { sendWebhook } from './assets/webhook-sender';
const card = buildCard({
cardId: 'deploy-notification',
title: 'Deployment Complete',
subtitle: 'production - v2.1.0',
imageUrl: 'https://www.jezweb.com.au/wp-content/uploads/2020/03/favicon-100x100.png',
sections: [{
widgets: [
{ decoratedText: { topLabel: 'Environment', text: 'Production' } },
{ decoratedText: { topLabel: 'Version', text: 'v2.1.0' } },
{ decoratedText: { topLabel: 'Status', text: '*Healthy*', startIcon: { knownIcon: 'STAR' } } },
{ buttonList: { buttons: [{ text: 'View Deployment', onClick: { openLink: { url: 'https://dash.example.com' } } }] } }
]
}]
});Digest Card (Weekly Summary)
摘要卡片(每周汇总)
typescript
const digest = buildCard({
cardId: 'weekly-digest',
title: 'Weekly Summary',
subtitle: `${count} updates this week`,
sections: [
{
header: 'Highlights',
widgets: items.map(item => ({
decoratedText: { text: item.title, bottomLabel: item.date }
}))
},
{
widgets: [{
buttonList: {
buttons: [{ text: 'View All', onClick: { openLink: { url: dashboardUrl } } }]
}
}]
}
]
});typescript
const digest = buildCard({
cardId: 'weekly-digest',
title: 'Weekly Summary',
subtitle: `${count} updates this week`,
sections: [
{
header: 'Highlights',
widgets: items.map(item => ({
decoratedText: { text: item.title, bottomLabel: item.date }
}))
},
{
widgets: [{
buttonList: {
buttons: [{ text: 'View All', onClick: { openLink: { url: dashboardUrl } } }]
}
}]
}
]
});Simple Text Alert
简单文本警报
typescript
await sendText(webhookUrl, `*Alert*: CPU usage above 90% on \`worker-prod-1\`\n<${alertUrl}|View Alert>`);typescript
await sendText(webhookUrl, `*Alert*: CPU usage above 90% on \`worker-prod-1\`\n<${alertUrl}|View Alert>`);Error Prevention
错误预防
| Mistake | Fix |
|---|---|
| Use |
| Use |
Missing | Wrap card in |
| Thread replies not threading | Append |
| Webhook returns 400 | Check JSON structure — common issue is missing |
| Card not showing | Ensure |
| 错误 | 修复方案 |
|---|---|
文本中使用 | 使用 |
使用 | 使用 |
缺少 | 将卡片包裹在 |
| 线程回复未关联到线程 | 在webhook URL后追加 |
| Webhook返回400错误 | 检查JSON结构——常见问题是顶层缺少 |
| 卡片未显示 | 确保 |
Asset Files
资源文件
| File | Purpose |
|---|---|
| TypeScript type definitions for cardsV2 |
| Utility to build card messages |
| POST to webhook with error handling |
| 文件 | 用途 |
|---|---|
| cardsV2的TypeScript类型定义 |
| 用于构建卡片消息的工具 |
| 向webhook发送POST请求并处理错误 |