第 10 章 · 01 IM 机器人(飞书/QQ/微信)集成 本节摘要:本节精读 (15674 行)——把 Reasonix agent 接入国内三大 IM(飞书 feishu、QQ、微信 weixin)。用户在 IM 里发消息,本地 bot 网关(desktop 运行时或 无头进程)接收,走完整的 Controller→agent→工具→权限→沙箱管线,把进度和结果回推到 IM。三种 IM 各有特色:飞书用 larksuite/oapi-sdk-go/v3,支持交互卡片按钮审批( );QQ 用官方 QQ Bot API,支持内联键盘( );微信走 Bot Assistant 扫码,无按钮用文本命令( )。
本节摘要:本节精读
internal/bot(15674 行)——把 Reasonix agent 接入国内三大 IM(飞书 feishu、QQ、微信 weixin)。用户在 IM 里发消息,本地 bot 网关(desktop 运行时或reasonix bot start无头进程)接收,走完整的 Controller→agent→工具→权限→沙箱管线,把进度和结果回推到 IM。三种 IM 各有特色:飞书用 larksuite/oapi-sdk-go/v3,支持交互卡片按钮审批(images/bot-feishu-approval.svg);QQ 用官方 QQ Bot API,支持内联键盘(images/bot-qq-approval.svg);微信走 Bot Assistant 扫码,无按钮用文本命令(images/bot-weixin-text-commands.svg)。本节还讲 IM 审批流程(agent 请求工具批准 → IM 推送审批卡 → 用户批准/拒绝,见images/bot-lark-yolo.svg)、IM 文本命令(/approve、/yolo、/use project等直接操控 agent)、以及把 agent 接入国内 IM 的实战(飞书机器人创建/QQ 频道/微信)。
内容来源:原项目源码
internal/bot/、docs/BOT_GUIDE.md,go.modgithub.com/larksuite/oapi-sdk-go/v3 v3.9.5,配图images/bot-feishu-approval.svg、images/bot-qq-approval.svg、images/bot-weixin-text-commands.svg、images/bot-lark-yolo.svg。
⚠️ 注意:IM bot 是 Reasonix 的"第四前端"——它不走 control.Controller 的命令/事件双流(那是 TUI/SSE/桌面),但走完整的 agent 管线(同一个 Controller、同一套权限/沙箱/审批规则)。本节聚焦三大 IM 的差异与审批流程,不深入各 IM 平台的 OAuth 细节。
阅读完本节,你应当能够:
reasonix bot start 无头进程)。/help、/status、/approve、/yolo、/use project 等)。第 8 章讲了三个前端(TUI/SSE/桌面)共享 control.Controller。IM bot 是特殊的"第四前端"——它不直接驱动 Controller 的命令流,而是通过桌面 bot 运行时(第 8 章讲过 bot_bridge.go)或无头 CLI 网关接入。
BOT_GUIDE.md 一句话讲清定位:
After a bot is connected, you can send Reasonix messages from Feishu, Lark, WeChat, or QQ. The desktop app or `reasonix bot start` process handles the model, tools, permissions, sandboxing, and local context, then sends progress and results back to the IM channel.
关键信息:
这保证了一致性——远程 IM 用户和本地 TUI 用户跑的是同一个 agent,受同一套权限和沙箱约束,没有任何"IM 后门"。BOT_GUIDE.md 明确:
Remote users go through the same controller, permission policy, tool approval mode, and sandbox rules as local desktop or CLI turns.
这是安全的关键——IM bot 没有绕过任何安全层(第 9 章)。
IM bot 有两个等价的运行入口,共享同一份配置([[bot.connections]]、[bot.allowlist]、[[bot.routes]] 等):
桌面应用的 Settings → Bots 配置 bot。桌面应用启动网关、保持状态、持久化每次连接的工具批准模式,还能打开对应的本地 IM 会话查看上下文/成本/token/工具轨迹。桌面是创建和测试 bot 连接最方便的方式,也是 IM bot 的"集成枢纽"(第 8 章第 2 节提过桌面同时承载 bot 运行时)。
reasonix bot doctor reasonix bot doctor --deep reasonix bot start --channels qq,feishu,lark,weixin --dir /path/to/project
reasonix bot start 是无头长驻进程,用同一份配置、同一份 allowlist、同一套路由、同一个 pairing store、同一套 adapter、同一个项目/会话索引。--channels 选要接哪些 IM 输入,--dir 把进来的消息路由到某个项目工作区,--model 覆盖默认模型。
注意:reasonix run(普通一次性任务)不会自动启动 IM 网关。IM bot 行为只在桌面 bot 运行时运行或 reasonix bot start 进程存活时才激活。
reasonix bot doctor --deep 报告队列、pairing、角色诊断,是排查 IM 连接问题的利器。
飞书用官方 SDK——go.mod 里:
github.com/larksuite/oapi-sdk-go/v3 v3.9.5
internal/bot/feishu/ 实现 adapter:feishu.go(主)、inbound.go(入站消息)、outbound.go/outbound_media.go(出站回复含媒体)、retry.go(重试)。
连接步骤:
飞书和 Lark 是同一套 SDK、同一套能力,但存为两个独立连接——可以给它们配不同的模型、工作目录、工具批准模式。
飞书的核心交互能力:交互卡片按钮。bot 文本回复作为独立的 Interactive Card JSON 2.0 markdown 发送,避免飞书/Lark 平台的引用前缀,同时保留 CommonMark 格式。卡片太大超过平台限制时,自动降级为纯文本。审批用卡片按钮(images/bot-feishu-approval.svg)。
webhook 模式下,配 verification token。入站 webhook 事件 fail-closed 校验——配置的 token 为空或缺失时拒绝调用,不静默开放 webhook。
internal/bot/qq/ 实现 adapter:adapter.go、gateway.go。QQ 用官方 QQ Bot 平台 API。
连接步骤(和飞书不同——不支持扫码,必须手动配):
QQ_BOT_APP_SECRET)。QQ 支持内联键盘按钮做审批(images/bot-qq-approval.svg)。Ask 问题作为文本发送,用普通文本、选项编号或 /answer <id> <answer> 回复。按钮过期或平台报告动作失败时,复制卡片里的 ID,发等价的文本命令。
QQ adapter 只读配置的 app_secret_env 值,不回退到无关的 QQ_SECRET 环境变量——这是安全细节,避免误读错环境变量导致泄密。QQ 和微信的 HTTP 调用用 bounded client,防止单个卡住的 provider 请求无限期阻塞网关。
微信走 Bot Assistant 扫码登录。连接步骤:
微信没有交互卡片按钮——审批用数字或文本命令(images/bot-weixin-text-commands.svg)。回复 1 批准、2 拒绝。Ask 问题用普通文本回复、选项编号或 /answer <id> <answer>。
BOT_GUIDE.md 给出官方对比:
| 频道 | 连接方式 | 审批 | Ask 问题 | 适合 |
|---|---|---|---|---|
| 飞书 Feishu | 扫码创建 PersonalAgent | 交互卡片按钮 或 命令 | 卡片按钮 或 命令 | 飞书工作区、DM、群 |
| Lark | 扫码创建 PersonalAgent | 卡片按钮 或 命令 | 卡片按钮 或 命令 | 国际 Lark 工作区 |
| 微信 WeChat | 微信扫码 | 回复 1/2 或 命令 |
普通文本/选项号/命令 | 轻量个人/移动测试 |
| 手动(App ID + App Secret) | 内联键盘/数字/命令 | 文本/选项号/命令 | QQ 群、DM、官方 QQ Bot 平台 |
飞书/Lark 卡片按钮会转换为命令(/approve <id>、/deny <id>、/answer <id> <option>)。QQ 按钮同理。按钮失效就发文本命令。
这是 IM bot 最核心的交互——agent 在执行中请求工具批准,IM 推送审批,用户在 IM 里批准或拒绝。
BOT_GUIDE.md 的时序图把流程讲清:
用户 → IM: 发请求 IM → 本地网关: 消息进入 bot 网关 网关 → 模型/工具: 模型推理,调工具 分支一(普通回复):网关 → IM: 直接发答案 分支二(需要审批): 网关 → IM: 发审批卡或审批文本 用户 → IM: 允许或拒绝 IM → 网关: 审批命令 网关 → 工具: 继续 or 停止该工具调用 网关 → IM: 发结果 分支三(需要用户选择 Ask): 网关 → IM: 发 Ask 问题 用户 → IM: 选选项或 /answer 网关 → IM: 继续,发结果
IM bot 用同一套权限系统(第 9 章第 2 节)。三种模式:
images/bot-lark-yolo.svg)。YOLO 的边界(BOT_GUIDE.md 明确):YOLO 跳过普通审批提示,但不绕过硬 deny 规则,不替你回答模型 Ask 问题,不替你批准 plan-mode 计划审批。即 YOLO 是"信任加速器"不是"安全开关"——这是第 9 章第 2 节 permission 体系在 IM 场景的兑现。
IM bot 的访问控制是强制的——不是任何人发消息都能驱动 agent。配置维度:
[bot.allowlist] enabled = true feishu_users = ["ou_member"] # 普通用户 feishu_admins = ["ou_admin"] # 管理员(/yolo、/mode 等) feishu_approvers = ["ou_approver"] # 审批者(/approve、/deny)
按连接还能配更细的 access(enabled / allow_all / pairing_enabled / users / groups / admins / approvers)。连接有活跃 access 设置时,先于 legacy 全局 [bot.allowlist] 检查。
pairing 机制让未知 DM 发送者收到一次性配对码,本地 reasonix bot pairing approve <code> 批准后才加入 access list。群聊不会被 DM pairing 或角色准入打开——群 ID 是额外的收窄层。
敏感命令的角色约束:/yolo、/mode 在配了 admins 时是 admin-only;/approve、/deny 需要 approver 或 admin;/projects、/use project、/sessions、/attach session、/search all 在配了角色列表时也 admin-only。
IM 里有完整的 slash 命令体系——用户在 IM 里直接操控 agent,等同本地 TUI 的能力。这些命令在飞书/Lark/微信/QQ 通用。
| 命令 | 作用 |
|---|---|
/help |
显示可用命令 |
/status |
显示活动任务、队列状态、工具批准模式、adapter 健康 |
/stop |
停止当前任务 |
/new |
开新会话 |
/reset |
重置当前会话 |
/approve <id> |
批准待审批操作 |
/deny <id> |
拒绝待审批操作 |
/answer <id> <option> |
回答 Ask 问题 |
| 命令 | 作用 |
|---|---|
/yolo / /yolo on / /yolo off / /yolo auto / /yolo status |
YOLO 模式开关 |
/mode yolo / /mode ask / /mode auto |
切换工具批准模式 |
/queue status / /queue steer / /queue followup / /queue collect / /queue interrupt |
队列模式 |
队列模式四种——默认 steer(同会话已运行时,新消息作为中途指导注入当前回合)、followup(排队为后续回合)、collect(合并为一个后续回合)、interrupt(取消当前任务保留最新消息)。steer 是第 6 章"ride the turn tail"哲学在 IM 场景的应用——新消息追加到尾部,不重新开回合。
| 命令 | 作用 |
|---|---|
/projects [query] |
列出索引的项目工作区 |
/use project <id|name> |
把当前远程会话路由到一个索引项目 |
/use project default |
清除项目覆盖 |
/sessions search <query> |
搜索索引的桌面/bot 会话 |
/attach session <id|query> |
从索引的 path: 转录继续远程会话 |
/search all <query> |
跨索引项目根搜索文件内容 |
关键安全约束——这些导航命令永远不接受从 IM 输入的任意路径。它们只跳索引目标(配置的 bot routes 工作区、连接工作区、活跃 bot 会话、保存的 session mappings)。这防止 IM 用户用 /use project /etc 之类跳到敏感目录。
1 批准、2 拒绝。1/2 当普通文本处理。[bot.connections] 的 workspace_root、model、tool_approval_mode(可每连接独立)。[bot.allowlist] 的 feishu_users/admins/approvers,限制谁能用。/status 是否正常。生产建议:开 guardian(第 9 章)、用 ask 模式不要 YOLO、配 approver 角色限制审批权、用 [[bot.routes]] 按聊天类型/用户/线程精细路由。
QQ_BOT_APP_SECRET(或配 app_secret_env 指向别的变量名)。QQ_SECRET。/approve。1/2 或 /approve//deny;Ask 用普通文本或 /answer。三大 IM 共用 TOML 配置:
[[bot.connections]] provider = "feishu" # adapter 家族:feishu/weixin/qq domain = "lark" # 区分变体如 Feishu vs Lark credential.app_id = "..." credential.app_secret_env = "..." workspace_root = "/path/to/project" model = "deepseek-pro" tool_approval_mode = "ask"
provider 是 adapter 家族,domain 区分变体(Feishu vs Lark)。每连接可独立设工作区、模型、批准模式。[[bot.routes]] 还能按连接/平台/聊天类型/聊天 ID/用户 ID/线程 ID 加更细的路由,空匹配字段是通配符,首个匹配的路由胜出。
[bot.control] 段暴露本地回环 HTTP API,默认禁用。启用时必须配 token_env,每个请求带 Authorization: Bearer <token>,只绑定 localhost/127.0.0.1/::1。端点:GET /status(会话和 adapter 健康快照)、GET /metrics(Prometheus 文本指标)、POST /send(通过配置的连接发文本或媒体)。这让外部监控系统(如 Grafana)能观测 bot 状态。
💡 契约要点:IM bot 是 Reasonix 把 agent 从开发者笔记本延伸到团队协作场景的关键。三大 IM 用同一套本地网关、同一套配置结构、同一套权限/沙箱/审批规则——只是 adapter 层(交互卡片 vs 文本命令)因平台能力而异。远程 IM 用户和本地 TUI 用户跑同一个 agent,没有后门。导航命令拒绝任意路径只跳索引目标,是 IM 场景特有的安全收窄。
reasonix bot start)处理模型/工具/权限/沙箱/上下文,IM 只当传输层;远程用户走同一 Controller 同一套安全规则,无后门。reasonix bot start --channels ... --dir ...),共享同一份配置;reasonix run 不自动启网关。QQ_BOT_APP_SECRET);不回退无关 QQ_SECRET;内联键盘审批;bounded client 防阻塞。1/2 或命令审批;适合轻量测试。[[bot.connections]] + [[bot.routes]] 配置;可选 [bot.control] 本地控制 API。下一节讲 SSH Remote-SSH(internal/remote 端口转发/SFTP 文件层/bootstrap 远端 serve)和桌面全栈(Wails + React 19 + 8 套主题)+ ACP VS Code 扩展,把 Reasonix 从本地延伸到远程开发场景。