---
id: "fa83652f76f1bcd119dd"
url: "https://www.xmcsl.cn/project/feishu-cli-embed/03-interactions/02-%E4%BD%BF%E7%94%A8%20Vercel%20Chat%20SDK%20%E6%8E%A5%E5%85%A5%E9%A3%9E%E4%B9%A6.html"
source_url: "https://open.feishu.cn/document/mcp_open_tools/integrating-agents-with-feishu/vercel-chat-sdk-lark-message-publish"
source_date: null
checked_at: "2026-11-05T04:21:48.909937+00:00"
status: "ready"
check_scope: "structure_only; not a factual or human review"
body_sha256: "604bb9741be31b355fdcb1e5488be4e39b2af8a0470b3d2520be932f8ef52c3c"
---

# 使用 Vercel Chat SDK 接入飞书 · 飞书 Agent 接入知识库

## Vercel Chat SDK 是什么

 

<a href="https://chat-sdk.dev">Vercel Chat SDK</a> 是一个面向多平台的聊天机器人开发框架，提供统一的 Channel、Thread、Message 抽象。基于该 SDK，开发者可以用同一套业务代码同时支持 Slack、Microsoft Teams、Discord、Telegram、WhatsApp、GitHub、Linear 等多个 IM 与协作平台。

 

它的核心理念是 <strong>Channel 抽象</strong>：把平台特定的鉴权、消息收发、状态管理统一封装在适配器层之下，业务代码只关心 <code>Channel</code>/ <code>Thread</code>/ <code>Message</code>。新平台的接入由对应的"适配器（adapter）"承担。

 

## 飞书官方适配器

 

飞书已经为 Vercel Chat SDK 发布了官方适配器 <a href="https://www.npmjs.com/package/@larksuite/vercel-chat-adapter">@larksuite/vercel-chat-adapter</a>，让 Chat SDK 上构建的产品可以无缝接入飞书。

 

适配器支持的能力：

 

<ul>&#10;<li>原生 cardkit 卡片流式（typewriter，非 post + edit 轮询）</li>&#10;<li>完整交互卡片（按钮、链接、菜单、字段、图片）</li>&#10;<li>消息编辑 / 删除 / 表情回复</li>&#10;<li>历史消息拉取（覆盖飞书 20+ 种原生消息类型）</li>&#10;<li>群聊 / 私聊识别 及 @ 提及处理</li>&#10;<li>WebSocket 长连接传输</li>&#10;<li><code>registerLarkApp</code> 扫码授权一键创建应用</li>&#10;</ul>

 

这个适配器基于飞书 Channel SDK 构建（详见下方<a href="https://open.larkoffice.com/document/mcp_open_tools/integrating-agents-with-feishu/vercel-chat-sdk-lark-message-publish#16b76461">适配器实现原理</a>章节）。

 

## 快速开始

 

### 创建飞书应用

 

#### 方式一：扫码授权（推荐）

 

调用 <code>registerLarkApp</code> 触发飞书官方扫码流程，生成一次性链接，用户扫码后自动返回 <code>client&#95;id</code> / <code>client&#95;secret</code>，并预配好本适配器所需的权限与事件订阅。

 

```TypeScript
import { registerLarkApp } from "@larksuite/vercel-chat-adapter";
import qrcode from "qrcode-terminal"; // pnpm add -D qrcode-terminal

const { client_id, client_secret } = await registerLarkApp({
  onQRCodeReady: ({ url }) => {
    console.log("使用飞书 / Lark 手机端扫码：");
    qrcode.generate(url, { small: true });
  },
  onStatusChange: ({ status }) => console.log("授权状态：", status),
});

console.log("LARK_APP_ID=", client_id);
console.log("LARK_APP_SECRET=", client_secret);
```

 

只需运行一次。把返回的 <code>client&#95;id</code> / <code>client&#95;secret</code> 持久化保存，后续启动通过 <code>LARK&#95;APP&#95;ID</code> / <code>LARK&#95;APP&#95;SECRET</code> 环境变量传入即可。

 

#### 方式二：开发者后台手动创建

 

在 <a href="https://open.larksuite.com/app">open.larksuite.com/app</a>（Lark）或 <a href="https://open.feishu.cn/app">open.feishu.cn/app</a>（飞书）创建应用，获取 <code>client&#95;id</code> / <code>client&#95;secret</code>。

 

### 安装适配器

 

