资讯动态

OpenClaw接入飞书实战:从消息回调到团队AI助手

发布时间:2026/10/20 11:40:37 来源:尧图企业网站定制
写完这篇指南之前先说说我在实际迭代中踩过的坑。团队协作工具里的 AI 助手跟网页端聊天机器人完全是两回事网页端不在乎谁来找你但飞书里至少得知道这是哪个群、哪个部门、了谁权限、隔离、超时重试、部署保活这些事每一项都直接影响“能不能稳定用”。所以这篇内容不只是贴一段接 Webhook 的代码而是从选型开始把 OpenClaw 接入飞书这件事完整拆开讲清楚我的落地方案和后来遇到的一堆现场问题。1. 方案先行为什么要把 OpenClaw 接到飞书上1.1 团队消息入口是天然的 AI 助手入口我们团队最早试过好几个形态独立网页、命令行、甚至做成了内部小站点。结果使用率一直上不去真正高频被用的反而是群里 机器人 这种最“原始”的方式。原因不复杂——大家上班本来就泡在飞书里查知识、转派事务、确认排期都是顺手的事。如果还要专门打开另一个页面哪怕只多一步使用意愿也会断崖式下降。把 OpenClaw 接到飞书本质上不是接一个 API而是把 AI 能力塞进大家原本就在用的消息流里。用户在群里发一句“帮我查一下本周的设备报修记录”机器人就能直接回答在单聊里问“下午两点会议改到四楼行不行”它也能去更新日程。这类交互适合谁我觉得最适合三种团队一是行政或客服性质的事务型岗位每天大量重复问答二是研发运维团队需要快速检索内部文档和工单三是管理者希望用自然语言把数据汇报拉到聊天窗口里。个人开发者同样能用同一套方案把自己家里的服务状态推给飞书群相当于拥有了一个会主动汇报的“值班机器人”。1.2 两种接入形态Webhook 回调与长连接飞书开放平台提供给开发者的机器人接入方式核心可以分为两类。第一类是 Webhook 回调。你在飞书开放平台配置一个公网 HTTPS 地址所有消息事件由飞书服务器主动 POST 到这个地址。这种模式链路直观、排查方便但要求你有一个稳定公网入口。家里宽带没有固定公网 IP、或者服务器藏在 NAT 后面的人会非常痛苦。第二类是长连接模式。飞书开放平台从早期单纯依赖 Webhook 扩展了长连接回传方式应用通过 SDK 主动和飞书服务端建立长连接事件会顺着这个已经建立的连接推下来。好处在于不需要公网回调地址只要能访问外网的服务器甚至开发机都能用。我实际测试下来长连接模式对个人部署特别友好省去了配置 Nginx 反向代理和 HTTPS 证书的环节。1.3 我为什么最终选择“长连接为主Webhook 为辅”个人部署我会推荐长连接。理由有三点第一免公网 IP 和域名一台云主机拉起进程就能跑第二SDK 自动处理断线重连稳定性比我最初写死 Webhook 时好很多第三省掉一层反向代理故障点变少。但如果是企业级场景尤其是需要把 OpenClaw 的能力嵌入到内部审批、工单这类系统里我还是建议用 Webhook 回调。因为企业内网通常有成熟的网关和统一鉴权策略回调链路更容易纳入监控消息轨迹也完整。两种模式不是互斥的飞书官方也允许应用同时配置。我的习惯是“开发调试用长连接正式多实例部署用 Webhook”生产环境还可以靠回调地址做负载均衡。这里先记住一个结论方案没有绝对好坏只有适不适合现有网络条件。2. 接入前的四个准备应用凭证、权限域、运行环境、依赖2.1 在飞书开放平台创建企业自建应用第一次操作的同学容易找不到入口实际上就是进飞书开放平台选择“企业自建应用”创建。创建完成后在“凭证与基础信息”里能看到 app_id 和 app_secret。这两个值一个用于识别应用身份一个用于签名和获取 token请务必像保存数据库密码一样对待它们。我习惯把这几个值直接写入环境变量而不是硬编码到代码里。app_id 和 app_secret 一旦泄露别人可以伪装成你的机器人在群里发消息轻则被管理员封禁重则引发安全事故。建议把这一条当作默认红线。在创建应用时还要选择“机器人”能力。这一步不选后面所有回调都不会生效。选完之后应用还处于未发布状态你自己能看到别人在群里根本找不到它所以后面必须走完发布流程。2.2 事件订阅与回调配置要让 OpenClaw 能收到用户消息必须在“事件订阅”中配置对应事件。核心事件是 im.message.receive_v1表示收到消息事件。它既覆盖单聊消息也覆盖群聊中 机器人 的消息。配置事件订阅时飞书会要求你填写“请求地址”。如果走 Webhook 模式这个地址必须是公网可达的 HTTPS 回调解如果你用长连接模式这个位置不需要填 URL但代码里必须用官方 SDK 建立长连接。这里有个高频误区不少人以为长连接不需要在后台“开启”其实还是要添加事件、订阅对应权限、并通过校验之后才会生效。同时需要留意“加密策略”。飞书允许配置 Encrypt Key 和 Verification Token。我自己强烈建议开启加密回调体里的内容会经过 AES 加密代码里解密后才能拿到明文。很多新手在这里栽跟头——因为回调验证时飞书返回的不是明文 challenge而是被加密后的字符串导致 URL 校验怎么都过不去。关于验证流程后面实操章节会专门给出代码。2.3 OpenClaw 运行时与模型 API 准备OpenClaw 的正常运转需要三样东西Python 运行时、LLM 模型的 API Key、以及执行工具链的环境。我目前用的是 Python 3.10安装 OpenClaw 的方式是pip install openclaw不同版本可能略有差异建议以官方安装文档为准。模型侧我同时保留了对话模型和嵌入模型两套配置对话模型负责回复生成嵌入模型负责把团队文档转成向量方便做知识库检索。接飞书时还需要一个飞书官方 SDK在 Python 里对应的包名通常是lark_oapi。这个 SDK 统一封装了获取 tenant_access_token、建立长连接、发送消息等操作比直接拼 REST API 省一半时间。2.4 权限的最小化原则很多机器人接完不能发消息九成原因都是权限没配够。飞书的权限系统非常细比如“读取单聊消息”“读取群组消息”“发送单聊消息”“发送群组消息”都是独立权限。你至少要给应用开启以下权限读取用户发给机器人的单聊消息、读取群聊中 机器人的消息、以应用身份发送消息。我的做法是先只开这几个最小权限跑通后再按功能增量加比如要让机器人读取云文档再加文档相关权限。尽量避免一次性开启“全部消息权限”那样每个群所有人都能命令你的机器人容易造成越权。权限配置完成后记得重新发布应用版本否则配置不会生效这是无数人验收时才发现的老坑。3. 实操从零到一完成 OpenClaw 接入飞书3.1 应用发布与可用性检查在开放平台左侧菜单找到“版本管理与发布”创建一个新版本并提交发布。管理员审核通过后应用才会出现在组织成员可见的机器人列表里。这里有个细节版本描述里最好写清楚机器人的功能和使用方式因为很多企业管理员会直接按描述判断要不要放行。发布完成之后在飞书搜索你创建的应用名就能看到机器人直接可以开始单聊测试。建议先手动在单聊里发一句“你好”观察事件是否进入你配置的回调服务或长连接日志。这一步能快速区分问题出在“应用没有消息权限”还是“代码链路不通”。3.2 回调服务的骨架代码挑战验证与事件转发这段代码我按“尽量跑起来”的标准给一个最小实现。无论你用长连接还是 Webhook事件处理的思路一致先解包再校验最后把消息交给 OpenClaw。用 Flask 写一个最小 Webhook 服务from flask import Flask, request, jsonify from lark_oapi.adapter.flask import adapter app Flask(__name__) app.route(/openclaw/callback, methods[POST]) def openclaw_callback(): payload request.json # 飞书 Webhook 模式首次配置时会发送 url_verification 挑战 if payload and payload.get(type) url_verification: return jsonify({ challenge: payload.get(challenge) }) # 其他消息事件交给后续处理 return handle_event(payload) if __name__ __main__: app.run(host0.0.0.0, port8000, debugFalse)如果开启了加密上面这段直接校验不过。要先用 Encrypt Key 解密import base64, json from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes def decrypt_payload(encrypt_key: str, data: str) - dict: # 实际实现请参考飞书官方 AES-256-CBC 示例注意填充逻辑 raw base64.b64decode(data) # 取出 key、iv、密文并按 PKCS7 解填充 return json.loads(decrypted_text)我个人不推荐自己手写解密太容易错。直接用lark_oapi官方事件处理器SDK 会在内部完成解密验证。下面这版是官方风格的简化形态from lark_oapi.api.im.v1 import ( P2ImMessageReceiveV1, P2ImMessageReceiveV1Handler ) class MessageHandler(P2ImMessageReceiveV1Handler): def handle(self, evt: P2ImMessageReceiveV1) - None: event evt.event message event.message chat_id message.chat_id content json.loads(message.content) # content 是 JSON 字符串 text content.get(text, ) # 交给下一层处理 process_message(chat_id, text, event.sender)使用官方事件处理器时只需要注册到长连接客户端即可不用自己处理解密、重试等琐碎逻辑。3.3 接入 OpenClaw 的完整消息链路实际处理流程可以拆成三步抽取消息、调用 OpenClaw、用飞书 API 回发。抽取这一步要特别处理机器人的情况。群聊里用户发“OpenClaw 今天巡检情况怎么样”消息文本中会带上_user_xxx这类占位符不清理掉会严重影响 LLM 的理解质量。我的做法是用正则把_user_[0-9]替换为空字符串只保留语义部分。调用 OpenClaw 时需要把会话 ID 设为 chat_id这是为了让同一个群、同一个单聊的上下文连续。如果不设置每次消息都是独立的机器人会像失忆一样没法接着上一句聊。import json def call_openclaw(text: str, chat_id: str) - str: # 忽略空文本 if not text.strip(): return 请说具体需求 result openclaw.chat( session_idchat_id, message{role: user, content: text} ) return result.answer回发消息直接用飞书 API注意使用的是 tenant_access_tokenfrom lark_oapi.api.im.v1 import ( CreateMessageRequest, CreateMessageRequestBody, CreateMessageResponse ) def send_text_message(chat_id: str, text: str): request CreateMessageRequest.builder() \ .receive_id_type(chat_id) \ .request_body( CreateMessageRequestBody.builder() .receive_id(chat_id) .msg_type(text) .content(json.dumps({text: text}, ensure_asciiFalse)) .build() ) \ .build() client.im.v1.message.create(request)这里有个判断让 OpenClaw 自己调用一个飞书插件来发消息还是在外层直接调 API我的经验是外层发消息更好。因为外层代码可以统一处理格式、失败重试和长度截断避免 LLM 生成长文本时格式漂移。3.4 部署成 24 小时在线服务要让机器人全天在线本质上要解决三件事进程退出后自动拉起、开机自动启动、日志持续收集。我用的是 systemd这是目前最省心的方式。先写好一个 service 文件[Unit] DescriptionOpenClaw Feishu Bot Afternetwork.target [Service] Userclaw WorkingDirectory/opt/openclaw-bot EnvironmentFile/etc/openclaw-bot.env ExecStart/usr/bin/python3 main.py Restartalways RestartSec5 [Install] WantedBymulti-user.target把 service 文件放到/etc/systemd/system/然后执行sudo systemctl daemon-reload sudo systemctl enable openclaw-bot sudo systemctl start openclaw-botRestartalways保证进程因为异常或内存溢出退出后五秒内自动拉起。我还会额外加一个大一点的进程保护并让日志输出到固定文件journalctl -u openclaw-bot -f看到这里可能有人问为什么不用 DockerDocker 当然可以而且更适合迁移。如果团队已有容器平台建议写个Dockerfile把 service 文件换成容器健康检查。但我个人部署单机机器人时还是用 systemd因为少一层容器网络后续排查飞书 503 或超时时更直接。4. 核心链路细节与权限设计从“能跑”到“好用”4.1 消息请求的完整时序理清时序对后面排查问题帮助极大。一次用户在群里 机器人的请求完整路径是这样的用户发送消息 - 飞书服务器投递事件到你的长连接或回调服务 - SDK 触发message.receive_v1- 代码解析文本 - 调用 OpenClaw 生成回复 - 再次调用飞书 API 主动发送消息 - 用户看到回答。这里最核心也最容易忽视的问题OpenClaw 调用 LLM 生成回答的时间可能很长而飞书要求回调处理有明确时限。如果你在回调函数里同步等待 LLM 回复很可能超过服务端的等待阈值飞书会判定处理失败并进行重投。重投又会再次触发 LLM 计算导致重复、慢、甚至消息队列堆积。正确姿势是把 LLM 调用放到异步任务里回调函数先马上返回一个接收成功的信号让飞书确认事件已经送达然后后台线程慢慢生成回答最终通过 API 推送过去。用 Python 的线程池或者队列都能实现结构大概是这样from concurrent.futures import ThreadPoolExecutor pool ThreadPoolExecutor(max_workers8) def handle_event(evt): # 快速入队不再阻塞当前回调 pool.submit(process_message, evt) # process_message 内解析 - OpenClaw - 发送这样既规避了超时又能利用多线程并发服务多个群。唯一代价是消息响应从“请求-响应”变成了“异步回发”需要在使用体验上做一点心理预期管理。4.2 把 OpenClaw 调教成团队助手而不是聊天机器接入之后默认的 OpenClaw 像一个通用聊天机器人这不是我们要的。真正团队的 AI 助手应该知道自己身处什么组织、为谁服务、能调用哪些工具、遇到什么场景禁止越权。我建议在 OpenClaw 的 system prompt 里显式注入几类信息团队内部叫法、常用工具清单、消息回答风格、以及“不知道就说不知道”的兜底原则。举一个我的实际配置片段你是团队值班助手当前环境为“某内部运维群”。 你可以查询工单系统、更新值班记录、翻查知识库。 请用简明、专业、不超过150字的方式回答。 如果你不确定不要编造提示用户联系人工。这个配置看起来简单但直接决定了机器人的可靠性。很多接入后“感觉不聪明”的问题其实不是模型不行而是 prompt 里缺少约束。另外OpenClaw 的工具调用权限也要单独控制。比如我给机器人只开放了“查询类工具”写入类的操作全部放到审核队列避免它在群里误改配置。4.3 多群隔离与权限白名单如果你只在一个群里测试这个环节可以不看但一旦部署到多个业务群就会出现 A 群的人问 B 群的数据或者群里随便一个成员都能命令机器人执行敏感操作。我强烈建议在 OpenClaw 上层加一层白名单中间件。白名单中间件至少要做两件事第一校验 chat_id 是否在允许服务的列表里不在列表内直接拒绝第二校验触发者身份群聊里只有管理员或指定角色可以使用写类工具。飞书事件体里带有sender.sender_id.open_id拿这个 open_id 去和预设的运营者名单匹配就行。我遇到过一个真实事件机器人进了测试大群后有人发了“给所有人发一条广告消息”要不是当时机器人没有发单聊消息的权限后果就是群发轰炸。所以我后来把权限收敛得特别紧宁可加权限后重新发布也不开全量权限。4.4 结合知识库与主动推送的进阶玩法接入飞书的 OpenClaw 不该只会被动回答它完全可以变成一个主动值守系统。我把内部知识库的更新、定时巡检脚本的输出、甚至天气和工作提醒都接进来了每天早上八点OpenClaw 调用定时任务把前一天工单的数据汇总推送到运维群每周五下午五点推送周报提醒。主动推送的实现难点不在于发消息而在于定时触发。OpenClaw 本身通常提供定时任务机制我建议把发布任务放在独立进程里避免和回调主进程耦合。另外虽然飞书支持机器人往群里发消息但过度推送会造成打扰建议限制频率并对每条主动推送赋予明确标题。实践证明“安静但有回应”的机器人比“话痨机器人”更受团队欢迎。5. 常见问题与排查实录5.1 URL 校验永远失败回调服务收不到请求Webhook 模式下配置请求地址时飞书会发送一个url_verification事件。很多人第一次都卡在这里。排查顺序建议是这样先看回调服务的日志确认飞书到底有没有打进来如果日志里完全没有请求就是地址不通或者证书问题如果收到了但校验失败多半是返回体不符合要求。正确返回应该是直接回显challenge字段并且 HTTP 状态码为 200。开启加密后这个challenge还需要先用 Encrypt Key 解密再明文返回。我见过最隐蔽的坑是代码里返回了{challenge: 解密后的值}但字段名拼错飞书要求的是保留原名。保持响应体结构和请求体一致是最容易被忽略的规则。5.2 机器人不回复但日志里明明收到了事件这是另一个高频问题。日志有事件说明链路通到了回调入口但机器人没说话问题多半出在后续代码逻辑。最常见的有四个原因解析消息内容时飞书 content 字段偶尔不是标准 JSON而是带转义的字符串导致 json.loads 失败OpenClaw 调用模型时报错但异常被吞掉了发送消息时缺少im:message相关权限异步线程池满了任务一直排队。我的建议是在处理链路的每一步都打印结构化日志带上chat_id和event_id这样能快速定位卡点。用这个笨办法我基本都能在十分钟内定位到问题。5.3 重复回复同一句话这个现象几乎是异步化之后必然出现的飞书事件没有收到成功的 ACK于是隔几秒重投一次你的后台任务又跑了一遍用户就看到两条相同回复。解决思路有两条一是回调入口收到事件后立刻执行去重二是在处理函数开头检查这个消息是否已经处理过。最简单且稳妥的去重方案是拿message_id做记忆。处理完一条消息后把它的 message_id 写入一个带过期时间的缓存例如 Redis 或 Python 的磁盘缓存重复到达时直接丢弃。我会把 TTL 设成一个小时因为飞书重试通常发生在短时间窗口内时间太长反而会造成新消息被误判为重复。5.4 长连接模式频繁掉线我早期用长连接时遇到过一个问题跑了一两天后连接断开机器人就静默失联。排查后发现是网络层对空闲连接做超时回收SDK 没有及时发送心跳。解决方法是升级到新版 SDK并在代码里拿到长连接状态后持续监听异常回调遇到断线主动重建。另外一个容易踩的坑是长连接模式下不要和定时任务塞在同一进程里用纯线程调度部分环境的协程调度会让心跳任务饿死。更好的做法是定时任务独立进程两者互不干扰。5.5 排查一页速查表症状常见原因快速处理URL 校验失败返回体非 challenge 明文 / 网络不通检查日志、确认端口与证书收不到事件未添加 im.message.receive_v1在开放平台补订阅并重新发布机器人不回复权限缺失或消息解析失败补权限按日志定位异常点重复回复回调未 ACK / 重试投递入口对 message_id 去重发消息报权限错误未发布新的权限版本重新发布应用版本长连接掉线SDK 版本过旧 / 心跳中断升级 SDK监视异常回调6. 我在实际部署中的几点体会如果让我重新做一遍接入我会先把“消息处理”的异步模型画清楚再开始写回调代码。整个接入过程中最耽误我时间的不是 OpenClaw 本身的配置而是飞书回调的同步、重复、超时这三件事。这几个问题没有一起想清楚就会陷入“明明代码看起来没问题可机器就是表现得痴呆”的困境。还有一个体会是关于模型的选择同一套飞书接入层换上不同的对话模型回复质量差异很大。我的建议是先用一个常规模型跑通全链路确认飞书侧稳定后再迭代模型和 prompt。很多朋友一开始就在 prompt 上精雕细琢结果连消息都没能发出去前面的努力全部白费。最后分享一个小技巧给 OpenClaw 接一个前置拦截层把“打招呼”“发谢谢”“无意义消息”直接过滤掉不送进 LLM。这条看起来很简单但能把大模型的调用量直接降下来一半响应速度也会有明显提升。24 小时在线这件事不只是让机器人不睡觉更要让它在每一条消息上都保持高效和专业。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