# 飞书联调指南(完整版) > 目标:**只看这一篇文档,就能把 dsh-im-feishu 从零跑通**——在飞书里指挥 DeepSeek Harness 的真实 agent。 > > 全文约 15 分钟。分四部分: > ① 接入飞书(扫码 1 分钟 / 手动 10 分钟,二选一) > ② 安装插件(一条命令) > ③ 在飞书里使用(派活 / 审批 / 查状态) > ④ 常见问题排查 --- ## 先说清楚:这个"界面"是什么 **这个插件没有网页界面。** 它的"界面"就是**飞书的聊天窗口**: - 你在飞书里私聊机器人 = 给 agent 派活 - agent 的回答 = 机器人发回的消息(带流式打字效果) - 危险操作 = 机器人发来一张**审批卡片**,上面有【批准】【拒绝】按钮 - 你不在电脑前,手机上的飞书就是全部操作界面 你的电脑上只需要跑一个**后台进程**(桥接程序),它负责:连飞书长连接收消息 → 交给 agent 干活 → 把结果发回飞书。终端窗口只用来观察连接状态。 --- ## ① 接入飞书(二选一:网页扫码 1 分钟 / 手动 10 分钟) ### 方式一:网页扫码接入(推荐,约 1 分钟,不碰终端) 不需要手动建应用、勾权限、配订阅——**在 DeepSeek Harness 网页里直接扫码**, 应用名、权限、事件、回调都按本插件需求**预填**: 1. 启动 `dsh web`,打开浏览器 **设置 → 插件 → 飞书** 页签 2. 点「**📱 扫码绑定 | Scan to connect**」 3. 网页出现**二维码** → 用**手机飞书扫码** → 在手机上确认(预填项都在,无需改动) 4. 页面显示「🎉 绑定成功」→ **重启 `dsh web`**,在飞书里私聊机器人开始使用 > 说明: > - 凭据写入 Host 本机 `$DSH_HOME/dsh-im/feishu-credentials.json`(仅本机可读), > **App Secret 不会出现在浏览器里**,也无需设置任何环境变量。 > - 预填的权限/事件/回调走飞书官方灰度(平台支持才自动生效);灰度未覆盖时确认页是默认模板, > 按下方「方式三」手动补勾即可,结果一样。 > - 扫码创建的应用属于扫码人所在企业,需要是企业成员(自己当管理员最省事)。 ### 方式二:终端扫码(CLI,1 分钟) 没有网页时用:`npx -y dsh-im-feishu-qr` → 终端二维码 → 手机飞书扫码 → 重启。 ### 方式三:手动创建(扫码失败 / 需要精细控制时) 下面的手动步骤与扫码等价,三选一即可。 > ⚠️ 长连接模式**只支持企业自建应用**(个人/商店应用不行)。你需要是企业管理成员(自己就是管理员最省事,发布不用等别人批)。 ### 1. 创建应用 1. 打开 [飞书开放平台](https://open.feishu.cn/app),用飞书账号登录 2. 点「**创建企业自建应用**」 3. 填应用名称(如 `DSH Agent`)、图标(随意选一个) 4. 创建后进入应用详情页 ### 2. 开启机器人能力 左侧菜单「**添加应用能力**」→「**机器人**」→ 打开开关。 ### 3. 记录凭据 左侧「**凭证与基础信息**」→「**应用凭证**」,记录两样: | 名称 | 示例 | 说明 | |---|---|---| | **App ID** | `cli_你的AppID` | 公开标识,`cli_` 开头 | | **App Secret** | `你的AppSecret` | **相当于密码**,只在你自己的机器上使用;怀疑泄露可在后台重置 | ### 4. 添加权限 左侧「**权限管理**」→「**添加权限**」,搜索并添加以下权限(**必须**): | 权限标识 | 说明 | |---|---| | `im:message.p2p_msg:readonly` | **接收用户单聊消息必需**(事件 `im.message.receive_v1` 推送依赖它,官方文档明确要求) | | `im:message:send_as_bot` | 以机器人身份发送消息(回消息/发审批卡片必需) | > ⚠️ 坑:笼统的 `im:message` **不能**让事件订阅生效。接收单聊消息必须 > `im:message.p2p_msg:readonly`;接收群聊 @ 机器人消息必须 `im:message.group_at_msg:readonly`(群聊可选)。 可选(用到再加): | 权限标识 | 说明 | |---|---| | `im:message.group_at_msg:readonly` | 接收群聊中 @ 机器人的消息(群聊用) | | `im:resource` | 读取图片/文件资源(IM 附件落盘用) | | `im:chat:readonly` | 读取群信息(群聊用) | ### 5. 订阅「事件」——接收用户消息 左侧「**开发配置**」→「**事件与回调**」→ 页面顶部点「**事件配置**」页签: 1. 订阅方式选「**使用长连接接收事件**」(本地就能收,不需要公网 IP/域名) 2. 点「**添加事件**」,搜索并添加:**接收消息**(事件名 `im.message.receive_v1`) 3. 保存 > 注意:长连接模式只有**企业自建应用**能用;添加事件后必须**发布版本**才生效(见第 7 步)。 ### 6. 订阅「回调」——接收审批按钮点击(关键,容易找错地方) `card.action.trigger` **不在「事件配置」里**,它在**另一个页签**: 1. 仍在「**开发配置**」→「**事件与回调**」页面 2. 页面顶部点「**回调配置**」页签(⚠️ 不是「事件配置」!) 3. 页面底部「已订阅的回调」→「**添加回调**」 4. 选择「**卡片回传交互**」(对应新版事件名 `card.action.trigger`)→ 确认添加 5. 保存 > 漏掉这一步的后果:审批卡片能收到、能显示,但点【批准】【拒绝】按钮没反应。 > 在配好之前,审批可以用文本命令代替:`/approve yes`(见 ③)。 ### 7. 设置可用范围 + 发布版本(不发布 = 白配) **可用范围**:左侧「**权限管理**」→「**可用范围**」→ 把你自己(和要使用的人)加入。 否则机器人收不到你的消息。 **发布**:左侧「**应用发布**」→「**版本管理与发布**」→「**创建版本**」: 1. 填版本号(如 `1.0.0`、`1.0.1`)、更新说明 2. 保存 → **申请线上发布** 3. 等企业管理员审批通过(如果应用是你创建的且你是管理员,通常自己点一下就过) > 每次修改权限/事件/回调后,都要**重新创建版本并发布**才会生效。 ### 8. 自查清单(发布后对照) - [ ] 应用是**企业自建应用** - [ ] 机器人能力已开启 - [ ] 有 `im:message.p2p_msg:readonly`(收单聊必需)和 `im:message:send_as_bot`(发送必需)权限 - [ ] 「事件配置」里加了 `im.message.receive_v1`,订阅方式为**长连接** - [ ] 「**回调配置**」里加了 `card.action.trigger`(审批按钮用) - [ ] 可用范围包含你 - [ ] 最新版本已发布并通过审批 --- ## ② 安装插件(一条命令) **前提**:已装好 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)(`dsh` 命令可用;提示 `command not found` 先 `npm install -g @deepseek-ai/dsh`)。 ```sh dsh plugin --profile web add dsh-im dsh-im-feishu -w ``` > `-w` 是给 pnpm 的(profile 是 workspace 根,pnpm 9 必须显式声明;报 `ERR_PNPM_ADDING_TO_ROOT` 时带上它)。 **配置环境变量**(在启动 `dsh web` 前导出): | 变量 | 来源 | 必须 | |---|---|---| | `FEISHU_APP_ID` | 飞书开放平台 → 凭证与基础信息 | ✅ | | `FEISHU_APP_SECRET` | 同上 | ✅ | | `DEEPSEEK_API_KEY` | DeepSeek 开放平台 | ✅ | ```sh export FEISHU_APP_ID=cli_你的AppID export FEISHU_APP_SECRET=你的AppSecret export DEEPSEEK_API_KEY=sk-你的Key dsh web ``` 启动后飞书通道自动连接(官方长连接,免公网);在飞书里私聊机器人即可使用。 > 想不装进 DSH、克隆仓库直接跑联调脚本?见文末「附:不装进 DSH 的联调方式」。 ## ③ 在飞书里使用 打开飞书 App/桌面端 → 搜索你的机器人应用名 → **私聊它**。 ### 第一次:信任确认 - **普通用户零配置**:你的第一条消息会收到"尚未被授权/已向管理员确认"提示,管理员(配置里 `security.admins` 的人)点 ✅ 按钮或回复 `/trust feishu:<你的open_id>` 即放行,永久生效。 - **管理员只需配置一次**:在 `$DSH_HOME/profiles/web/cordis.patch.yml` 的 `im.security.admins` 里填入**你自己的**用户键(如 `["feishu:ou_78e92c..."]`)即可——管理员隐式放行,无需重复写 `allowlist`。 - 个人自用想省事:把 `im.security.trustOnFirstContact` 设为 `true`(首条消息自动信任,跳过确认)。 ### 常用操作 | 你在飞书里发 | 会发生什么 | |---|---| | `/new` | 创建新会话,agent 就绪 | | 直接发任务,如 `列出当前目录内容` | agent 执行,**结果流式逐段发回**,最后附结果卡片(耗时 + token 用量) | | 任务里触发危险命令(如删除文件) | 收到**审批卡片**:工具名、参数(已脱敏)、风险等级、【批准】【拒绝】按钮 | | 点【批准】 | agent 继续执行,完成后发结果卡片 | | 点【拒绝】 | agent 收到"用户拒绝了",停止该操作 | | `/approve yes` 或 `/approve no` | 文本方式审批(卡片按钮没配好时用这个) | | `/status` | 渠道连接状态、会话列表、等待中的审批 | | `/log` | 把最近一次任务的**完整输出**以文件发回(长输出被截断时用) | | `/mute` `/unmute` | 关闭/打开本聊天通知 | | `/help` | 命令列表 | ### 群聊(可选) 把机器人拉进群,群里 @ 机器人 发消息即可;群里只有 allowlist 成员能派活,管理员才能审批。 --- ## ④ 常见问题排查 | 现象 | 原因与解决 | |---|---| | 启动 `dsh web` 报 `appSecret or clientAssertionProvider is required` | **没配凭据**:要么 `export FEISHU_APP_ID / FEISHU_APP_SECRET` 再启动,要么用 `npx -y dsh-im-feishu-qr` 扫码接入(自动写凭据文件);缺凭据时通道会优雅断开,不会崩整个 dsh web | | 飞书通道没连上 | ① App ID/Secret 复制完整吗?② 应用是企业自建吗?③ 长连接只认 `cli_` 开头的 ID ④ 环境变量有没有在启动 `dsh web` 前导出 | | 连上了,但发消息 bot 不回 | ① 「事件配置」里加了 `im.message.receive_v1` 并**发布**了吗?② 可用范围包含你吗?③ 你私聊的是这个应用吗? | | bot 回消息报"无权限"/"未授权" | 首次接触触发信任流程:管理员 `/trust feishu:` 授权;或配置 `trustOnFirstContact: true` 自动信任 | | 审批卡片显示但**按钮点了没反应** | 「回调配置」页签里没加 `card.action.trigger`(见 ① 第 6 步),或用 `/approve yes` 文本审批 | | 发消息报权限错误 | 缺 `im:message:send_as_bot` 权限,或新权限没重新发布版本 | | 改了配置不生效 | 每次改权限/事件/回调都要**重新创建版本并发布**,等审批通过 | | agent 执行出错 | 终端窗口会打印 agent 日志;把终端输出截图给我排查 | --- ## 附:不装进 DSH 的联调方式(开发者) 需要克隆本仓库 + Node.js 22+: ```sh npm install FEISHU_APP_ID=cli_xxx FEISHU_APP_SECRET=xxx DEEPSEEK_API_KEY=sk-xxx \ node demo/feishu-real.mjs --mode demo ``` `--mode demo`:首条消息自动信任(个人联调用);`--mode prod`:严格 allowlist(真实部署基线)。 --- ## 附:真实效果长什么样 机器人发来的消息大致如下(飞书聊天窗口里): ``` ✅ 任务完成 完成!我做了以下操作: 1. 创建了 hello.py ... 2. 运行了它,输出 hello world ⏱ 5.8s · 🔢 790 in / 375 out tokens ``` 审批卡片: ``` 🔐 审批请求 工具: demo-shell 参数: {command=rm -rf build} 风险: high 原因: 工具 "demo-shell" 被判定为 high 风险(IM 远程审批,默认拒绝) 会话: im-feishu-oc_xxxxx [✅ 批准] [❌ 拒绝] ```