ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

硬核实战:从零构建飞书 × OpenClaw 自动化情报站(一):Webhook 接入与 TaoToken 统一 Key 配置

硬核实战:从零构建飞书 × OpenClaw 自动化情报站(一):Webhook 接入与 TaoToken 统一 Key 配置 1. 为什么飞书机器人一定要走 Webhook而不是轮询如果你正在把飞书当成团队的情报入口想让 OpenClaw 这类 Agent 工具自动采集、整理、回推到群里第一个绕不开的问题就是飞书怎么把消息实时交到你手里。很多人第一反应是写个定时任务每隔几秒调一次飞书的消息接口问一句“有新消息吗”。这个方案能跑但延迟高、空转多消息一多就开始堆积体验很差。Webhook 换了个思路你不再主动去问而是提前在飞书开放平台登记一个公网 URL当群里有人发消息、机器人被 、或者卡片被点击时飞书服务器主动向你登记的地址发一个 HTTP POST。请求的发起权在事件源手里你的服务只需要被动接收、解析、分发。这就是所谓的 Push 模型也是工业级 IM 机器人的标准做法。这篇是系列第一篇目标很明确把飞书 Webhook 回调链路和 OpenClaw 情报采集链路第一次打通。具体交付四样东西——一个可复制的 Flask 接收端骨架、OpenClaw 侧 config.toml 的配置片段、TaoToken 统一 Key 在 settings.json 里的填写位置以及本地反向代理验证 Webhook 可达性的命令和预期返回。适合需要把多源 AI 能力接进飞书群的技术团队也适合自己搭自动化情报站的同学。整条链路大致是这样飞书群消息触发事件飞书服务器 POST 到你的公网入口反向代理转发到本机 Flask 的 18789 端口Flask 做握手校验和指令提取再把清洗后的文本交给 OpenClawOpenClaw 调用模型能力生成结果最后回推飞书。这一篇先把前半段跑通。2. TaoToken 前置统一 Key 与 OpenClaw 的接入位置在动手写代码之前先把模型调用的入口定下来。OpenClaw 作为 Agent 工具本身不绑定某一家模型它需要一个兼容 OpenAI 协议风格的 API 端点。TaoToken 提供的就是这样一个统一入口你申请一个 Key就能在 OpenClaw 里调用多种模型不用为每个模型单独维护一套鉴权和地址。官网地址是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 基址是 https://taotoken.net/api 注意这个 API 地址后面不加任何查询参数。你需要先去控制台创建一个 API Key创建入口在 https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 。Key 只在创建时完整显示一次复制下来存到安全的地方。如果你只是想先验证模型能不能通可以直接用模型对话页面试一句 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 。如果打算长期跑编码类或 Agent 类任务建议了解下 Coding Plan https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 遇到参数问题优先查这里。注意API Key 属于敏感凭证不要写进会提交到 Git 的配置文件里。建议用环境变量注入或者放在 .gitignore 覆盖的本地配置中。OpenClaw 侧的配置分两块一块是 config.toml负责声明模型端点和行为另一块是 settings.json负责填写实际的 Key 和运行时参数。下面两节分别给出可复制的片段。3. 可复制配置Flask 接收端、config.toml 与 settings.json3.1 Flask 接收端骨架 bridge.py先建一个最小可运行的接收端。它的职责有三个响应飞书的 url_verification 握手、解析 im.message.receive_v1 事件、把用户文本打印或转发出去。依赖只有 Flask 和 requests。# bridge.py import json import os import requests from flask import Flask, request, jsonify app Flask(__name__) # OpenClaw 本地网关地址后续章节会用到 OPENCLAW_ENDPOINT os.environ.get(OPENCLAW_ENDPOINT, http://127.0.0.1:18790/ingest) app.route(/webhook, methods[POST]) def handle_feishu(): data request.get_json(silentTrue) or {} # 1. 握手校验飞书首次配置时会发 url_verification if data.get(type) url_verification: return jsonify({challenge: data.get(challenge)}) # 2. 事件分发只处理消息接收事件 header data.get(header, {}) if header.get(event_type) im.message.receive_v1: event data.get(event, {}) message event.get(message, {}) # content 是被二次转义的 JSON 字符串需要再解析一次 raw_content message.get(content, {}) try: msg_content json.loads(raw_content) except json.JSONDecodeError: msg_content {} user_text msg_content.get(text, ).strip() print(f 接收指令: {user_text}) # 3. 转发给 OpenClaw可选链路打通后再启用 if user_text: try: requests.post( OPENCLAW_ENDPOINT, json{text: user_text, source: feishu}, timeout5, ) except requests.RequestException as exc: print(f转发 OpenClaw 失败: {exc}) return jsonify({code: 0, msg: ok}) if __name__ __main__: app.run(host0.0.0.0, port18789, debugFalse)启动命令pip install flask requests python bridge.py启动后你会看到 Flask 监听在 0.0.0.0:18789。注意 host 必须是 0.0.0.0否则反向代理从外部转发进来会连不上。3.2 OpenClaw 的 config.toml 片段OpenClaw 的 config.toml 负责声明模型提供方。把 base_url 指向 TaoToken 的 API 地址模型名按你实际要用的填。# config.toml [provider.taotoken] type openai_compatible base_url https://taotoken.net/api api_key_env TAOTOKEN_API_KEY default_model gpt-4o-mini timeout_seconds 60 [agent.default] provider taotoken system_prompt 你是一个情报整理助手负责把飞书群里的原始消息归纳成结构化摘要。 max_tokens 2048 temperature 0.3 [ingest] listen_host 127.0.0.1 listen_port 18790 path /ingest这里 api_key_env 指向环境变量名而不是把 Key 明文写进 toml。启动 OpenClaw 前先导出export TAOTOKEN_API_KEY你的Key3.3 settings.json 里 TaoToken Key 的填写位置有些 OpenClaw 版本或插件用 settings.json 管理运行时配置。Key 字段通常叫 api_key 或 token放在 provider 对应的节点下。结构大致如下{ providers: { taotoken: { base_url: https://taotoken.net/api, api_key: sk-你的Key, default_model: gpt-4o-mini } }, runtime: { log_level: info, ingest_port: 18790 } }提示settings.json 和 config.toml 同时存在时以你所用 OpenClaw 版本的加载顺序为准。不确定就只保留一份避免 Key 来源混乱。4. 验证请求反向代理与 Webhook 可达性测试飞书服务器在公网你的 Flask 在本机 18789中间需要一个公网入口。生产环境用 Nginx 或云负载均衡本地调试可以用反向代理工具把本机端口映射出去。这里给出 Nginx 的配置和本地验证命令。4.1 Nginx 反向代理配置server { listen 443 ssl; server_name your-domain.example.com; ssl_certificate /etc/nginx/certs/fullchain.pem; ssl_certificate_key /etc/nginx/certs/privkey.pem; location /webhook { proxy_pass http://127.0.0.1:18789/webhook; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_read_timeout 30s; } }改完执行nginx -t检查语法再nginx -s reload生效。云服务器还要在安全组放行 443 入站否则握手请求在网络层就被丢弃表现为 Connection Timeout。4.2 本地模拟飞书握手请求在配置飞书后台之前先用 curl 模拟一次 url_verification确认你的接收端能正确回传 challengecurl -X POST https://your-domain.example.com/webhook \ -H Content-Type: application/json \ -d {type:url_verification,challenge:test-challenge-123}预期返回{challenge:test-challenge-123}如果返回的是这个说明公网入口、反向代理、Flask 三层都通了。如果返回 502多半是 Flask 没起来或端口不对返回 404检查 Nginx 的 location 路径和 proxy_pass 是否一致。4.3 模拟消息事件握手通过后再模拟一条消息事件确认解析逻辑正常curl -X POST https://your-domain.example.com/webhook \ -H Content-Type: application/json \ -d { header: {event_type: im.message.receive_v1}, event: { message: { content: {\text\:\帮我整理今天的行业新闻\} } } }预期在 Flask 控制台看到 接收指令: 帮我整理今天的行业新闻同时接口返回{code:0,msg:ok}。到这一步飞书到本地的链路就算打通了。4.4 验证 OpenClaw 侧模型调用链路打通后单独验证 OpenClaw 能不能通过 TaoToken 调通模型。用 curl 直接打 API 基址curl https://taotoken.net/api/chat/completions \ -H Authorization: Bearer $TAOTOKEN_API_KEY \ -H Content-Type: application/json \ -d { model: gpt-4o-mini, messages: [{role: user, content: 用一句话说明 Webhook 和轮询的区别}] }返回里能看到 choices 数组和模型输出就说明 Key 和端点都正确。如果返回 401检查 Key 是否复制完整返回 404检查 base_url 是否误加了路径后缀。5. 本篇常见错排查5.1 握手返回 challenge 为空最常见的原因是 request.get_json() 拿不到数据。飞书发的是 application/json但如果你在 Nginx 里改了 Content-Type或者 Flask 前面还有一层没透传 body就会解析失败。用request.get_data(as_textTrue)打印原始 body 确认一下。另外注意 challenge 字段在顶层不在 header 里。5.2 端口占用导致 Flask 起不来报错Address already in use说明 18789 被占了。查一下lsof -i :18789如果是上次没退干净的进程kill 掉再启动。OpenClaw 的 18790 同理两个端口别配重了。5.3 反向代理 502 Bad Gateway三个检查点Flask 是否监听 0.0.0.0 而不是 127.0.0.1Nginx 的 proxy_pass 地址端口是否和 Flask 一致SELinux 或防火墙是否拦截了本机回环转发。云服务器上curl http://127.0.0.1:18789/webhook能通但外网不通基本就是安全组没放行。5.4 content 字段解析报错飞书消息的 content 是被转义过的 JSON 字符串形如{\text\:\hello\}。直接当字典用会报错必须先 json.loads 一次。如果消息类型是图片或文件content 结构不同text 字段可能不存在记得用 get 兜底。5.5 TaoToken 调用返回 401 或 403先确认环境变量是否真的导出成功echo $TAOTOKEN_API_KEY。如果是在 systemd 或 Docker 里跑 OpenClaw环境变量不会自动继承需要在 service 文件或 compose 里显式声明。另外检查 Key 有没有多余空格复制时容易带上换行。5.6 事件重复推送飞书在没收到你的成功响应前会重试。如果你的处理逻辑耗时较长先返回 200 再异步处理避免飞书判定超时重复推送。生产环境建议加一个基于 event_id 的去重表。6. 下一步把链路接进真实情报流到这里飞书 Webhook 到本地 Flask 的链路已经能跑OpenClaw 的模型端点也验证通过。接下来要做的是把 bridge.py 里那段转发逻辑真正接到 OpenClaw 的 ingest 接口上让群消息触发 Agent 采集和整理再把结果以卡片形式回推飞书群。如果你在接入过程中卡在 Key 配置或端点地址上直接去 API Keys 页面重新生成一个再试 https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 。参数细节以接入文档为准 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。想先确认模型输出风格用模型对话页试一句最快 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 。长期跑 Agent 任务的话Coding Plan 的额度模型更划算 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 。下一篇会处理端口主权冲突和 OpenClaw 网关的并发启动问题那是链路打通后第一个真正会咬人的坑。
返回列表