```Bash
pnpm add @larksuite/vercel-chat-adapter chat @chat-adapter/state-memory
```

 

### 最小可运行示例

 

```TypeScript
import { Chat } from "chat";
import { createMemoryState } from "@chat-adapter/state-memory";
import { createLarkAdapter } from "@larksuite/vercel-chat-adapter";

const bot = new Chat({
  userName: "mybot",
  adapters: {
    lark: createLarkAdapter({
      appId: process.env.LARK_APP_ID!,
      appSecret: process.env.LARK_APP_SECRET!,
    }),
  },
  state: createMemoryState(),
});

bot.onNewMention(async (thread, message) => {
  await thread.subscribe();
  await thread.post(`收到：${message.text}`);
});

bot.onDirectMessage(async (thread, message) => {
  await thread.post(`收到私信：${message.text}`);
});

await bot.initialize();
```

 

<code>bot.initialize()</code> 会建立 WebSocket 长连接并保持运行，Node.js 进程会一直运行直到 <code>bot.shutdown()</code> 被调用。

 

### 配置环境变量

 

如果不显式传 <code>appId</code>、<code>appSecret</code>，适配器会从以下环境变量自动读取：

 

<ul>&#10;<li><code>LARK&#95;APP&#95;ID</code> —— 飞书 App ID</li>&#10;<li><code>LARK&#95;APP&#95;SECRET</code> —— 飞书 App Secret</li>&#10;</ul>

 

## 适配器实现原理

 

这个适配器基于 <a href="https://github.com/larksuite/node-sdk">飞书 Channel SDK</a>（<code>@larksuiteoapi/node-sdk</code> 中的 <code>LarkChannel</code>）构建。Channel SDK 是飞书提供的高阶 SDK，封装了：

 

<ul>&#10;<li>事件订阅与签名验证</li>&#10;<li>WebSocket 长连接与心跳重连</li>&#10;<li>20+ 种原生消息类型的归一化（<code>normalize()</code> 输出统一格式）</li>&#10;<li>Cardkit 卡片流式接口</li>&#10;<li>历史消息拉取</li>&#10;<li>应用凭证管理（自动 token 刷新）</li>&#10;</ul>

 

适配器开发者只需要做"接口翻译" —— 把 Channel SDK 的接口映射到 Vercel Chat SDK 的 <code>Adapter</code> 接口。下面是核心代码示意（简化版）：

 

```TypeScript
import { LarkChannel } from "@larksuiteoapi/node-sdk";
import type { Adapter, Message } from "chat";

export const createLarkAdapter = (config?: LarkConfig): Adapter => {
  const channel = new LarkChannel({
    appId: config?.appId ?? process.env.LARK_APP_ID,
    appSecret: config?.appSecret ?? process.env.LARK_APP_SECRET,
    safety: { enabled: false }, // Chat SDK 已处理 dedupe / lock
  });

return {
    name: "lark",

async initialize() {
      // 收消息：Channel SDK 已经归一化，适配器只做格式映射
      channel.on("message", (normalized) => {
        const threadId = encodeThreadId(normalized.chatId, normalized.rootId);
        chat.handleIncomingMessage({
          text: normalized.text,
          threadId,
          author: {
            id: normalized.senderId,
            isMe: normalized.senderId === botIdentity.openId,
          },
          raw: normalized,
        });
      });
      await channel.connect();
    },

async post(threadId, message: Message) {
      const { chatId, rootId } = decodeThreadId(threadId);
      return channel.send({
        chatId,
        content: renderMarkdown(message),
        replyTo: rootId,
      });
    },

async stream(threadId, handler) {
      const { chatId, rootId } = decodeThreadId(threadId);
      // 使用原生 cardkit typewriter，非 post + edit 轮询
      return channel.cardkit.stream({
        chatId,
        replyTo: rootId,
        produce: handler,
      });
    },

async fetchMessages(threadId) {
      const { chatId, rootId } = decodeThreadId(threadId);
      const history = await channel.getHistoricalMessages({ chatId, rootId });
      return history.map(toMessage);
    },
  };
};
```

 

整个适配器的核心控制流不到百行 —— Channel SDK 已经处理了大部分飞书平台特定的复杂度，适配器只承担"接口翻译"这一核心工作。

 

## 相关链接

 

<ul>&#10;<li><a href="https://www.npmjs.com/package/@larksuite/vercel-chat-adapter">@larksuite/vercel-chat-adapter on npm</a></li>&#10;</ul>
