关于 google-chat-api
google-chat-api 是面向构建 Google Chat 集成的开发者的技能,介绍通知 Webhook 与交互式机器人。还涵盖卡片、表单、对话框,以及空间、成员和表情回应的 API 操作。
主要功能
- 01通过 Webhook 发送通知
- 02构建交互式机器人和卡片
- 03处理消息、按钮与表单事件
- 04管理空间、成员和表情回应
适用场景
- 01向 Chat 空间发送 CI/CD 或监控通知
- 02在 Chat 中收集表单信息或审批
- 03创建空间并管理成员角色
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ jezweb/ claude-skills --skill google-chat-api安装后在 Claude Code 中输入/google-chat-api确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
README.md.claude-plugin/plugin.jsonreferences/cards-v2-schema.mdcommon-errors.mdgoogle-chat-docs.mdtemplates/bearer-token-verify.tscard-builder-examples.tsform-validation.tsinteractive-bot.tswebhook-handler.ts详细介绍
Google Chat API
状态:已可用于生产环境 最后更新:2026-01-09(新增:Spaces API、Members API、Reactions API、速率限制) 依赖项:Cloudflare Workers(推荐)、用于令牌验证的 Web Crypto API 最新版本:Google Chat API v1(稳定版)、Cards v2(Cards v1 已弃用)、[email protected]
快速入门(5 分钟)
1. 创建 Webhook(最简单的方法)
# No code needed - just configure in Google Chat
# 1. Go to Google Cloud Console
# 2. Create new project or select existing
# 3. Enable Google Chat API
# 4. Configure Chat app with webhook URL
Webhook URL:https://your-worker.workers.dev/webhook
为什么这很重要:
- 这是向 Chat 发送消息最简单的方法
- 传入 Webhook 无需身份验证
- 非常适合来自外部系统的通知
- 仅限发送消息(不支持交互式响应)
2. 创建交互式机器人(Cloudflare Worker)
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const event = await request.json()
// Respond with a card
return Response.json({
text: "Hello from bot!",
cardsV2: [{
cardId: "unique-card-1",
card: {
header: { title: "Welcome" },
sections: [{
widgets: [{
textParagraph: { text: "Click the button below" }
}, {
buttonList: {
buttons: [{
text: "Click me",
onClick: {
action: {
function: "handleClick",
parameters: [{ key: "data", value: "test" }]
}
}
}]
}
}]
}]
}
}]
})
}
}
关键事项:
- 必须在超时时间内响应(通常为 30 秒)
- 始终返回有效的 JSON,其中包含
cardsV2数组 - 卡片架构必须完全准确——一个字段错误就会导致整张卡片失效
3. 验证 Bearer 令牌(生产环境安全)
async function verifyToken(token: string): Promise<boolean> {
// Verify token is signed by [email protected]
// See templates/bearer-token-verify.ts for full implementation
return true
}
为什么这很重要:
- 防止未经授权访问你的机器人
- HTTP 端点需要此项(Webhook 除外)
- 使用 Web Crypto API(兼容 Cloudflare Workers)
三步设置流程
步骤 1:选择集成类型
选项 A:传入 Webhook(仅用于通知)
适用于:
- CI/CD 通知
- 警报系统
- 单向通信
- 外部服务 → Chat
设置:
- 创建 Chat 空间
- 在空间设置中配置传入 Webhook
- 向 Webhook URL 发送 POST JSON 请求
无需编写代码——只需发送 HTTP POST:
curl -X POST 'https://chat.googleapis.com/v1/spaces/.../messages?key=...' \
-H 'Content-Type: application/json' \
-d '{"text": "Hello from webhook!"}'
选项 B:HTTP 端点机器人(交互式)
适用于:
- 交互式表单
- 基于按钮的工作流
- 收集用户输入
- Chat → 你的服务 → Chat
设置:
- 创建 Google Cloud 项目
- 启用 Chat API
- 配置使用 HTTP 端点的 Chat 应用
- 部署 Cloudflare Worker
- 处理事件并使用卡片响应
需要编写代码——请参阅 templates/interactive-bot.ts
步骤 2:设计卡片(如果使用交互式机器人)
重要:仅使用 Cards v2。Cards v1 已于 2025 年弃用。Cards v2 在网页端采用 Material Design(渲染更快,外观更佳)。
Cards v2 结构:
{
"cardsV2": [{
"cardId": "unique-id",
"card": {
"header": {
"title": "Card Title",
"subtitle": "Optional subtitle",
"imageUrl": "https://..."
},
"sections": [{
"header": "Section 1",
"widgets": [
{ "textParagraph": { "text": "Some text" } },
{ "buttonList": { "buttons": [...] } }
]
}]
}
}]
}
组件类型:
textParagraph- 文本内容buttonList- 按钮(文本或图标)textInput- 文本输入框selectionInput- 下拉菜单、复选框、开关dateTimePicker- 日期/时间选择器divider- 水平分隔线image- 图片decoratedText- 带图标/按钮的文本
文本格式(新增:2025 年 9 月 - 正式发布):
Cards v2 同时支持 HTML 和 Markdown 格式:
// HTML formatting (traditional)
{
textParagraph: {
text: "This is <b>bold</b> and <i>italic</i> text with <font color='#ea9999'>color</font>"
}
}
// Markdown formatting (NEW - better for AI agents)
{
textParagraph: {
text: "This is **bold** and *italic* text\n\n- Bullet list\n- Second item\n\n```\ncode block\n```"
}
}
支持的 Markdown(文本消息和卡片):
**bold**或*italic*`code`表示行内代码- list item或1. ordered表示列表```code block```表示多行代码~strikethrough~
支持的 HTML(仅卡片):
<b>bold</b>、<i>italic</i>、<u>underline</u><font color="#FF0000">colored</font><a href="url">link</a>
Markdown 的重要性:大模型通常会直接输出 Markdown。2025 年 9 月之前,你必须将 Markdown 转换为 HTML。现在可以直接将 Markdown 传给 Chat。
关键事项:
- 每张卡片最多 100 个组件——超出后会被静默截断
- 组件顺序很重要——按从上到下的顺序显示
- cardId 必须唯一——使用时间戳或 UUID
步骤 3:处理用户交互
用户点击按钮或提交表单时:
export default {
async fetch(request: Request): Promise<Response> {
const event = await request.json()
// Check event type
if (event.type === 'MESSAGE') {
// User sent message
return handleMessage(event)
}
if (event.type === 'CARD_CLICKED') {
// User clicked button
const action = event.action.actionMethodName
const params = event.action.parameters
if (action === 'submitForm') {
return handleFormSubmission(event)
}
}
return Response.json({ text: "Unknown event" })
}
}
事件类型:
ADDED_TO_SPACE- 机器人已添加到空间REMOVED_FROM_SPACE- 机器人已移除MESSAGE- 用户发送了消息CARD_CLICKED- 用户点击了按钮/提交了表单
关键规则
务必做到
✅ 返回包含 cardsV2 数组结构的有效 JSON
✅ 为每张卡片设置唯一的 cardId
✅ 验证 HTTP 端点的 Bearer 令牌(生产环境)
✅ 处理所有事件类型(MESSAGE、CARD_CLICKED 等)
✅ 每张卡片的组件数量控制在 100 个以内
✅ 在服务器端验证表单输入
切勿执行
❌ 在代码中存储密钥(请使用 Cloudflare Workers 密钥) ❌ 单张卡片中的组件超过 100 个(会静默失败) ❌ 返回格式错误的 JSON(会导致整条消息失效) ❌ 跳过 Bearer 令牌验证(存在安全风险) ❌ 仅依赖客户端验证(请在服务端验证) ❌ 使用同步阻塞操作(有超时风险)
已知问题预防
此技能可预防 6 个有记录的问题:
问题 #1:Bearer 令牌验证失败(401)
错误:“未授权”或“凭据无效” 来源:Google Chat API 文档 原因:未验证令牌或使用了错误的验证方法 预防措施:模板包含 Web Crypto API 验证(兼容 Cloudflare Workers)
问题 #2:卡片 JSON 架构无效(400)
错误:“JSON 负载无效”或“未知字段”
来源:Cards v2 API 参考
原因:字段名称拼写错误、嵌套错误或包含额外字段
预防措施:使用 google-chat-cards 库或符合精确架构的模板
问题 #3:超出组件数量限制(静默失败)
错误:没有错误提示——超过 100 个的组件不会渲染 来源:Google Chat API 限制 原因:在单张卡片中添加了过多组件 预防措施:技能说明了 100 个组件的限制及分页模式
问题 #4:表单验证错误格式错误
错误:表单未向用户显示验证错误 来源:交互式卡片文档 原因:错误响应格式有误 预防措施:模板包含正确的错误格式:
{
"actionResponse": {
"type": "DIALOG",
"dialogAction": {
"actionStatus": {
"statusCode": "INVALID_ARGUMENT",
"userFacingMessage": "Email is required"
}
}
}
}
问题 #5:Webhook“无法连接”错误
错误:Chat 显示“无法连接到机器人” 来源:Webhook 设置指南 原因:URL 无法公开访问、发生超时或响应格式错误 预防措施:技能包含超时处理和响应格式验证
问题 #6:超出速率限制(429)
错误:“RESOURCE_EXHAUSTED”或状态码 429 来源:Google Chat API 配额 原因:超出每个项目、空间或用户的请求限制 预防措施:技能说明了速率限制和指数退避模式
配置文件参考
Cloudflare Worker(wrangler.jsonc)
{
"name": "google-chat-bot",
"main": "src/index.ts",
"compatibility_date": "2026-01-03",
"compatibility_flags": ["nodejs_compat"],
// Secrets (set with: wrangler secret put CHAT_BOT_TOKEN)
"vars": {
"ALLOWED_SPACES": "spaces/SPACE_ID_1,spaces/SPACE_ID_2"
}
}
这些设置的用途:
nodejs_compat- Web Crypto API(令牌验证)所必需- 密钥安全存储(不放在代码中)
- 用于配置的环境变量
常见模式
模式 1:通知机器人(Webhook)
// External service sends notification to Chat
async function sendNotification(webhookUrl: string, message: string) {
await fetch(webhookUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
text: message,
cardsV2: [{
cardId: `notif-${Date.now()}`,
card: {
header: { title: "Alert" },
sections: [{
widgets: [{
textParagraph: { text: message }
}]
}]
}
}]
})
})
}
适用场景:CI/CD 告警、监控通知、事件触发
模式 2:交互式表单
// Show form to collect data
function showForm() {
return {
cardsV2: [{
cardId: "form-card",
card: {
header: { title: "Enter Details" },
sections: [{
widgets: [
{
textInput: {
name: "email",
label: "Email",
type: "SINGLE_LINE",
hintText: "[email protected]"
}
},
{
selectionInput: {
name: "priority",
label: "Priority",
type: "DROPDOWN",
items: [
{ text: "Low", value: "low" },
{ text: "High", value: "high" }
]
}
},
{
buttonList: {
buttons: [{
text: "Submit",
onClick: {
action: {
function: "submitForm",
parameters: [{
key: "formId",
value: "contact-form"
}]
}
}
}]
}
}
]
}]
}
}]
}
}
适用场景:数据收集、审批工作流、创建工单
模式 3:对话框(模态窗口)
// Open modal dialog
function openDialog() {
return {
actionResponse: {
type: "DIALOG",
dialogAction: {
dialog: {
body: {
sections: [{
header: "Confirm Action",
widgets: [{
textParagraph: { text: "Are you sure?" }
}, {
buttonList: {
buttons: [
{
text: "Confirm",
onClick: {
action: { function: "confirm" }
}
},
{
text: "Cancel",
onClick: {
action: { function: "cancel" }
}
}
]
}
}]
}]
}
}
}
}
}
}
适用场景:确认、多步骤工作流、专注数据录入
使用随附资源
脚本(scripts/)
此技能没有可执行脚本。
模板(templates/)
所有项目必需:
templates/webhook-handler.ts- 基本 Webhook 接收器templates/wrangler.jsonc- Cloudflare Workers 配置
根据需要选用:
templates/interactive-bot.ts- 带事件处理的 HTTP 端点templates/card-builder-examples.ts- 常见卡片模式templates/form-validation.ts- 带错误响应的输入验证templates/bearer-token-verify.ts- 令牌验证工具
何时加载这些模板:用户要求以下操作时,Claude 应参考这些模板:
- 设置 Google Chat 机器人
- 创建交互式卡片
- 添加表单验证
- 验证 Bearer 令牌
- 处理按钮点击
参考资料(references/)
references/google-chat-docs.md- 重要文档链接references/cards-v2-schema.md- 完整卡片结构参考references/common-errors.md- 错误排查指南
Claude 应在以下情况加载这些资料:排查错误、设计卡片、了解 API
高级主题
斜杠命令
注册斜杠命令以执行快速操作:
// User types: /create-ticket Bug in login
if (event.message?.slashCommand?.commandName === 'create-ticket') {
const text = event.message.argumentText
return Response.json({
text: `Creating ticket: ${text}`,
cardsV2: [/* ticket confirmation card */]
})
}
使用场景:快速操作、快捷方式、高级用户功能
线程回复
在现有线程中回复:
return Response.json({
text: "Reply in thread",
thread: {
name: event.message.thread.name // Use existing thread
}
})
使用场景:对话、后续跟进、分组讨论
Spaces API
以编程方式管理 Google Chat 空间(聊天室)。需要Chat 管理员或应用权限。
可用方法
| 方法 | 描述 | 所需范围 |
|---|---|---|
spaces.create | 创建新空间 | chat.spaces.create |
spaces.delete | 删除空间 | chat.delete |
spaces.get | 获取空间详情 | chat.spaces.readonly |
spaces.list | 列出机器人加入的空间 | chat.spaces.readonly |
spaces.patch | 更新空间设置 | chat.spaces |
spaces.search | 根据条件搜索空间 | chat.spaces.readonly |
spaces.setup | 创建空间并添加成员 | chat.spaces.create |
spaces.findDirectMessage | 查找与特定用户的私信 | chat.spaces.readonly |
创建空间
async function createSpace(accessToken: string) {
const response = await fetch('https://chat.googleapis.com/v1/spaces', {
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
spaceType: 'SPACE', // or 'GROUP_CHAT', 'DIRECT_MESSAGE'
displayName: 'Project Team',
singleUserBotDm: false,
spaceDetails: {
description: 'Team collaboration space',
guidelines: 'Be respectful and on-topic'
}
})
})
return response.json()
}
列出空间(机器人可访问的空间)
async function listSpaces(accessToken: string) {
const response = await fetch(
'https://chat.googleapis.com/v1/spaces?pageSize=100',
{
headers: { 'Authorization': `Bearer ${accessToken}` }
}
)
const data = await response.json()
// Returns: { spaces: [...], nextPageToken: '...' }
return data.spaces
}
搜索空间
async function searchSpaces(accessToken: string, query: string) {
const params = new URLSearchParams({
query: query, // e.g., 'displayName:Project'
pageSize: '50'
})
const response = await fetch(
`https://chat.googleapis.com/v1/spaces:search?${params}`,
{
headers: { 'Authorization': `Bearer ${accessToken}` }
}
)
return response.json()
}
搜索查询语法:
displayName:Project- 名称包含“Project”spaceType:SPACE- 仅搜索空间(不包括私信)createTime>2025-01-01- 搜索指定日期之后创建的空间- 使用
AND/OR运算符组合条件
Members API
以编程方式管理空间成员身份。需要用户或应用授权。
可用方法
| 方法 | 描述 | 所需范围 |
|---|---|---|
spaces.members.create | 将成员添加到空间 | chat.memberships |
spaces.members.delete | 移除成员 | chat.memberships |
spaces.members.get | 获取成员详情 | chat.memberships.readonly |
spaces.members.list | 列出所有成员 | chat.memberships.readonly |
spaces.members.patch | 更新成员角色 | chat.memberships |
将成员添加到空间
async function addMember(accessToken: string, spaceName: string, userEmail: string) {
const response = await fetch(
`https://chat.googleapis.com/v1/${spaceName}/members`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
member: {
name: `users/${userEmail}`,
type: 'HUMAN' // or 'BOT'
},
role: 'ROLE_MEMBER' // or 'ROLE_MANAGER'
})
}
)
return response.json()
}
列出空间成员
async function listMembers(accessToken: string, spaceName: string) {
const response = await fetch(
`https://chat.googleapis.com/v1/${spaceName}/members?pageSize=100`,
{
headers: { 'Authorization': `Bearer ${accessToken}` }
}
)
return response.json()
// Returns: { memberships: [...], nextPageToken: '...' }
}
更新成员角色
async function updateMemberRole(
accessToken: string,
memberName: string, // e.g., 'spaces/ABC/members/DEF'
newRole: 'ROLE_MEMBER' | 'ROLE_MANAGER'
) {
const response = await fetch(
`https://chat.googleapis.com/v1/${memberName}?updateMask=role`,
{
method: 'PATCH',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ role: newRole })
}
)
return response.json()
}
成员角色:
ROLE_MEMBER- 普通成员(可读写消息)ROLE_MANAGER- 可管理空间设置和成员
Reactions API
为消息添加表情回应。此功能于 2025 年推出,支持自定义工作区表情符号。
可用方法
| 方法 | 描述 |
|---|---|
spaces.messages.reactions.create | 为消息添加回应 |
spaces.messages.reactions.delete | 移除回应 |
spaces.messages.reactions.list | 列出消息的回应 |
添加回应
async function addReaction(
accessToken: string,
messageName: string, // e.g., 'spaces/ABC/messages/XYZ'
emoji: string
) {
const response = await fetch(
`https://chat.googleapis.com/v1/${messageName}/reactions`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
emoji: {
unicode: emoji // e.g., '👍' or custom emoji code
}
})
}
)
return response.json()
}
列出回应
async function listReactions(accessToken: string, messageName: string) {
const response = await fetch(
`https://chat.googleapis.com/v1/${messageName}/reactions?pageSize=100`,
{
headers: { 'Authorization': `Bearer ${accessToken}` }
}
)
return response.json()
// Returns: { reactions: [...], nextPageToken: '...' }
}
自定义表情符号:工作区管理员可以上传自定义表情符号。使用表情符号的 customEmoji.uid,而不是 unicode。
速率限制
Google Chat API 会强制实施严格的配额,以防止滥用。对于生产应用,了解这些限制至关重要。
每个项目的配额(每分钟)
| 操作 | 限制 | 备注 |
|---|---|---|
| 读取操作 | 3,000/分钟 | spaces.get、members.list、messages.list |
| 成员身份写入 | 300/分钟 | members.create、members.delete |
| 空间写入 | 60/分钟 | spaces.create、spaces.patch |
| 消息操作 | 600/分钟 | messages.create、reactions.create |
| 回应 | 600/分钟 | 与消息操作共用配额 |
每个空间的配额(每秒)
| 操作 | 限制 |
|---|---|
| 读取操作 | 15/秒 |
| 写入操作 | 1/秒 |
每个用户的配额
经过用户身份验证的请求也会按用户进行限流:
- 对于大多数操作,每位用户 60 次请求/分钟
- 创建空间时,每位用户 10 次请求/分钟
处理速率限制错误
async function withRetry<T>(
fn: () => Promise<T>,
maxRetries = 3
): Promise<T> {
for (let i = 0; i < maxRetries; i++) {
try {
return await fn()
} catch (error: any) {
if (error.status === 429) {
// Rate limited - wait with exponential backoff
const waitMs = Math.pow(2, i) * 1000 + Math.random() * 1000
await new Promise(r => setTimeout(r, waitMs))
continue
}
throw error
}
}
throw new Error('Max retries exceeded')
}
// Usage
const spaces = await withRetry(() => listSpaces(accessToken))
最佳实践:
- 尽可能缓存读取操作
- 批量执行成员操作
- 高效使用分页(请求较大的页面,减少请求次数)
- 针对 429 错误实现指数退避
- 在 Google Cloud Console 中监控配额使用情况
依赖项
必需:
- Cloudflare Workers 账号(免费套餐即可)
- 已启用 Chat API 的 Google Cloud Project
- 公共 HTTPS 端点(Workers 会提供)
可选:
[email protected]- 类型安全的卡片构建器(非官方)- Web Crypto API(内置于 Cloudflare Workers)
官方文档
- Google Chat API:https://developers.google.com/workspace/chat
- Cards v2 参考:https://developers.google.com/workspace/chat/api/reference/rest/v1/cards
- Webhook 指南:https://developers.google.com/workspace/chat/quickstart/webhooks
- 交互式卡片:https://developers.google.com/workspace/chat/dialogs
- Cloudflare Workers:https://developers.cloudflare.com/workers
软件包版本(已于 2026-01-09 验证)
{
"dependencies": {
"google-chat-cards": "^1.0.3"
},
"devDependencies": {
"@cloudflare/workers-types": "^4.20260109.0",
"wrangler": "^4.58.0"
}
}
注意:没有官方的 Google Chat npm 软件包,请直接使用 fetch API。
生产环境示例
此技能基于真实世界的实现:
- 社区示例:translatebot(Worker + Chat + Translate API)
- 官方示例:Google 文档中的多个可用示例
令牌节省:约 65-70%(8k → 2.5k 个令牌) 避免的错误:6/6 个已记录问题 验证:✅ Webhook 处理程序,✅ 卡片构建器,✅ 令牌验证,✅ 表单验证,✅ 速率限制处理
故障排除
问题:“Unauthorized”(401)错误
解决方案:实现 Bearer 令牌验证(参见 templates/bearer-token-verify.ts)
问题:卡片无法呈现 / “Invalid JSON payload”
解决方案:根据 Cards v2 架构验证卡片 JSON,确保字段名称完全正确
问题:第 100 个之后的小组件不显示
解决方案:拆分为多张卡片或使用分页
问题:表单验证错误未显示给用户
解决方案:使用 actionResponse.dialogAction.actionStatus 返回正确的错误格式
问题:“Unable to connect to bot”
解决方案:确保 URL 可公开访问、在超时前响应并返回有效 JSON
完整设置检查清单
使用此检查清单验证设置:
- 已创建 Google Cloud 项目
- 已在项目中启用 Chat API
- 已将 Chat 应用配置为使用 webhook/HTTP 端点 URL
- Cloudflare Worker 已部署且可访问
- 已实现 Bearer 令牌验证(如果使用 HTTP 端点)
- 已根据架构验证卡片 JSON
- 每张卡片的小组件数量少于 100
- 表单验证返回正确的错误格式
- 已在 Chat 空间中成功测试
- 已处理所有事件类型的错误
有疑问?遇到问题?
- 查看
references/common-errors.md以排查问题 - 确认卡片 JSON 结构符合 Cards v2 架构
- 查看官方文档:https://developers.google.com/workspace/chat
- 确保已为 HTTP 端点实现 Bearer 令牌验证