首页
/ LobeHub 中的 chat SDK 实践:一次编写 Bot 逻辑,跨 Slack、Teams、Discord 与 GitHub 等平台部署

LobeHub 中的 chat SDK 实践:一次编写 Bot 逻辑,跨 Slack、Teams、Discord 与 GitHub 等平台部署

2026-09-05 13:00:32作者:齐冠琰

本文基于 LobeHub 仓库中的 Agent 技能文档 SKILL.md,系统讲解 chat SDK 这套统一 TypeScript 聊天机器人 SDK 的核心概念、事件处理器、流式响应与 JSX 交互卡片,并结合 LobeHub 仓库内真实依赖配置与 5 个自研渠道适配器(微信、QQ、飞书、LINE、iMessage)的实际用法,帮助你掌握"逻辑写一次、多平台部署"的完整技术路径。

一、chat SDK 是什么,以及它在 LobeHub 中的位置

chat SDK 是一个统一的 TypeScript SDK,目标是让开发者只写一份 Bot 逻辑,即可部署到 Slack、Teams、Google Chat、Discord、GitHub、Linear 等多个平台。它的核心抽象是:由一个主入口 Chat 协调各平台适配器(Adapter),并通过可插拔的状态层(State)持久化会话订阅关系。

在 LobeHub 仓库中,这份能力被记录在 Agent 技能目录下的 SKILL.md(frontmatter 中标注 user-invocable: false,即它是供 AI Agent 在构建聊天机器人任务时自动加载的参考技能,而非用户直接调用的命令)。该技能文档给出的标准工作流是:在动手写代码之前,先阅读随包分发的完整文档与类型定义

node_modules/chat/docs/           # 完整文档(MDX 文件)
node_modules/chat/dist/           # 构建产物类型(.d.ts 文件)

