ClawSkills logoClawSkills

Feishu Interactive Cards

创建并发送包含按钮、表单、投票和丰富 UI 元素的交互式卡片到飞书。适用于回复飞书消息且存在任何不确定性的场景。

介绍

# Feishu Interactive Cards

## 核心原则

**在回复飞书且存在任何不确定性时:发送交互卡片而不是纯文本。**

交互卡片允许用户通过按钮进行响应,而无需手动输入,从而使交互更快、更清晰。

## 使用场景

**必须使用交互卡片:** - 用户需要做出选择(是/否,多项选择) - 执行操作前需要确认 - 显示待办事项或任务列表 - 创建投票或调查 - 收集表单输入 - 任何不确定的情况

**纯文本即可:** - 简单通知(无需回复) - 纯数据展示(无交互) - 已确认的命令结果

**示例:** - 错误:“我已为您删除文件”(直接执行) - 正确:发送卡片“确认删除文件?” [确认] [取消]

## 快速开始

### 1. 启动回调服务(长轮询模式)

```bash cd E:\openclaw\workspace\skills\feishu-interactive-cards\scripts node card-callback-server.js ```

**特性:** - 使用飞书长轮询(无需公网 IP) - 自动重连 - 自动将回调发送至 OpenClaw 网关

### 2. 发送交互卡片

```bash # Confirmation card node scripts/send-card.js confirmation "Confirm delete file?" --chat-id oc_xxx

# Todo list node scripts/send-card.js todo --chat-id oc_xxx

# Poll node scripts/send-card.js poll "Team activity" --options "Bowling,Movie,Dinner" --chat-id oc_xxx

# Custom card node scripts/send-card.js custom --template examples/custom-card.json --chat-id oc_xxx ```

### 3. 在 Agent 中使用

当 Agent 需要发送飞书消息时:

```javascript // Wrong: Send plain text await message({ action: "send", channel: "feishu", message: "Confirm delete?" });

// Right: Send interactive card await exec({ command: `node E:\\openclaw\\workspace\\skills\\feishu-interactive-cards\\scripts\\send-card.js confirmation "Confirm delete file test.txt?" --chat-id ${chatId}` }); ```

## 卡片模板

请参阅 `examples/` 目录获取完整的卡片模板: - `confirmation-card.json` - 确认对话框 - `todo-card.json` - 带复选框的任务列表 - `poll-card.json` - 投票和调查 - `form-card.json` - 带输入字段的表单

有关详细的卡片设计模式和最佳实践,请参阅 [references/card-design-guide.md](references/card-design-guide.md)。

## 回调处理

回调服务器会自动将所有卡片交互发送至 OpenClaw 网关。有关详细的集成指南,请参阅 [references/gateway-integration.md](references/gateway-integration.md)。

**快速示例:**

```javascript // Handle confirmation if (callback.data.action.value.action === "confirm") { const file = callback.data.action.value.file; // ⚠️ SECURITY: Validate and sanitize file path before use // Use OpenClaw's built-in file operations instead of shell commands const fs = require('fs').promises; const path = require('path'); try { // Validate file path (prevent directory traversal) const safePath = path.resolve(file); if (!safePath.startsWith(process.cwd())) { throw new Error('Invalid file path'); } // Use fs API instead of shell command await fs.unlink(safePath); // Update card await updateCard(callback.context.open_message_id, { header: { title: "Done", template: "green" }, elements: [ { tag: "div", text: { content: `File ${path.basename(safePath)} deleted`, tag: "lark_md" } } ] }); } catch (error) { // Handle error await updateCard(callback.context.open_message_id, { header: { title: "Error", template: "red" }, elements: [ { tag: "div", text: { content: `Failed to delete file: ${error.message}`, tag: "lark_md" } } ] }); } } ```

## 最佳实践

### 卡片设计 - 标题和内容清晰 - 按钮操作明显 - 对破坏性操作使用 `danger` 类型 - 在按钮 `value` 中携带完整状态以避免额外查询

### 交互流程 ``` User request -> Agent decides -> Send card -> User clicks button -> Callback server -> Gateway -> Agent handles -> Update card/execute ```

### 错误处理 - 超时:如果用户未响应,发送提醒 - 重复点击:内置去重(3秒窗口) - 失败:更新卡片以显示错误消息

### 性能 - 异步处理:快速响应,后台处理长任务 - 批量操作:将相关操作合并在一张卡片中

## 配置

在 `~/.openclaw/openclaw.json` 中进行配置:

```json { "channels": { "feishu": { "accounts": { "main": { "appId": "YOUR_APP_ID", "appSecret": "YOUR_APP_SECRET" } } } }, "gateway": { "enabled": true, "port": 18789, "token": "YOUR_GATEWAY_TOKEN" } } ```

回调服务器会自动读取配置。

## 故障排除

**按钮点击无效:** - 检查回调服务器是否正在运行 - 验证飞书后端使用的是“长轮询”模式 - 确保已订阅 `card.action.trigger` 事件

**网关未收到回调:** - 启动网关:`E:\openclaw\workspace\scripts\gateway.cmd` - 检查 `~/.openclaw\openclaw.json` 中的 token

**卡片显示问题:** - 使用提供的模板作为基础 - 验证 JSON 格式 - 检查必填字段

## 安全性

**⚠️ 关键:切勿将用户输入直接传递给 Shell 命令!**

此技能包含全面的安全指南。请在实现回调处理程序之前阅读 [references/security-best-practices.md](references/security-best-practices.md)。

主要安全原则: - 始终验证并清理用户输入 - 使用 Node.js 内置 API 代替 Shell 命令 - 实施适当的权限检查 - 防止命令注入漏洞 - 使用 event_id 进行去重

## 参考资料

- [安全最佳实践](references/security-best-practices.md) - **请首先阅读本文!** - [飞书卡片文档](https://open.feishu.cn/document/ukTMukTMukTM/uczM3QjL3MzN04yNzcDN) - [OpenClaw 文档](https://docs.openclaw.ai)

更多产品