OpenClaw 消息工具详解:多渠道消息发送实战指南

目录

    • 摘要
    • [1. 引言:消息工具的重要性](#1. 引言:消息工具的重要性)
      • [1.1 为什么需要统一的消息工具](#1.1 为什么需要统一的消息工具)
      • [1.2 OpenClaw 消息工具的设计理念](#1.2 OpenClaw 消息工具的设计理念)
    • [2. message 工具核心概念](#2. message 工具核心概念)
      • [2.1 工具定义与参数](#2.1 工具定义与参数)
      • [2.2 消息发送流程](#2.2 消息发送流程)
    • [3. 多渠道消息发送](#3. 多渠道消息发送)
      • [3.1 支持的渠道概览](#3.1 支持的渠道概览)
      • [3.2 Telegram 消息发送](#3.2 Telegram 消息发送)
      • [3.3 飞书消息发送](#3.3 飞书消息发送)
      • [3.4 Discord 消息发送](#3.4 Discord 消息发送)
      • [3.5 Slack 消息发送](#3.5 Slack 消息发送)
    • [4. 消息格式与样式](#4. 消息格式与样式)
      • [4.1 文本格式化](#4.1 文本格式化)
      • [4.2 表格处理](#4.2 表格处理)
      • [4.3 代码块处理](#4.3 代码块处理)
    • [5. 富文本与卡片消息](#5. 富文本与卡片消息)
      • [5.1 卡片消息概述](#5.1 卡片消息概述)
      • [5.2 飞书卡片消息](#5.2 飞书卡片消息)
      • [5.3 Discord Embed 消息](#5.3 Discord Embed 消息)
    • [6. 消息回复与引用](#6. 消息回复与引用)
      • [6.1 回复消息](#6.1 回复消息)
      • [6.2 引用消息](#6.2 引用消息)
      • [6.3 线程消息](#6.3 线程消息)
    • [7. 消息撤回与编辑](#7. 消息撤回与编辑)
      • [7.1 消息编辑](#7.1 消息编辑)
      • [7.2 消息撤回](#7.2 消息撤回)
    • [8. 跨会话消息发送](#8. 跨会话消息发送)
      • [8.1 使用场景](#8.1 使用场景)
      • [8.2 实现方式](#8.2 实现方式)
      • [8.3 权限控制](#8.3 权限控制)
    • [9. 实战案例](#9. 实战案例)
      • [9.1 案例一:智能客服通知系统](#9.1 案例一:智能客服通知系统)
      • [9.2 案例二:多平台监控告警](#9.2 案例二:多平台监控告警)
      • [9.3 案例三:交互式问卷系统](#9.3 案例三:交互式问卷系统)
    • [10. 最佳实践与注意事项](#10. 最佳实践与注意事项)
      • [10.1 性能优化建议](#10.1 性能优化建议)
      • [10.2 安全注意事项](#10.2 安全注意事项)
      • [10.3 常见问题与解决方案](#10.3 常见问题与解决方案)
    • [11. 总结](#11. 总结)
    • 参考资料

摘要

消息发送是 AI Agent 与用户交互的核心桥梁,OpenClaw 的 message 工具提供了强大而灵活的多渠道消息发送能力。本文深入剖析 message 工具的设计理念、核心参数、多渠道适配机制,以及富文本消息、卡片消息、消息回复与引用、消息撤回与编辑等高级功能。通过 Telegram、飞书、Discord、Slack、WhatsApp 等主流平台的实战案例,帮助读者掌握跨平台消息发送的最佳实践。无论你是构建智能客服、自动化通知系统,还是企业协作机器人,本文都将为你提供完整的技术指南。


1. 引言:消息工具的重要性

在 AI Agent 的世界里,消息是连接智能与用户的纽带。一个设计良好的消息系统,不仅要能发送文本,还要支持富媒体、交互组件、跨平台适配等复杂需求。OpenClaw 的 message 工具正是为此而生。

1.1 为什么需要统一的消息工具

想象这样一个场景:你开发了一个 AI 助手,最初只在 Telegram 上运行。随着用户需求增长,你需要将其扩展到飞书、Discord、Slack 等多个平台。如果没有统一的消息抽象层,你将面临以下挑战:

挑战 具体问题 影响
API 差异 每个平台的消息 API 参数、格式各不相同 开发成本成倍增加
功能差异 有的平台支持卡片消息,有的不支持 功能实现不一致
限流策略 不同平台的频率限制、消息长度限制不同 需要针对每个平台适配
媒体处理 图片、文件的上传方式各不相同 媒体发送逻辑复杂
交互组件 按钮、表单等交互元素实现方式迥异 用户体验难以统一

OpenClaw 的 message 工具通过统一的抽象层解决了这些问题。开发者只需调用一个工具,指定目标渠道和消息内容,框架会自动处理平台差异,实现"一次编写,多端运行"。

1.2 OpenClaw 消息工具的设计理念

OpenClaw 的消息工具设计遵循以下核心原则:

统一接口,平台适配

无论目标平台是 Telegram、飞书还是 Discord,调用方式保持一致。框架内部根据渠道类型自动选择合适的发送策略。
🌐 平台 API
🔌 渠道适配层
🔧 消息工具抽象层
👤 用户层
AI Agent 调用
message 工具
参数解析与验证
渠道路由
Telegram 适配器
飞书适配器
Discord 适配器
Slack 适配器
WhatsApp 适配器
Telegram Bot API
飞书开放平台
Discord Gateway
Slack Web API
WhatsApp Web API

功能丰富,扩展灵活

message 工具不仅支持基础文本发送,还涵盖:

  • 富文本格式化(Markdown、HTML)
  • 媒体文件发送(图片、视频、文档)
  • 交互式卡片消息
  • 消息回复与引用
  • 消息撤回与编辑
  • 投票与问卷
  • 表情反应

安全可控,权限精细

通过 groupPolicyallowFrom 等配置,可以精确控制消息发送权限,防止滥用。


2. message 工具核心概念

2.1 工具定义与参数

message 工具是 OpenClaw 提供的核心工具之一,用于发送、删除和管理消息。其定义包含丰富的参数,支持多种消息操作。

核心参数说明

参数名 类型 必填 说明
action string 操作类型:send、broadcast 等
target string 目标渠道/用户 ID,省略则回复当前会话
message string 消息文本内容
channel string 指定渠道类型,如 telegram、feishu
channelId string 指定渠道内的目标 ID
media string 媒体文件 URL 或本地路径
replyTo string 回复的消息 ID
silent boolean 静默发送,不触发通知

目标参数解析

message 工具支持多种目标指定方式,灵活适应不同场景:

yaml 复制代码
# 方式一:直接指定目标(推荐)
target: "telegram:-1001234567890"  # Telegram 群组
target: "feishu:ou_xxxxx"          # 飞书用户
target: "discord:123456789"        # Discord 频道

# 方式二:分离指定
channel: "telegram"
channelId: "-1001234567890"

# 方式三:省略目标(回复当前会话)
# 在对话上下文中,AI 自动推断回复目标
message: "这是回复消息"

2.2 消息发送流程

当 AI Agent 调用 message 工具发送消息时,OpenClaw 内部会经历以下处理流程:
平台 API Discord 适配器 飞书适配器 Telegram 适配器 路由层 message 工具 AI Agent 平台 API Discord 适配器 飞书适配器 Telegram 适配器 路由层 message 工具 AI Agent alt [Telegram 渠道] [飞书渠道] [Discord 渠道] 调用 message 工具 解析参数 验证权限 路由到目标渠道 调用 Telegram 适配器 sendMessage API 返回 messageId 发送结果 调用飞书适配器 im.message.create 返回 messageId 发送结果 调用 Discord 适配器 创建消息 返回 messageId 发送结果 返回发送结果

这个流程展示了 OpenClaw 如何通过统一的工具接口,实现对不同平台的无缝适配。对于 AI Agent 而言,它只需要调用 message 工具,无需关心底层平台差异。


3. 多渠道消息发送

OpenClaw 原生支持 20+ 消息平台,每个平台都有其独特的配置方式和发送特性。本节将详细介绍主流平台的接入与消息发送方法。

3.1 支持的渠道概览

渠道 类型 特点 适用场景
Telegram 即时通讯 Bot API 成熟,支持频道、群组、私聊 国际化应用、社区运营
飞书/Lark 企业协作 卡片消息丰富,支持文档、审批集成 企业内部应用、办公自动化
Discord 社区平台 支持服务器、频道、线程,游戏社区活跃 游戏社区、技术社区
Slack 企业协作 企业级功能完善,支持 App、Slash 命令 企业办公、团队协作
WhatsApp 即时通讯 用户基数大,支持个人和商业账号 客户服务、营销触达
微信企业号 企业协作 国内企业首选,与微信生态打通 国内企业办公
钉钉 企业协作 阿里生态,支持钉钉小程序 阿里系企业应用
Matrix 去中心化 开源协议,支持联邦部署 隐私敏感场景
Signal 加密通讯 端到端加密,隐私保护强 安全通信场景
IRC 传统聊天 轻量级,兼容性好 技术社区、开源项目

3.2 Telegram 消息发送

Telegram 是 OpenClaw 支持最完善的渠道之一,具有 API 稳定、功能丰富、文档完善等优点。

配置示例

yaml 复制代码
channels:
  telegram:
    enabled: true
    botToken: "123456789:ABCdefGHIjklMNOpqrsTUVwxyz"  # Bot Token
    dmPolicy: "pairing"      # 私聊策略:pairing/open/allowlist
    groupPolicy: "open"      # 群聊策略
    allowFrom: []            # 允许的用户列表
    groups:                  # 群组配置
      "-1001234567890":
        requireMention: true # 需要 @ 提及才响应

上述配置展示了 Telegram 渠道的基本设置。botToken 是从 BotFather 获取的机器人令牌,是连接 Telegram API 的关键凭证。dmPolicy 控制私聊权限策略,pairing 表示需要用户先与机器人配对才能对话。groupPolicy 控制群聊权限,open 表示任何群都可以添加机器人。groups 配置允许对特定群组进行精细化控制,如设置 requireMention 要求用户必须 @ 机器人才会响应。

消息发送代码示例

python 复制代码
# Telegram 消息发送核心逻辑
async def send_telegram_message(
    chat_id: str,
    text: str,
    token: str,
    reply_to_message_id: str = None,
    message_thread_id: int = None,
    silent: bool = False
):
    """
    发送 Telegram 消息
    
    Args:
        chat_id: 目标聊天 ID(用户 ID、群组 ID 或频道 ID)
        text: 消息文本内容(支持 Markdown 和 HTML 格式)
        token: Bot Token
        reply_to_message_id: 回复的消息 ID
        message_thread_id: 话题/线程 ID(用于论坛群组)
        silent: 是否静默发送(无通知)
    
    Returns:
        dict: 包含 messageId 和发送状态的字典
    """
    url = f"https://api.telegram.org/bot{token}/sendMessage"
    
    payload = {
        "chat_id": chat_id,
        "text": text,
        "parse_mode": "Markdown"  # 支持 Markdown 格式
    }
    
    # 可选参数
    if reply_to_message_id:
        payload["reply_to_message_id"] = reply_to_message_id
    if message_thread_id:
        payload["message_thread_id"] = message_thread_id
    if silent:
        payload["disable_notification"] = True
    
    async with aiohttp.ClientSession() as session:
        async with session.post(url, json=payload) as resp:
            result = await resp.json()
            if result.get("ok"):
                message_id = result["result"]["message_id"]
                return {"messageId": str(message_id), "chatId": chat_id}
            else:
                raise Exception(f"Telegram send failed: {result.get('description')}")

上述代码展示了 Telegram 消息发送的核心实现。函数接收聊天 ID、消息文本和 Bot Token 作为主要参数,构造 API 请求并发送。parse_mode 设置为 Markdown 表示消息支持 Markdown 格式化。可选参数包括回复消息 ID、话题线程 ID 和静默发送标志。函数返回包含 messageIdchatId 的字典,便于后续操作如编辑或删除消息。

3.3 飞书消息发送

飞书(Lark)是字节跳动的企业协作平台,提供了丰富的消息能力,特别是交互式卡片消息。

配置示例

yaml 复制代码
channels:
  feishu:
    enabled: true
    appId: "cli_xxxxxxxxxxxxxxxx"           # 应用 ID
    appSecret: "xxxxxxxxxxxxxxxxxxxxxxxx"   # 应用密钥
    encryptKey: ""                          # 消息加密密钥(可选)
    verificationToken: ""                   # 验证令牌(可选)
    domain: "feishu"                        # 域名:feishu 或 lark
    connectionMode: "websocket"             # 连接模式:websocket/webhook
    dmPolicy: "pairing"                     # 私聊策略
    groupPolicy: "open"                     # 群聊策略
    renderMode: "auto"                      # 渲染模式:auto/raw/card

飞书配置需要从飞书开放平台获取 appIdappSecretdomain 区分国内版(feishu)和国际版(lark)。connectionMode 支持两种模式:websocket 使用长连接,适合服务器环境;webhook 使用 HTTP 回调,需要公网可访问的地址。renderMode 控制消息渲染方式,auto 会根据内容自动选择文本或卡片格式。

消息发送代码示例

python 复制代码
# 飞书消息发送核心逻辑
async def send_feishu_message(
    receive_id: str,
    text: str,
    client: FeishuClient,
    receive_id_type: str = "open_id",
    reply_to_message_id: str = None
):
    """
    发送飞书消息
    
    Args:
        receive_id: 接收者 ID(open_id、user_id 或 chat_id)
        text: 消息文本内容(支持 Markdown 格式)
        client: 飞书客户端实例
        receive_id_type: ID 类型(open_id/user_id/chat_id)
        reply_to_message_id: 回复的消息 ID
    
    Returns:
        dict: 包含 messageId 的发送结果
    """
    # 构建消息体(富文本格式)
    content = json.dumps({
        "zh_cn": {
            "content": [
                [
                    {
                        "tag": "md",
                        "text": text
                    }
                ]
            ]
        }
    })
    
    if reply_to_message_id:
        # 回复消息
        response = await client.im.message.reply(
            path={"message_id": reply_to_message_id},
            data={
                "content": content,
                "msg_type": "post"
            }
        )
    else:
        # 发送新消息
        response = await client.im.message.create(
            params={"receive_id_type": receive_id_type},
            data={
                "receive_id": receive_id,
                "content": content,
                "msg_type": "post"
            }
        )
    
    if response.code == 0:
        message_id = response.data.get("message_id")
        return {"messageId": message_id, "chatId": receive_id}
    else:
        raise Exception(f"Feishu send failed: {response.msg}")

上述代码展示了飞书消息发送的核心实现。飞书使用富文本格式(msg_type: "post")发送消息,内容需要构造为 JSON 结构。receive_id_type 指定 ID 类型,open_id 是推荐的用户标识方式。回复消息使用 im.message.reply API,发送新消息使用 im.message.create API。飞书 API 返回 code 字段表示操作结果,0 表示成功。

3.4 Discord 消息发送

Discord 是游戏和技术社区的热门平台,支持服务器、频道、线程等多层次结构。

配置示例

yaml 复制代码
channels:
  discord:
    enabled: true
    token: "MTk4NjIyNDgzNDc..."  # Bot Token
    dm:
      policy: "pairing"           # 私聊策略
      allowFrom: []               # 允许的用户 ID 列表
    groupPolicy: "open"           # 群组策略
    guilds:                       # 服务器配置
      "123456789012345678":
        channels:
          "987654321098765432":
            requireMention: false

Discord 配置需要从 Discord Developer Portal 创建应用并获取 Bot Token。guilds 配置允许对特定服务器的特定频道进行精细控制。Discord 的权限模型比较复杂,需要在 Developer Portal 中配置 Intents 才能接收消息事件。

消息发送代码示例

python 复制代码
# Discord 消息发送核心逻辑
async def send_discord_message(
    channel_id: str,
    text: str,
    token: str,
    reply_to_id: str = None,
    silent: bool = False
):
    """
    发送 Discord 消息
    
    Args:
        channel_id: 目标频道 ID 或用户 ID(格式:user:ID)
        text: 消息文本内容(支持 Markdown 格式)
        token: Bot Token
        reply_to_id: 回复的消息 ID
        silent: 是否静默发送
    
    Returns:
        dict: 包含 messageId 的发送结果
    """
    # 判断是私聊还是频道
    if channel_id.startswith("user:"):
        # 私聊:先创建 DM 频道
        user_id = channel_id.replace("user:", "")
        dm_url = f"https://discord.com/api/v10/users/@me/channels"
        dm_payload = {"recipient_id": user_id}
        
        async with aiohttp.ClientSession() as session:
            async with session.post(
                dm_url,
                json=dm_payload,
                headers={"Authorization": f"Bot {token}"}
            ) as dm_resp:
                dm_data = await dm_resp.json()
                target_channel_id = dm_data["id"]
    else:
        target_channel_id = channel_id
    
    # 发送消息
    url = f"https://discord.com/api/v10/channels/{target_channel_id}/messages"
    payload = {"content": text}
    
    if reply_to_id:
        payload["message_reference"] = {"message_id": reply_to_id}
    if silent:
        payload["flags"] = 4096  # SUPPRESS_NOTIFICATIONS
    
    async with aiohttp.ClientSession() as session:
        async with session.post(
            url,
            json=payload,
            headers={"Authorization": f"Bot {token}"}
        ) as resp:
            result = await resp.json()
            message_id = result.get("id")
            return {"messageId": message_id, "channel": "discord"}

上述代码展示了 Discord 消息发送的实现。Discord 的私聊需要先创建 DM 频道,然后才能发送消息。message_reference 字段用于实现消息回复功能。flags 字段设置为 4096 可以静默发送消息,不触发接收者的通知。Discord API 使用 REST 风格,通过 Authorization 头传递 Bot Token。

3.5 Slack 消息发送

Slack 是企业协作的主流平台,支持丰富的消息格式和交互组件。

配置示例

yaml 复制代码
channels:
  slack:
    enabled: true
    botToken: "xoxb-xxxxxxxxxxxx-xxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxx"  # Bot Token
    appToken: "xapp-x-x-xxxxxxxxxxxx-xxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxx"  # App Token
    dm:
      policy: "pairing"
      allowFrom: []
    groupPolicy: "open"
    channels:
      "C1234567890":
        requireMention: true

Slack 配置需要两种 Token:botToken(xoxb- 开头)用于 API 调用,appToken(xapp- 开头)用于 Socket Mode 连接。Slack 的权限系统比较复杂,需要在应用配置页面添加相应的 OAuth Scopes。


4. 消息格式与样式

不同平台对消息格式的支持程度不同,OpenClaw 通过智能适配,让开发者能够用统一的方式发送格式化消息。

4.1 文本格式化

Markdown 支持

大多数平台都支持 Markdown 格式,但具体语法略有差异:

格式 Markdown 语法 Telegram 飞书 Discord Slack
粗体 **text**
斜体 *text*_text_
删除线 ~~text~~
代码 code
代码块 ` ```code````
链接 [text](url)
引用 > text
列表 - item

平台特定格式

某些平台支持特定的格式化语法:

markdown 复制代码
<!-- Telegram 特有 -->
[inline mention](tg://user?id=123456789)  <!-- 内联提及用户 -->

<!-- Discord 特有 -->
<@123456789>      <!-- 提及用户 -->
<#987654321>      <!-- 提及频道 -->
<@&111222333>     <!-- 提及角色 -->

<!-- Slack 特有 -->
<@U12345678>      <!-- 提及用户 -->
<#C12345678>      <!-- 提及频道 -->
<!here>           <!-- @here 提及 -->
<!channel>        <!-- @channel 提及 -->

4.2 表格处理

Markdown 表格在不同平台的渲染效果差异较大。OpenClaw 提供了智能表格处理机制:
飞书
Telegram
Discord
Slack
消息包含表格
渠道类型
转换为卡片表格
转换为图片
转换为代码块
转换为代码块
发送卡片消息
发送图片消息
发送格式化文本

飞书卡片表格示例

飞书支持在卡片消息中渲染表格,效果最佳:

json 复制代码
{
  "schema": "2.0",
  "config": {
    "wide_screen_mode": true
  },
  "body": {
    "elements": [
      {
        "tag": "markdown",
        "content": "| 列1 | 列2 | 列3 |\n|-----|-----|-----|\n| A | B | C |\n| D | E | F |"
      }
    ]
  }
}

4.3 代码块处理

代码块是技术文档和错误信息展示的重要方式。OpenClaw 支持语法高亮和自动格式化:

python 复制代码
# 代码块示例
def hello_world():
    """这是一个示例函数"""
    print("Hello, OpenClaw!")
    return True

if __name__ == "__main__":
    hello_world()

上述代码块展示了 Python 代码的格式化效果。OpenClaw 会根据目标平台自动选择最佳的代码块渲染方式,确保代码可读性。


5. 富文本与卡片消息

卡片消息是现代聊天平台的重要特性,支持丰富的布局、交互组件和动态内容。

5.1 卡片消息概述

卡片消息相比纯文本消息具有以下优势:

特性 纯文本消息 卡片消息
布局控制 单一流式布局 多列、分区布局
交互组件 仅链接可点击 按钮、选择器、输入框
媒体展示 单张图片 图片、视频、图标组合
动态更新 需编辑整条消息 可更新特定区域
品牌定制 自定义颜色、样式

5.2 飞书卡片消息

飞书的卡片消息功能最为完善,支持复杂的交互逻辑。

基础卡片结构

json 复制代码
{
  "schema": "2.0",
  "config": {
    "wide_screen_mode": true
  },
  "header": {
    "title": {
      "tag": "plain_text",
      "content": "卡片标题"
    },
    "subtitle": {
      "tag": "plain_text",
      "content": "卡片副标题"
    },
    "template": "blue"
  },
  "body": {
    "elements": [
      {
        "tag": "div",
        "text": {
          "tag": "lark_md",
          "content": "**正文内容**,支持 *Markdown* 格式"
        }
      },
      {
        "tag": "action",
        "actions": [
          {
            "tag": "button",
            "text": {
              "tag": "plain_text",
              "content": "确认"
            },
            "type": "primary",
            "value": {
              "action": "confirm"
            }
          },
          {
            "tag": "button",
            "text": {
              "tag": "plain_text",
              "content": "取消"
            },
            "type": "default",
            "value": {
              "action": "cancel"
            }
          }
        ]
      }
    ]
  }
}

上述 JSON 结构展示了飞书卡片消息的基本框架。schema 指定卡片版本,config 配置显示模式。header 定义卡片头部,包含标题、副标题和主题色。body 包含卡片主体内容,div 元素用于展示文本,action 元素包含交互按钮。按钮的 value 字段会在用户点击时传递给回调处理函数。

卡片消息发送代码

python 复制代码
async def send_feishu_card(
    receive_id: str,
    card: dict,
    client: FeishuClient,
    receive_id_type: str = "open_id"
):
    """
    发送飞书卡片消息
    
    Args:
        receive_id: 接收者 ID
        card: 卡片 JSON 结构
        client: 飞书客户端
        receive_id_type: ID 类型
    
    Returns:
        dict: 发送结果
    """
    content = json.dumps(card)
    
    response = await client.im.message.create(
        params={"receive_id_type": receive_id_type},
        data={
            "receive_id": receive_id,
            "content": content,
            "msg_type": "interactive"  # 卡片消息类型
        }
    )
    
    if response.code == 0:
        return {"messageId": response.data.get("message_id")}
    else:
        raise Exception(f"Card send failed: {response.msg}")

上述代码展示了飞书卡片消息的发送方法。关键点是将 msg_type 设置为 interactive,并将卡片 JSON 序列化为字符串作为 content。卡片消息支持动态更新,可以通过 im.message.patch API 更新已发送的卡片内容。

5.3 Discord Embed 消息

Discord 使用 Embed 结构实现富文本消息:

python 复制代码
async def send_discord_embed(
    channel_id: str,
    embed: dict,
    token: str
):
    """
    发送 Discord Embed 消息
    
    Args:
        channel_id: 目标频道 ID
        embed: Embed 结构
        token: Bot Token
    
    Returns:
        dict: 发送结果
    """
    url = f"https://discord.com/api/v10/channels/{channel_id}/messages"
    
    payload = {
        "embeds": [embed]  # Discord 支持一次发送多个 Embed
    }
    
    async with aiohttp.ClientSession() as session:
        async with session.post(
            url,
            json=payload,
            headers={"Authorization": f"Bot {token}"}
        ) as resp:
            result = await resp.json()
            return {"messageId": result.get("id")}

Embed 结构示例

json 复制代码
{
  "title": "Embed 标题",
  "description": "Embed 描述内容",
  "url": "https://example.com",
  "color": 5814783,
  "fields": [
    {
      "name": "字段1",
      "value": "字段值",
      "inline": true
    },
    {
      "name": "字段2", 
      "value": "字段值",
      "inline": true
    }
  ],
  "footer": {
    "text": "页脚文本",
    "icon_url": "https://example.com/icon.png"
  },
  "thumbnail": {
    "url": "https://example.com/thumbnail.png"
  },
  "image": {
    "url": "https://example.com/image.png"
  }
}

6. 消息回复与引用

消息回复和引用是对话场景中的常见需求,OpenClaw 提供了统一的支持方式。

6.1 回复消息

回复消息时,目标平台会在原消息下方显示关联,形成对话线索。

参数说明

参数 说明 示例
replyTo 回复的消息 ID "12345"
message 回复内容 "这是回复内容"
target 目标渠道(可选) "telegram:-1001234567890"

各平台回复机制
📨 消息回复机制
Telegram

reply_to_message_id
飞书

im.message.reply
Discord

message_reference
Slack

thread_ts
WhatsApp

quoted message
message 工具

replyTo 参数

代码示例

python 复制代码
# 回复消息的统一调用方式
await message_tool.invoke({
    "action": "send",
    "target": "telegram:-1001234567890",
    "message": "这是回复内容",
    "replyTo": "12345"  # 原消息 ID
})

6.2 引用消息

引用消息与回复消息类似,但不会形成回复线索,而是在消息中显示引用内容。

飞书引用消息

飞书支持在消息中引用其他消息的内容:

json 复制代码
{
  "zh_cn": {
    "content": [
      [
        {
          "tag": "quote",
          "text": "这是被引用的消息内容"
        }
      ],
      [
        {
          "tag": "text",
          "text": "这是回复内容"
        }
      ]
    ]
  }
}

6.3 线程消息

Discord 和 Slack 支持线程功能,可以在主消息下创建讨论线程:

python 复制代码
# Discord 线程消息
await send_discord_message(
    channel_id="123456789",
    text="这是线程中的消息",
    thread_id="987654321"  # 线程 ID
)

# Slack 线程消息
await send_slack_message(
    channel="C1234567890",
    text="这是线程中的消息",
    thread_ts="1234567890.123456"  # 线程时间戳
)

7. 消息撤回与编辑

消息发送后,有时需要修改或撤回。OpenClaw 支持这些操作,但不同平台的限制不同。

7.1 消息编辑

平台限制对比

平台 时间限制 内容限制 API
Telegram 无限制 仅可编辑自己的消息 editMessageText
飞书 24 小时 仅可编辑自己的消息 im.message.update
Discord 无限制 仅可编辑自己的消息 PATCH /messages/{id}
Slack 无限制 仅可编辑自己的消息 chat.update
WhatsApp 不支持 - -

编辑消息代码示例

python 复制代码
async def edit_telegram_message(
    chat_id: str,
    message_id: str,
    new_text: str,
    token: str
):
    """
    编辑 Telegram 消息
    
    Args:
        chat_id: 聊天 ID
        message_id: 要编辑的消息 ID
        new_text: 新的消息内容
        token: Bot Token
    
    Returns:
        dict: 编辑结果
    """
    url = f"https://api.telegram.org/bot{token}/editMessageText"
    
    payload = {
        "chat_id": chat_id,
        "message_id": int(message_id),
        "text": new_text,
        "parse_mode": "Markdown"
    }
    
    async with aiohttp.ClientSession() as session:
        async with session.post(url, json=payload) as resp:
            result = await resp.json()
            if result.get("ok"):
                return {"success": True, "messageId": message_id}
            else:
                raise Exception(f"Edit failed: {result.get('description')}")

上述代码展示了 Telegram 消息编辑的实现。editMessageText API 接收聊天 ID、消息 ID 和新文本内容。Telegram 对消息编辑没有时间限制,这是相比其他平台的优势。编辑成功后,消息会显示"已编辑"标记。

7.2 消息撤回

平台限制对比

平台 时间限制 撤回他人消息 API
Telegram 无限制 需管理员权限 deleteMessage
飞书 无限制 需应用权限 im.message.delete
Discord 无限制 需管理消息权限 DELETE /messages/{id}
Slack 无限制 需管理员权限 chat.delete
WhatsApp 约 1 小时 仅自己的消息 -

撤回消息代码示例

python 复制代码
async def delete_feishu_message(
    message_id: str,
    client: FeishuClient
):
    """
    撤回飞书消息
    
    Args:
        message_id: 要撤回的消息 ID
        client: 飞书客户端
    
    Returns:
        dict: 撤回结果
    """
    response = await client.im.message.delete(
        path={"message_id": message_id}
    )
    
    if response.code == 0:
        return {"success": True}
    else:
        raise Exception(f"Delete failed: {response.msg}")

8. 跨会话消息发送

OpenClaw 支持跨会话消息发送,即 AI Agent 可以向非当前对话的用户或群组发送消息。

8.1 使用场景

跨会话消息发送适用于以下场景:

  • 主动通知:系统监控到异常时,主动通知管理员
  • 定时提醒:根据日程安排,定时发送提醒消息
  • 广播消息:向多个群组或用户发送相同内容
  • 任务触发:某个任务完成后,通知相关人员

8.2 实现方式

指定目标发送

python 复制代码
# 向指定 Telegram 用户发送消息
await message_tool.invoke({
    "action": "send",
    "target": "telegram:123456789",
    "message": "这是一条主动通知消息"
})

# 向指定飞书群组发送消息
await message_tool.invoke({
    "action": "send",
    "channel": "feishu",
    "channelId": "oc_xxxxxxxxxxxxx",
    "message": "任务已完成,请查看结果"
})

广播消息

python 复制代码
# 向多个目标广播消息
await message_tool.invoke({
    "action": "broadcast",
    "targets": [
        "telegram:-1001234567890",
        "feishu:oc_xxxxxxxxxxxxx",
        "discord:123456789"
    ],
    "message": "系统维护通知:今晚 22:00-23:00 进行系统升级"
})

8.3 权限控制

跨会话消息发送涉及权限控制,防止滥用:

yaml 复制代码
# 配置示例:限制跨会话发送
channels:
  telegram:
    enabled: true
    botToken: "xxx"
    # 只允许发送给已配对的用户
    dmPolicy: "pairing"
    allowFrom: []
    # 群组需要明确配置
    groupPolicy: "allowlist"
    groupAllowFrom:
      - "-1001234567890"

9. 实战案例

9.1 案例一:智能客服通知系统

场景描述

某电商平台需要构建智能客服通知系统,当订单状态变更时,自动通知用户。要求支持 Telegram 和飞书两种渠道。

架构设计
👤 用户端
🤖 OpenClaw
📨 消息中心
🏢 业务系统
订单服务
库存服务
物流服务
消息队列
消息处理器
模板引擎
message 工具
Telegram 适配器
飞书适配器
Telegram 用户
飞书用户

核心代码实现

python 复制代码
import asyncio
from dataclasses import dataclass
from typing import Optional

@dataclass
class NotificationMessage:
    """通知消息数据结构"""
    user_id: str
    channel: str  # telegram / feishu
    template: str  # 模板名称
    data: dict     # 模板数据
    priority: str = "normal"  # normal / high

class NotificationService:
    """通知服务"""
    
    def __init__(self, message_tool):
        self.message_tool = message_tool
        self.templates = {
            "order_created": "🎉 订单创建成功!\n\n订单号:{order_id}\n商品:{product_name}\n金额:¥{amount}\n\n预计 {delivery_time} 送达",
            "order_shipped": "📦 您的订单已发货!\n\n订单号:{order_id}\n快递公司:{carrier}\n运单号:{tracking_number}\n\n点击查看物流详情",
            "order_delivered": "✅ 订单已送达!\n\n订单号:{order_id}\n收货人:{receiver}\n\n感谢您的购买,欢迎再次光临!"
        }
    
    async def send_notification(self, notification: NotificationMessage):
        """
        发送通知消息
        
        Args:
            notification: 通知消息对象
        
        Returns:
            dict: 发送结果
        """
        # 渲染消息模板
        template = self.templates.get(notification.template)
        if not template:
            raise ValueError(f"Unknown template: {notification.template}")
        
        message_text = template.format(**notification.data)
        
        # 构建目标
        target = f"{notification.channel}:{notification.user_id}"
        
        # 发送消息
        result = await self.message_tool.invoke({
            "action": "send",
            "target": target,
            "message": message_text
        })
        
        return result
    
    async def broadcast_notification(
        self,
        user_list: list,
        template: str,
        data: dict
    ):
        """
        批量发送通知
        
        Args:
            user_list: 用户列表 [{user_id, channel}, ...]
            template: 模板名称
            data: 模板数据
        
        Returns:
            list: 发送结果列表
        """
        tasks = []
        for user in user_list:
            notification = NotificationMessage(
                user_id=user["user_id"],
                channel=user["channel"],
                template=template,
                data=data
            )
            tasks.append(self.send_notification(notification))
        
        results = await asyncio.gather(*tasks, return_exceptions=True)
        return results

# 使用示例
async def main():
    # 初始化服务
    service = NotificationService(message_tool)
    
    # 发送单个通知
    await service.send_notification(NotificationMessage(
        user_id="123456789",
        channel="telegram",
        template="order_shipped",
        data={
            "order_id": "ORD20240315001",
            "carrier": "顺丰速运",
            "tracking_number": "SF1234567890"
        }
    ))
    
    # 批量发送通知
    await service.broadcast_notification(
        user_list=[
            {"user_id": "123456789", "channel": "telegram"},
            {"user_id": "ou_xxxxx", "channel": "feishu"}
        ],
        template="order_created",
        data={
            "order_id": "ORD20240315002",
            "product_name": "OpenClaw 高级版订阅",
            "amount": "299.00",
            "delivery_time": "即时生效"
        }
    )

上述代码实现了一个完整的通知服务。NotificationMessage 数据类定义了通知消息的结构,包含用户 ID、渠道、模板名称和模板数据。NotificationService 类封装了消息发送逻辑,支持单个发送和批量发送。模板引擎使用 Python 的字符串格式化功能,将数据填充到预定义的模板中。broadcast_notification 方法使用 asyncio.gather 实现并发发送,提高批量发送效率。

9.2 案例二:多平台监控告警

场景描述

运维团队需要在系统出现异常时,通过多个渠道同时发送告警消息,确保告警及时送达。

实现代码

python 复制代码
from datetime import datetime
from enum import Enum

class AlertLevel(Enum):
    """告警级别"""
    INFO = "info"
    WARNING = "warning"
    ERROR = "error"
    CRITICAL = "critical"

class AlertService:
    """告警服务"""
    
    ALERT_EMOJIS = {
        AlertLevel.INFO: "ℹ️",
        AlertLevel.WARNING: "⚠️",
        AlertLevel.ERROR: "❌",
        AlertLevel.CRITICAL: "🚨"
    }
    
    def __init__(self, message_tool, alert_channels: dict):
        """
        初始化告警服务
        
        Args:
            message_tool: message 工具实例
            alert_channels: 告警渠道配置
                {
                    "telegram": ["-1001234567890"],
                    "feishu": ["oc_xxxxx"],
                    "discord": ["123456789"]
                }
        """
        self.message_tool = message_tool
        self.alert_channels = alert_channels
    
    def _format_alert(
        self,
        level: AlertLevel,
        title: str,
        message: str,
        details: dict = None
    ) -> str:
        """格式化告警消息"""
        emoji = self.ALERT_EMOJIS[level]
        timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        
        text = f"{emoji} **{title}**\n\n"
        text += f"级别:{level.value.upper()}\n"
        text += f"时间:{timestamp}\n\n"
        text += f"{message}\n"
        
        if details:
            text += "\n**详细信息:**\n"
            for key, value in details.items():
                text += f"- {key}: {value}\n"
        
        return text
    
    async def send_alert(
        self,
        level: AlertLevel,
        title: str,
        message: str,
        details: dict = None,
        channels: list = None
    ):
        """
        发送告警
        
        Args:
            level: 告警级别
            title: 告警标题
            message: 告警内容
            details: 详细信息
            channels: 指定发送渠道(可选,默认发送到所有配置渠道)
        """
        alert_text = self._format_alert(level, title, message, details)
        
        # 确定发送目标
        targets = []
        if channels:
            for channel in channels:
                if channel in self.alert_channels:
                    for channel_id in self.alert_channels[channel]:
                        targets.append(f"{channel}:{channel_id}")
        else:
            for channel, channel_ids in self.alert_channels.items():
                for channel_id in channel_ids:
                    targets.append(f"{channel}:{channel_id}")
        
        # 广播告警
        results = await self.message_tool.invoke({
            "action": "broadcast",
            "targets": targets,
            "message": alert_text
        })
        
        return results

# 使用示例
async def monitor_alert():
    service = AlertService(message_tool, {
        "telegram": ["-1001234567890"],
        "feishu": ["oc_xxxxx"],
        "discord": ["123456789"]
    })
    
    # 发送严重告警
    await service.send_alert(
        level=AlertLevel.CRITICAL,
        title="数据库连接异常",
        message="主数据库连接池已耗尽,当前活跃连接数达到上限",
        details={
            "数据库": "MySQL 主库",
            "活跃连接": "100/100",
            "等待队列": "45",
            "持续时间": "5 分钟"
        }
    )

9.3 案例三:交互式问卷系统

场景描述

HR 部门需要通过飞书发送员工满意度调查问卷,收集员工反馈。

飞书卡片问卷实现

python 复制代码
async def send_survey_card(client: FeishuClient, user_id: str):
    """发送飞书问卷卡片"""
    
    card = {
        "schema": "2.0",
        "config": {"wide_screen_mode": True},
        "header": {
            "title": {"tag": "plain_text", "content": "📋 员工满意度调查"},
            "subtitle": {"tag": "plain_text", "content": "感谢您抽出时间参与调查"},
            "template": "turquoise"
        },
        "body": {
            "elements": [
                {
                    "tag": "div",
                    "text": {
                        "tag": "lark_md",
                        "content": "**Q1:您对当前工作环境满意吗?**"
                    }
                },
                {
                    "tag": "action",
                    "actions": [
                        {
                            "tag": "button",
                            "text": {"tag": "plain_text", "content": "非常满意 😊"},
                            "type": "primary",
                            "value": {"q1": "5"}
                        },
                        {
                            "tag": "button",
                            "text": {"tag": "plain_text", "content": "满意 🙂"},
                            "type": "primary",
                            "value": {"q1": "4"}
                        },
                        {
                            "tag": "button",
                            "text": {"tag": "plain_text", "content": "一般 😐"},
                            "type": "default",
                            "value": {"q1": "3"}
                        }
                    ]
                },
                {
                    "tag": "hr"
                },
                {
                    "tag": "div",
                    "text": {
                        "tag": "lark_md",
                        "content": "**Q2:您认为团队协作效率如何?**"
                    }
                },
                {
                    "tag": "input",
                    "placeholder": {"tag": "plain_text", "content": "请输入您的看法..."},
                    "element_id": "q2_input",
                    "required": False
                },
                {
                    "tag": "hr"
                },
                {
                    "tag": "action",
                    "actions": [
                        {
                            "tag": "button",
                            "text": {"tag": "plain_text", "content": "提交问卷"},
                            "type": "primary",
                            "value": {"action": "submit_survey"}
                        }
                    ]
                }
            ]
        }
    }
    
    response = await client.im.message.create(
        params={"receive_id_type": "open_id"},
        data={
            "receive_id": user_id,
            "content": json.dumps(card),
            "msg_type": "interactive"
        }
    )
    
    return response

上述代码展示了飞书交互式问卷卡片的实现。卡片包含标题、副标题和多个交互元素。action 元素中的按钮可以收集用户选择,input 元素允许用户输入文本反馈。用户点击按钮后,飞书会向配置的回调地址发送事件,OpenClaw 可以接收并处理这些事件,实现完整的问卷流程。


10. 最佳实践与注意事项

10.1 性能优化建议

优化点 建议 说明
消息分块 长消息自动分块发送 避免超出平台限制
并发控制 使用异步发送,控制并发数 提高发送效率,避免限流
缓存 Token 缓存访问令牌,避免重复获取 减少网络请求
错误重试 实现指数退避重试机制 应对临时网络故障
消息队列 高频场景使用消息队列 削峰填谷,保证可靠性

10.2 安全注意事项

敏感信息保护

yaml 复制代码
# 配置文件中避免硬编码敏感信息
channels:
  telegram:
    enabled: true
    # 使用环境变量
    botToken: "${TELEGRAM_BOT_TOKEN}"
    # 或使用文件引用
    tokenFile: "/etc/openclaw/telegram-token"

权限最小化原则

yaml 复制代码
# 只开放必要的权限
channels:
  feishu:
    dmPolicy: "allowlist"  # 只允许白名单用户
    allowFrom:
      - "ou_xxxxx"
    groupPolicy: "disabled"  # 禁用群聊

10.3 常见问题与解决方案

问题 原因 解决方案
消息发送失败 Token 过期或无效 检查 Token 有效性,刷新 Token
消息被截断 超出平台长度限制 使用消息分块或卡片消息
群组无响应 未配置群组权限 检查 groupPolicygroups 配置
卡片显示异常 JSON 格式错误 验证卡片 JSON 结构
媒体发送失败 文件过大或格式不支持 检查文件大小和格式限制

11. 总结

本文全面深入地介绍了 OpenClaw 的 message 消息工具,从核心概念、多渠道支持、消息格式化,到富文本卡片、消息回复编辑、跨会话发送等高级功能,最后通过三个实战案例展示了实际应用场景。

核心要点回顾

  1. 统一抽象,多端适配:message 工具通过统一的接口设计,屏蔽了不同平台的 API 差异,让开发者能够"一次编写,多端运行"。无论是 Telegram、飞书、Discord 还是 Slack,调用方式保持一致,大大降低了开发成本。

  2. 功能丰富,灵活可控:支持文本、媒体、卡片、投票等多种消息类型,以及回复、引用、编辑、撤回等操作。通过精细的权限配置,可以有效控制消息发送范围,防止滥用。

  3. 平台特性,智能适配:虽然接口统一,但 OpenClaw 也充分利用了各平台的独特能力。飞书的卡片消息、Discord 的 Embed、Slack 的线程消息等,都能在 message 工具中得到体现。

  4. 实战导向,即学即用:通过智能客服通知、多平台监控告警、交互式问卷三个案例,展示了 message 工具在实际业务中的应用方法。这些案例可以直接作为项目开发的参考模板。

思考与展望

随着 AI Agent 技术的发展,消息交互将变得更加智能和自然。未来,message 工具可能会支持更多高级特性,如:

  • 基于上下文的智能消息路由
  • 多模态消息(语音、视频)的统一处理
  • 跨平台会话状态同步
  • 消息效果分析与优化建议

掌握 message 工具,是构建高质量 AI Agent 的重要一步。希望本文能够帮助读者深入理解 OpenClaw 的消息发送机制,在实际项目中发挥更大的价值。


参考资料

相关推荐
SuniaWang2 小时前
2026 AI Agent 爆发元年:OpenClaw v2026.4.2(The Lobster)Windows 深度部署与全路径避坑指南
人工智能·windows·openclaw·小龙虾
追光的蜗牛丿2 小时前
OpenCV Mat 中的图像数据是如何存储的
人工智能·opencv·计算机视觉
jinanwuhuaguo2 小时前
OpenClaw办公人员核心技能深度培训体系:从认知重塑到数字组织构建的全链路实战指南
java·大数据·开发语言·人工智能·openclaw
ai生成式引擎优化技术2 小时前
AI世界的多元化结构理论猜想
人工智能
Fairy要carry2 小时前
面试-LayerNorm和RMSNorm的区别
人工智能
ZGi.ai2 小时前
企业AI的运行底座是什么?和AI工具有什么本质区别?
人工智能·rag·大模型落地·企业ai·ai底座
海海不掉头发2 小时前
【神经网络基础】-学习探索篇章-基础篇
人工智能·神经网络·学习
lifallen2 小时前
Flink Agents:从 DataStream 到 Agent 算子的接入与装配
java·大数据·人工智能·python·语言模型·flink