按任务类型选择重点阅读的关键文档:

  • docs/getting-started.mdx — 安装与初始化指南
  • docs/usage.mdx — 事件处理器、线程(thread)、消息(message)、频道(channel)
  • docs/streaming.mdx — 基于 AI SDK 的流式响应
  • docs/cards.mdx — JSX 交互卡片
  • docs/actions.mdx — 按钮/下拉框处理器
  • docs/modals.mdx — 表单对话框(仅 Slack 支持)
  • docs/adapters/*.mdx — 各平台适配器的接入配置
  • docs/state/*.mdx — 状态适配器配置(Redis、ioredis、memory)

同时建议阅读 node_modules/chat/dist/ 下的 TypeScript 类型,以掌握完整 API 面。

仓库内的真实依赖证据

LobeHub 根 package.json 中固定了 SDK 版本 "chat": "~4.38.0",并且工作区(pnpm-workspace.yaml)纳入了 packages/** 下的多个适配器包。更重要的是,LobeHub 围绕该 SDK 自研了 5 个面向中文生态与个人 IM 渠道的适配器,它们全部依赖 chat ~4.38.0

适配器包 渠道 包描述(来自各自 package.json)
chat-adapter-wechat 微信 "WeChat (iLink) Bot adapter for chat SDK"
chat-adapter-qq QQ "QQ Bot adapter for chat SDK"
chat-adapter-line LINE "LINE Messaging API Bot adapter for chat SDK"
chat-adapter-feishu 飞书/Lark "Lark/Feishu adapter for chat SDK"
chat-adapter-imessage iMessage "iMessage adapter for chat SDK via BlueBubbles"

这说明 LobeHub 不仅消费 chat SDK,还将其适配器机制扩展到了官方文档未覆盖的平台——这也是该技能文档存在的实际背景:为在本仓库中开发此类 Bot 或适配器的 Agent 提供统一的知识基线。

二、快速上手:最小可运行的多平台 Bot

技能文档给出的标准 Quick Start 如下,完整继承了 Chat 构造、Slack 适配器与 Redis 状态三层结构:

import { Chat } from 'chat';
import { createSlackAdapter } from '@chat-adapter/slack';
import { createRedisState } from '@chat-adapter/state-redis';

const bot = new Chat({
  userName: 'mybot',
  adapters: {
    slack: createSlackAdapter({
      botToken: process.env.SLACK_BOT_TOKEN!,
      signingSecret: process.env.SLACK_SIGNING_SECRET!,
    }),
  },
  state: createRedisState({ url: process.env.REDIS_URL! }),
});

bot.onNewMention(async (thread) => {
  await thread.subscribe();
  await thread.post("Hello! I'm listening to this thread.");
});

bot.onSubscribedMessage(async (thread, message) => {
  await thread.post(`You said: ${message.text}`);
});

逐段拆解关键配置:

  • userName: 'mybot' — 机器人的名字,事件路由时用于识别"是否 @ 了我";
  • adapters — 平台适配器的映射表,键为平台名(slack),值为 createXxxAdapter() 的产物。多平台部署时只需在此表里追加条目(如 teamsdiscord),业务代码零改动;
  • state: createRedisState(...) — 生产环境使用 Redis 持久化线程订阅状态;开发环境可换用 @chat-adapter/state-memory 的内存实现;
  • 环境变量 SLACK_BOT_TOKENSLACK_SIGNING_SECRETREDIS_URL — 分别对应 Slack Bot Token、Slack 签名密钥、Redis 连接串,属于接入该平台与状态层的必要前提。

这段代码的运行语义是:Bot 在被未订阅的线程中 @ 时自动 subscribe() 加入监听,之后对该线程内每条消息做复读响应——这正是后续所有事件模型的缩影。

三、核心概念:六大抽象的分工

技能文档将 SDK 的 API 面归纳为六个核心概念,理解它们是读懂一切 API 的前提:

  • Chat — 主入口,负责协调各适配器并将事件路由到对应处理器;
  • Adapters — 平台特定层(Slack、Teams、GChat、Discord、GitHub、Linear),屏蔽各平台 Webhook 协议与消息格式差异;
  • State — 可插拔的持久化层,生产用 Redis,开发用 memory;它记住"哪些线程被订阅过",是 onSubscribedMessage 能够工作的前提;
  • Thread — 会话线程对象,提供 post()(发消息)、subscribe()(订阅线程)、startTyping()(输入中状态)等方法;
  • Message — 归一化消息格式,包含三个字段:text(纯文本)、formatted(mdast AST 结构化格式)、raw(平台原始数据);
  • Channel — 线程的容器,支持列出频道与直接向频道发消息。

值得强调的是 Message 的三段式设计:业务逻辑读取 text 即可跨平台通用;需要富文本处理时消费 formatted 的 mdast AST;需要平台特有元信息(如 Slack 附件、Discord embed 原始体)时回退到 raw。这一归一化正是"逻辑写一次"能够成立的技术基础。

四、事件处理器体系

SDK 通过一组 on* 注册方法暴露全部事件。技能文档给出的完整触发条件表如下:

处理器 触发时机
onNewMention Bot 在未订阅线程中被 @
onSubscribedMessage 已订阅线程中的任意消息
onNewMessage(regex) 未订阅线程中匹配正则的消息
onSlashCommand("/cmd") 斜杠命令调用
onReaction(emojis) emoji 反应被添加或移除
onAction(actionId) 按钮点击与下拉框选择
onAssistantThreadStarted Slack Assistants API 线程被打开
onAppHomeOpened Slack App Home 标签页被打开

从中可以推断出 SDK 的核心事件模型是**"线程订阅制"**:

  1. onNewMention 是入口——只有被 @ 才会产生订阅意图,处理器里显式调用 thread.subscribe() 后,该线程进入已订阅状态(写入 State);
  2. 进入订阅状态后,onSubscribedMessage 接管线程内全部后续消息,无需再 @;
  3. onNewMessage(regex) 则提供"免 @ 触发"的路径,用于按文本模式(如以特定前缀开头)被动拦截未订阅线程中的消息;
  4. onAction(actionId) 与 JSX 卡片形成闭环——卡片里的按钮点击会携带 actionId 回流到 Bot(见第六节)。

其中后两个(onAssistantThreadStartedonAppHomeOpened)是 Slack 生态专属事件,体现了适配器层在归一化之上仍保留平台特有能力入口的设计。

五、流式响应:AI 回答逐字"打字机"输出

技能文档指出:thread.post() 接受任意 AsyncIterable<string>,因此可以直接对接 AI SDK 的 textStream

import { ToolLoopAgent } from 'ai';
const agent = new ToolLoopAgent({ model: 'anthropic/claude-4.5-sonnet' });

bot.onNewMention(async (thread, message) => {
  const result = await agent.stream({ prompt: message.text });
  await thread.post(result.textStream);
});

从签名契约看,SDK 只关心"一个可异步迭代的字符串流",不关心字符串来自哪家模型服务商——LobeHub 作为多模型网关项目,这一设计意味着任何自家 Agent 运行时的输出流都能原样接入聊天渠道。适配器层负责把流式片段映射为各平台的原生增量更新机制(Slack 消息更新、Discord 内容刷新等),对 Bot 逻辑透明。

六、JSX 交互卡片:跨平台的富 UI 描述

SDK 提供了一套类 React 的 JSX 组件来描述交互卡片,先在 tsconfig.json 中配置 jsxImportSource: "chat",即可使用这些组件:CardCardTextButtonActionsFieldsFieldSelectSelectOptionImageDividerLinkButtonSectionRadioSelect

文档示例:

await thread.post(
  <Card title="Order #1234">
    <CardText>Your order has been received!</CardText>
    <Actions>
      <Button id="approve" style="primary">
        Approve
      </Button>
      <Button id="reject" style="danger">
        Reject
      </Button>
    </Actions>
  </Card>,
);

使用要点:

  • thread.post() 的入参是多态的——可以传字符串(普通消息)、AsyncIterable<string>(流式消息),也可以传 JSX 卡片元素;
  • <Button id="approve">id 即 actionId,用户点击后由 bot.onAction('approve') 处理器接收,形成"发卡 → 点击 → 回调"的完整交互闭环;
  • style 支持 primarydanger 等语义样式,由适配器翻译成各平台按钮的配色/语义;
  • 表单类对话框(Modals)目前仅 Slack 支持,其余平台会退化为卡片内的 Select/RadioSelect/Fields 组合——这也是组件列表里单独提供 Fields/Field/RadioSelect 的原因。

七、包矩阵:核心 SDK、平台适配器与状态适配器

技能文档列出的完整包清单:

用途
chat 核心 SDK
@chat-adapter/slack Slack
@chat-adapter/teams Microsoft Teams
@chat-adapter/gchat Google Chat
@chat-adapter/discord Discord
@chat-adapter/github GitHub Issues
@chat-adapter/linear Linear Issues
@chat-adapter/state-redis Redis 状态(生产)
@chat-adapter/state-ioredis ioredis 状态(替代方案)
@chat-adapter/state-memory 内存状态(开发)

在 LobeHub 仓库中,该矩阵被进一步扩展为上文表格中的 5 个 @lobechat/chat-adapter-* 包(微信、QQ、LINE、飞书、iMessage)。这些包同样遵循"依赖核心 chat 包 + 实现适配器接口"的模式(各包 package.json 中均声明 "chat": "~4.38.0" 为依赖),并在 pnpm-workspace.yaml 声明的 packages/** 工作区内统一构建——这为"如何为 chat SDK 增加新平台适配器"提供了仓库内可直接参考的范例结构。

八、Webhook 接入:把 SDK 挂到你的 HTTP 框架

每个适配器都通过 bot.webhooks.{platform} 暴露一个 Webhook 处理函数。接入方式是与你的 HTTP 框架路由做绑定,技能文档列出的典型宿主包括 Next.js API Routes、Hono、Express:

// 以 Hono 为例的概念性接法(平台名与处理器一一对应)
app.post('/webhooks/slack', (req) => bot.webhooks.slack(req));
app.post('/webhooks/discord', (req) => bot.webhooks.discord(req));

(以上为基于文档描述的接法示意。)部署侧需要为每个启用的平台适配器配置对应的平台侧回调地址(Slack Events URL、Discord Interactions 等),并保证 signingSecret 等验签配置就位——Slack 适配器的 signingSecret 参数(见第二节 Quick Start)即用于此目的。

九、发布流程:Changesets 驱动的 SDK 多包发版

技能文档还记录了 chat SDK 自身 monorepo 的发布流程:它使用 Changesets 管理版本与 CHANGELOG,任何改变包行为的 PR 都必须附带一个 changeset。操作流程:

pnpm changeset
# → 选择受影响的包(例如 @chat-adapter/slack、chat)
# → 选择 bump 类型:patch(修复)、minor(新功能)、major(破坏性变更)
# → 写一段进入 CHANGELOG 的简短摘要

该命令会在 .changeset/ 目录生成一个描述文件,需随 PR 一起提交。合并入 main 后,Changesets GitHub Action 会自动开出一个 "Version Packages" PR 完成版本号提升与 CHANGELOG 更新,再合并该 PR 即发布到 npm。如果你计划向上游 chat SDK monorepo 贡献功能(例如新增平台适配器支持),需要遵循这套"改动 + changeset"同 PR 提交的约定。

十、小结:技能文档沉淀的三条工程经验

回到 SKILL.md 本身,它对 Agent 与开发者沉淀了三点可复用的工程经验:

  1. 先读包内文档再写代码——node_modules/chat/docs/dist/ 类型是比任何二手资料都权威的 API 依据;
  2. 用"订阅制线程模型"组织事件——以 onNewMention → subscribe() → onSubscribedMessage 为主干,辅以 onNewMessage(regex)onAction 扩展触发面;
  3. 适配器与状态都可替换——平台扩展走 adapters 表,持久化走 state 注入,业务逻辑对两者均无感,这也是 LobeHub 能在此机制上自研微信/QQ/飞书/LINE/iMessage 五个渠道适配器的原因。

掌握以上内容后,你可以在 LobeHub 工作区内为任意支持的 IM 渠道编写 Bot、接入流式模型响应,并用 JSX 卡片构建跨平台的富交互界面。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.13 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
897
5.8 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
529
593
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
915
1.83 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.58 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.35 K
1.46 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.01 K
515
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
547
388