# 飞书配置指南

> ← [返回 README](./README.md) | [📚 文档索引](./docs/README.md)

AI 朝廷支持飞书作为通讯渠道，无需公网 IP，使用 WebSocket 长连接接收消息。

> ⚠️ **飞书与 Discord 的核心差异**
>
> Discord Bot 可以互相 @触发（Bot A @Bot B，Bot B 会收到消息并回复），所以 Discord 适合多 Bot 频道派活模式。
>
> **飞书 Bot 不能互相 @触发**——飞书 Bot 发出的 @mention 不会被其他 Bot 识别为事件。因此飞书推荐**单 Bot + sessions_spawn 后台调度**架构。

> 💡 **快速导航**
> - [第一步：创建飞书应用](#第一步创建飞书应用)
> - [第二步：配置 OpenClaw](#第二步配置-openclaw)
> - [第三步：启动并验证](#第三步启动并验证)
> - [架构说明：单 Bot + sessions_spawn](#架构说明单-bot--sessions_spawn)
> - [完整配置示例](#完整配置示例单-bot-推荐)
> - [高级用法：多 Bot 模式（可选）](#高级用法多-bot-模式可选)
> - [诊断与排查](#诊断与排查)
> - [常见报错及解决方案](#常见报错及解决方案)
> - [FAQ](#常见问题)

---

## 前置条件

- 已通过 `install.sh` 或 `install-lite.sh` 完成基础安装
- OpenClaw 已安装（`openclaw --version` 能正常输出）
- 有飞书企业版账号（个人版不支持自建应用）

## 第一步：创建飞书应用

**飞书只需创建 1 个应用（司礼监）。** 司礼监作为唯一入口，通过 `sessions_spawn` 在后台调度其他部门。

### 1. 打开飞书开放平台

访问 [https://open.feishu.cn/app](https://open.feishu.cn/app) 并登录。

> 如果是 Lark（国际版），访问 [https://open.larksuite.com/app](https://open.larksuite.com/app)

### 2. 创建企业自建应用

- 点击 **创建企业自建应用**
- 填写应用名称（如 "AI朝廷-司礼监"）和描述
- 选择一个应用图标

### 3. 复制凭证

在 **凭证与基础信息** 页面，复制：
- **App ID**（格式：`cli_xxx`）
- **App Secret**

⚠️ App Secret 请妥善保管，不要泄露。截图时注意打码！

### 4. 配置权限

在 **权限管理** 页面，搜索并添加以下权限：

| 权限标识 | 说明 | 必须 |
|---------|------|------|
| `im:message` | 获取与发送消息 | ✅ |
| `im:message.group_at_msg:readonly` | 获取群组中 @机器人的消息 | ✅ |
| `im:message.p2p_msg:readonly` | 获取单聊消息 | ✅ |
| `im:message:readonly` | 读取消息 | ✅ |
| `im:message:send_as_bot` | 以机器人身份发送消息 | ✅ |
| `im:resource` | 获取消息中的资源文件 | ✅ |
| `im:chat.members:bot_access` | 获取群成员信息 | 推荐 |
| `im:chat.access_event.bot_p2p_chat:read` | 获取单聊事件 | 推荐 |
| `contact:user.employee_id:readonly` | 获取用户信息 | 推荐 |

或点击 **批量导入**，粘贴以下 JSON：

```json
{
  "scopes": {
    "tenant": [
      "im:message",
      "im:message.group_at_msg:readonly",
      "im:message.p2p_msg:readonly",
      "im:message:readonly",
      "im:message:send_as_bot",
      "im:resource",
      "im:chat.members:bot_access",
      "im:chat.access_event.bot_p2p_chat:read",
      "contact:user.employee_id:readonly"
    ],
    "user": [
      "im:chat.access_event.bot_p2p_chat:read"
    ]
  }
}
```

添加后，点击 **批量开通** 审批权限。企业自建应用通常自动审批。

### 5. 启用机器人能力

在 **应用能力 > 机器人**：
- 开启机器人能力
- 设置机器人名称（如 "司礼监"）

### 6. 配置事件订阅

> ⚠️ **重要顺序：** 先完成第二步（配置 OpenClaw 并启动 Gateway），再回来配置事件订阅！
> 因为飞书的 WebSocket 连接需要 Gateway 运行中才能握手成功。

在 **事件订阅** 中：
1. 选择 **使用长连接接收事件**（WebSocket 模式）
2. 添加事件：`im.message.receive_v1`（接收消息）

### 7. 发布应用

- 在 **版本管理与发布** 中创建版本
- 提交审核并发布
- 等待管理员审批（企业自建应用通常自动审批）

### 8. 将机器人添加到群聊

- 打开飞书群聊 → 群设置 → 群机器人 → 添加机器人
- 搜索你创建的应用名称并添加

---

## 第二步：配置 OpenClaw

### 方式一：交互式配置（推荐）

```bash
openclaw channels add
```

选择 Feishu，然后输入 App ID 和 App Secret。

### 方式二：手动编辑配置文件

编辑 `~/.openclaw/openclaw.json`，在 `channels` 中添加飞书配置：

```json
{
  "channels": {
    "feishu": {
      "enabled": true,
      "dmPolicy": "open",
      "groupPolicy": "open",
      "accounts": {
        "silijian": {
          "appId": "cli_xxx",
          "appSecret": "你的App Secret",
          "name": "司礼监",
          "groupPolicy": "open"
        }
      }
    }
  }
}
```

> 💡 **关键配置说明：**
> - `dmPolicy: "open"` — 私聊策略。`"open"` 允许直接对话（推荐新手）；`"pairing"` 需要在服务器上运行 `openclaw pairing approve` 审批后才能私聊，适合安全要求高的场景
> - `groupPolicy: "open"` — 群聊策略。必须设为 `"open"` 才能接收群消息

### 方式三：环境变量

```bash
export FEISHU_APP_ID="cli_xxx"
export FEISHU_APP_SECRET="你的App Secret"
```

---

## 第三步：启动并验证

```bash
# 重启 Gateway
openclaw gateway restart

# 查看状态
openclaw gateway status

# 查看日志（确认飞书连接成功）
openclaw logs --follow
```

日志中应该看到类似以下信息：
```
feishu: connected (ws)
feishu: account "silijian" ready
```

### 验证步骤

1. **私聊测试**：在飞书中搜索机器人名称，发送一条消息，确认收到回复
2. **群聊测试**：在机器人所在群聊中 @机器人 发送消息
3. **查看日志**：`openclaw logs --follow` 确认消息被接收和处理

---

## 架构说明：单 Bot + sessions_spawn

### 为什么飞书推荐单 Bot？

| 特性 | Discord | 飞书 |
|------|---------|------|
| Bot 互相 @触发 | ✅ 支持 | ❌ **不支持** |
| 多 Bot 频道派活 | ✅ 适合 | ❌ 行不通 |
| 推荐架构 | 多 Bot + @mention | **单 Bot + sessions_spawn** |

飞书 Bot 发出的 @mention 不会被其他 Bot 识别为事件。所以 Discord 那种「司礼监在频道里 @兵部 派活」的模式，在飞书上**完全行不通**。

### 单 Bot 架构工作流

```
用户 → @司礼监（飞书唯一 Bot）
         │
         ├── sessions_spawn → 兵部（后台编码）
         │                      └── 完成 → 结果回到司礼监
         ├── sessions_spawn → 户部（后台分析）
         │                      └── 完成 → 结果回到司礼监
         └── 司礼监汇总结果 → 回复用户
```

**对用户来说**：只看到司礼监一个 Bot，体验简洁。
**对系统来说**：10 个 Agent 在后台各司其职，完整朝廷在运转。

### 司礼监飞书版 vs Discord 版

| | Discord 版 | 飞书版 |
|---|---|---|
| 派活方式 | 在频道 @部门bot | `sessions_spawn` 后台派发 |
| 工作可见性 | 频道内公开可见 | 后台执行，司礼监汇报结果 |
| 需要的 Bot 数量 | 10 个 Discord Bot | **1 个飞书应用** |

> 💡 **Discord 用 @部门派活，飞书用 sessions_spawn 派活。** 两种模式功能完全一样，只是调度方式不同。

---

## 完整配置示例（单 Bot 推荐）

以下是飞书单 Bot 模式的完整配置：

```json
{
  "channels": {
    "discord": {
      "enabled": false,
      "accounts": {}
    },
    "feishu": {
      "enabled": true,
      "dmPolicy": "open",
      "groupPolicy": "open",
      "accounts": {
        "silijian": {
          "appId": "cli_你的司礼监AppId",
          "appSecret": "你的司礼监Secret",
          "name": "司礼监",
          "groupPolicy": "open"
        }
      }
    }
  },
  "agents": {
    "defaults": {
      "workspace": "/root/clawd",
      "model": { "primary": "your-provider/fast-model" },
      "sandbox": { "mode": "non-main" }
    },
    "list": [
      {
        "id": "silijian",
        "name": "司礼监",
        "default": true,
        "identity": { "theme": "你是AI朝廷的司礼监大内总管。你的职责是【规划调度】，不是亲自执行。说话简练干脆。\n\n【核心原则】除了日常闲聊和简单问答，所有涉及实际工作的任务（写代码、查资料、分析数据、写文案、运维操作等），一律使用 sessions_spawn 派发给对应部门执行。你是指挥官，不是搬砖工。\n\n【部门职责】内阁=战略决策、都察院=审查监察、兵部=编码开发、户部=财务分析、礼部=品牌营销、工部=运维部署、吏部=项目管理、刑部=法务合规、翰林院=研究文档。\n\n【派活方式】使用 sessions_spawn 将任务派发给对应部门的 agentId。派活时用高级 Prompt 模板：【角色】+【任务】+【背景】+【要求】+【格式】，确保一次性给出所有约束。完成后主动向用户汇报结果摘要。\n\n【审批流程】涉及代码提交 → spawn 都察院审查；涉及重大决策（预算、架构、方向变更）→ spawn 内阁审议。都察院审查不通过则打回修改，内阁有否决权。\n\n【什么时候自己回答】仅限：纯闲聊、确认信息、汇报进度、问澄清问题。其他一律派活。" },
        "subagents": {
          "allowAgents": ["neige", "duchayuan", "bingbu", "hubu", "libu", "gongbu", "libu2", "xingbu", "hanlinyuan"]
        }
      },
      { "id": "neige" },
      { "id": "duchayuan" },
      { "id": "bingbu" },
      { "id": "hubu" },
      { "id": "libu" },
      { "id": "gongbu" },
      { "id": "libu2" },
      { "id": "xingbu" },
      { "id": "hanlinyuan" }
    ]
  },
  "bindings": [
    { "agentId": "silijian", "match": { "channel": "feishu", "accountId": "silijian" } }
  ]
}
```

> 💡 **注意**：10 个 Agent 全部保留（后台工作），但只需要 1 条 binding（飞书 → 司礼监）。其他部门通过 `sessions_spawn` 被司礼监调度，不需要独立的飞书应用。

---

## 高级用法：多 Bot 模式（可选）

> ⚠️ **不推荐飞书新用户使用此模式。** 飞书 Bot 不能互相 @触发，多 Bot 模式只适用于需要**多个独立入口**的场景（如不同群绑定不同部门 Bot）。大多数用户使用上面的单 Bot 模式即可。

如果你确实需要多个独立的飞书 Bot 入口，可以创建多个飞书应用：

### 适用场景

- 不同飞书群需要绑定不同部门（如「开发群」绑兵部，「运营群」绑礼部）
- 需要用户直接与特定部门对话，而非通过司礼监中转
- 企业内部不同团队使用不同 Bot

### 多 Bot 配置示例

```json
{
  "channels": {
    "feishu": {
      "enabled": true,
      "dmPolicy": "open",
      "groupPolicy": "open",
      "accounts": {
        "silijian": {
          "appId": "cli_司礼监的AppId",
          "appSecret": "司礼监的Secret",
          "name": "司礼监",
          "groupPolicy": "open"
        },
        "bingbu": {
          "appId": "cli_兵部的AppId",
          "appSecret": "兵部的Secret",
          "name": "兵部",
          "groupPolicy": "open"
        }
      }
    }
  },
  "bindings": [
    { "agentId": "silijian", "match": { "channel": "feishu", "accountId": "silijian" } },
    { "agentId": "bingbu", "match": { "channel": "feishu", "accountId": "bingbu" } }
  ]
}
```

> ⚠️ **注意**：多 Bot 模式下各 Bot 之间**不能**通过 @mention 互相触发。跨部门协作仍然需要 `sessions_spawn` 或 `sessions_send`。

---

## Lark 国际版

如果使用 Lark（国际版），在配置中加上 `domain: "lark"`：

```json
{
  "channels": {
    "feishu": {
      "domain": "lark",
      "enabled": true,
      "dmPolicy": "open",
      "groupPolicy": "open",
      "accounts": {
        "silijian": {
          "appId": "cli_xxx",
          "appSecret": "xxx",
          "name": "司礼监",
          "groupPolicy": "open"
        }
      }
    }
  }
}
```

---

## 省配额优化（可选）

减少飞书 API 调用量：

```json
{
  "channels": {
    "feishu": {
      "typingIndicator": false,
      "resolveSenderNames": false
    }
  }
}
```

| 选项 | 默认 | 说明 |
|------|------|------|
| `typingIndicator` | true | 发送"正在输入"状态，关闭可减少 API 调用 |
| `resolveSenderNames` | true | 查询发送者姓名，关闭可减少 API 调用 |

---

## 诊断与排查

### 使用 doctor.sh 检查配置

项目自带诊断脚本，可以自动检测飞书配置问题：

```bash
bash doctor.sh
```

doctor.sh 会检查：
- ✅ 飞书是否启用
- ✅ account 的 appId 格式（应以 `cli_` 开头）
- ✅ appSecret 是否已填写（非占位符）
- ✅ groupPolicy 是否设为 open
- ✅ bindings 是否正确路由

### 使用 OpenClaw 自带 doctor

```bash
openclaw doctor
```

重点关注输出中的 **Channel status** 部分，会显示 `Feishu: ok` 或报错信息。

### 查看 Gateway 日志

```bash
# 实时查看日志
openclaw logs --follow

# 或查看最近日志
openclaw gateway logs
```

日志中常见的飞书相关信息：

| 日志内容 | 含义 |
|---------|------|
| `feishu: connected (ws)` | WebSocket 连接成功 ✅ |
| `feishu: account "xxx" ready` | Bot 就绪 ✅ |
| `feishu: ws error` | WebSocket 连接失败 ❌ |
| `feishu: auth failed` | 认证失败（appId/appSecret 错误）❌ |
| `feishu: event received` | 收到飞书事件 ✅ |

### 飞书开放平台日志

在飞书开放平台查看服务端日志：

1. 进入应用 → **事件订阅** → 查看「近期事件」
2. 进入 **开发者后台** → **日志查询** → 筛选 API 调用记录
3. 事件推送失败会在「近期事件」中标红显示

---

## 常见报错及解决方案

### 1. WebSocket 连接失败

**症状：** 日志显示 `feishu: ws error` 或连接超时

**排查：**
```bash
# 检查网络连通性
curl -v https://open.feishu.cn/open-apis/bot/v2/app/info
# 检查 DNS 解析
nslookup open.feishu.cn
```

**解决方案：**
- 确认服务器能访问 `open.feishu.cn`（国内服务器通常没问题）
- 如果是海外服务器，确认没有防火墙阻断到飞书的连接
- 检查是否有代理设置影响 WebSocket 连接
- 重启 Gateway：`openclaw gateway restart`

### 2. 认证失败（appId/appSecret 错误）

**症状：** 日志显示 `auth failed` 或 `invalid app credentials`

**解决方案：**
- 重新检查飞书开放平台的 **凭证与基础信息** 页面
- appId 应以 `cli_` 开头
- appSecret 需要完整复制，注意前后不要有空格
- 运行 `bash doctor.sh` 检查配置中是否有占位符

### 3. 权限不足

**症状：** 机器人能收到消息但无法回复，或日志显示 `permission denied`

**解决方案：**
- 飞书开放平台 → 权限管理 → 确认所有权限状态为「已开通」
- 如果有权限显示「待审批」，联系企业管理员审批
- 权限变更后需要 **重新发布应用版本** 才生效

### 4. 事件订阅未生效

**症状：** 飞书群里发消息，日志完全没有反应

**排查清单：**
1. 飞书开放平台 → 事件订阅 → 确认添加了 `im.message.receive_v1`
2. 确认选择了 **WebSocket 长连接** 模式（不是 HTTP 回调）
3. 确认应用已 **发布**（未发布的应用不会收到事件）
4. 确认 Gateway 正在运行：`openclaw gateway status`
5. 查看飞书开放平台 → 事件订阅 → 「近期事件」是否有推送记录

### 5. 群消息不响应

**症状：** 私聊正常，群聊不触发

**解决方案：**
- 确认 account 配置中有 `"groupPolicy": "open"`
- 确认机器人已添加到群聊（群设置 → 群机器人）
- 部分群可能需要 @机器人 才触发，设置 `groupPolicy: "open"` 可免 @
- 运行 `bash doctor.sh` 检查 groupPolicy 配置

### 6. 发送消息失败

**症状：** 能收到消息但回复失败，日志显示 send error

**解决方案：**
- 确认有 `im:message:send_as_bot` 权限
- 确认应用版本已发布
- 如果是群聊，确认机器人仍在群中（未被移除）
- 检查消息内容是否超过飞书限制（单条消息最大约 4000 字符）

---

## 常见问题

**Q: 需要公网 IP 吗？**
A: 不需要。飞书的 WebSocket 模式是由你的服务器主动连接飞书服务器，不需要公网 IP 或域名。

**Q: 飞书个人版能用吗？**
A: 不能。飞书开放平台的自建应用功能需要企业版。免费的企业版也可以。

**Q: 飞书需要创建几个应用？**
A: **只需 1 个。** 创建司礼监应用即可，其他部门通过 `sessions_spawn` 后台调度，不需要独立的飞书应用。

**Q: 可以同时用 Discord 和飞书吗？**
A: 可以。在配置中同时启用 discord 和 feishu，各自配置 accounts 和 bindings 即可。Discord 用多 Bot + @mention 模式，飞书用单 Bot + sessions_spawn 模式。

**Q: 飞书 token 会过期吗？**
A: WebSocket 模式下 OpenClaw 会自动管理 token 刷新，不需要手动处理。

**Q: 怎么重新生成 App Secret？**
A: 飞书开放平台 → 凭证与基础信息 → 重置 App Secret。注意重置后需要更新配置文件并重启 Gateway。

**Q: Discord 用 @部门派活，飞书怎么派活？**
A: 飞书用 `sessions_spawn`。司礼监收到任务后，自动用 `sessions_spawn` 把任务派给对应部门的 agentId，部门完成后结果回到司礼监，由司礼监向用户汇报。效果完全一样，只是调度方式不同。
