mcpField
G
google-chat-api

google-chat-api

github.com/jezweb生产力1.1k314 次安装3 周前更新
代码仓库

关于 google-chat-api

google-chat-api 是面向构建 Google Chat 集成的开发者的技能,介绍通知 Webhook 与交互式机器人。还涵盖卡片、表单、对话框,以及空间、成员和表情回应的 API 操作。

主要功能

  1. 01通过 Webhook 发送通知
  2. 02构建交互式机器人和卡片
  3. 03处理消息、按钮与表单事件
  4. 04管理空间、成员和表情回应

适用场景

  1. 01向 Chat 空间发送 CI/CD 或监控通知
  2. 02在 Chat 中收集表单信息或审批
  3. 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.json
references/
cards-v2-schema.md
common-errors.md
google-chat-docs.md
templates/
bearer-token-verify.ts
card-builder-examples.ts
form-validation.ts
interactive-bot.ts
webhook-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

设置:

  1. 创建 Chat 空间
  2. 在空间设置中配置传入 Webhook
  3. 向 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

设置:

  1. 创建 Google Cloud 项目
  2. 启用 Chat API
  3. 配置使用 HTTP 端点的 Chat 应用
  4. 部署 Cloudflare Worker
  5. 处理事件并使用卡片响应

需要编写代码——请参阅 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)

官方文档


软件包版本(已于 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 空间中成功测试
  • 已处理所有事件类型的错误

有疑问?遇到问题?

  1. 查看 references/common-errors.md 以排查问题
  2. 确认卡片 JSON 结构符合 Cards v2 架构
  3. 查看官方文档:https://developers.google.com/workspace/chat
  4. 确保已为 HTTP 端点实现 Bearer 令牌验证

评论

支持 Markdown