
飞书机器人做到第五个Carl 把半年的返工打包成了开源 SkillWebhook 签名里时间戳与拼接顺序老写反Flask 路由和 lark-oapi 适配器常搅在一起。本篇只走 Claude Code 这一路Key 在 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 创建Base URL 填 https://taotoken.net/api。Skill 本身不神秘它是把一个飞书机器人该怎么搭的隐性经验写成模型能读的说明书让 Claude Code 在动手前先读规则而不是顺手去编。真正拖慢进度的往往不是飞书 API 有多难而是 AI 每接一个新机器人都要把开放平台文档重翻一遍事件订阅怎么验签、消息怎么发、卡片怎么回、定时任务放哪一层每次从零推导就每次从零犯错。走通之后原本AI 自己查文档、写一版跑不通、你贴报错、它再猜的循环会换成读 Skill、反问需求、一次生成骨架。TaoToken 在这条链路里只做一件事给 Claude Code 供一条稳定的模型通道不参与飞书签名、事件验签、卡片 JSON 的任何一步。1. 飞书机器人 Skill 挡掉的是哪几轮返工1.1 Webhook 签名时间戳和签名字符串的拼接顺序飞书事件订阅的回调需要验签签名串由时间戳、随机串和密钥按固定顺序拼出来还要把请求体的原始字节算进去。这几样东西一旦顺序变了或者中途把字节转成字符串再编码一次算出来的摘要就对不上飞书那头只会回一个含糊的失败你这边看不到任何有意义的堆栈。模型在没有约束的时候最容易在这里自由发挥一会儿先拼时间戳一会儿先拼 body一会儿用request.data一会儿用request.get_data()之后又.decode()。每个版本看起来都差不多对但验签就是过不去。Skill 把这些顺序和取值方式写死在文档里模型拿到的是一个确定答案而不是一个需要现场推理的开放题。1.2 Flask 路由和 lark-oapi 适配器被混在一起lark-oapi 自带事件分发器Flask 又有自己的一套路由和请求上下文。混着写的典型症状是把 SDK 的 handler 直接塞进 Flask 视图函数或者干脆绕开 SDK 自己手写一套验签加解析。前者会因为请求体被 Flask 提前读过而拿不到原始字节后者会在卡片回调、消息已读这类事件上不断补丁越补越乱。Skill 里把这个边界定清楚谁负责接 HTTP 请求、谁负责验签、谁负责把事件对象交给业务函数、谁负责拼卡片。边界一旦固定模型生成的目录结构就稳定了你也不会在第三个机器人上发现前两个的写法完全不兼容。1.3 三条安装路线本篇只碰 Claude Code 那一路Carl 给的三条路是同一个 Skill 的不同壳Copilot 放进~/.copilot/skills/Claude Code 放进~/.claude/skills/Cursor 用.cursor/rules/的规则文件替代。三者内容同源只是被读取的时机和格式不同。本篇只处理 Claude Code因为它的配置文件恰好也是接第三方模型通道时最常被改的那一份。把 Skill 放对目录、把 Base URL 换到 https://taotoken.net/api两件事凑在一起才是一次完整的接入。2. 把 Skill 落到 ~/.claude/skills/ 这一步别放错目录2.1 目录层级与 SKILL.md 的写法Claude Code 按目录扫描技能一个技能一个文件夹入口文件固定叫SKILL.md。放错一层比如直接把SKILL.md丢在~/.claude/skills/根下或者多套了一层没必要的目录都可能出现文件明明在模型却说没看到。文件头部需要一小段 YAML用来描述这个技能叫什么、什么时候该用它。名字和触发描述写得越具体模型越容易在合适的时机把它读进来。--- name: feishu-bot-builder description: 搭建飞书机器人时使用。覆盖事件订阅回调验签、消息发送、卡片回复、定时推送的项目骨架以及 App ID、App Secret、Chat ID 的读取方式。用户提到飞书机器人、事件回调、群消息推送时加载。 --- ## 工作流 1. 先反问需求不要直接生成代码。 2. 确认发送内容、目标群、触发方式、是否需要 对话。 3. 按固定目录生成 src/、config/、.env.example、QUICKSTART.md、README.md。 4. 说明哪些配置必须由使用者自己填不要伪造 App Secret。 ## 边界 - 回调验签的拼接顺序以本文件为准不要自行调整。 - 事件分发交给 SDK 的适配器不要在 Flask 视图里重写验签。 - 不在代码里写死任何密钥。上面是结构示例真正的内容以你实际拿到的 Skill 为准。重点是让模型读到先反问、再生成这个顺序而不是一上来就吐一堆代码。2.2 确认 Claude Code 真的读到了它放好之后别急着建机器人先单独开一个新会话做一次最小验证直接问它现在能看到哪些技能或者让它把技能里的工作流复述一遍。如果它答得含糊或者复述的内容和文件对不上先处理目录问题不要带着疑问往下走。常见的三个原因是目录层级错了、front matter 里的name和目录名冲突、描述写得太泛导致模型判断这次用不上。新会话很重要因为技能列表通常在会话启动时加载旧会话里改文件不一定即时生效。3. settings.json 里把 Claude Code 的 Base URL 指到 TaoToken3.1 先拿 Key打开落地页进控制台创建打开 TaoToken 注册进控制台创建 API Key。创建完成后先把这串 Key 复制到安全的地方再顺手看一眼模型广场里当前可用的模型 ID记下你要用的那一个。模型列表会变所以别凭记忆写一个 ID 进去以页面当时显示为准。这一步和飞书完全无关你只是给 Claude Code 准备一条模型通道。飞书的 App ID、App Secret、Chat ID 是后面生成项目时再填的两套凭证不要混在同一个文件里。3.2 ~/.claude/settings.json 的 env 三件套Claude Code 读用户级配置文件把模型通道写在env字段里最省事换终端、换项目都生效。{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_AUTH_TOKEN: YOUR_API_KEY, ANTHROPIC_MODEL: YOUR_MODEL_ID } }三个值的来源分别是Base URL 固定填https://taotoken.net/apiANTHROPIC_AUTH_TOKEN填你刚创建的YOUR_API_KEYANTHROPIC_MODEL填模型广场里你选中的那个 ID。Key 如果已经写进项目里的环境变量文件记得别把.env提交进版本库。3.3 环境变量写法以及 /v1 那个尾巴不想动配置文件也可以在 shell 里直接导出适合临时试一把export ANTHROPIC_BASE_URLhttps://taotoken.net/api export ANTHROPIC_AUTH_TOKENYOUR_API_KEY export ANTHROPIC_MODELYOUR_MODEL_ID这里最容易错的一点是给 Base URL 补一个/v1。看着像是更完整实际上会让请求打到不存在的路径上表现为莫名其妙的 404。填https://taotoken.net/api就停住不要在后面加任何路径、斜杠或查询参数也不要把它和官网地址混用——官网地址是给人点的接口地址才是填进工具里的。4. 拿回对话从 Skill 反问需求到生成 src/ 与 QUICKSTART.md4.1 第一轮让它先读 Skill 再反问通道通了、技能也在了这时候不要输入帮我写一个飞书机器人。更好的开场是让它先说明准备怎么干它会从技能里读到哪些约束、打算按什么目录生成、哪些信息需要你提供。这一轮的目的不是产出代码而是确认它确实在读技能而不是又在凭印象编。如果它跳过这一轮直接开始写代码说明技能没被加载或描述没匹配上回到 2.2 检查别硬着头皮往下走。带着没加载的技能往前跑后面所有报错都会变得难以定位。4.2 第二轮发什么、发到哪个群、几点定时、群里能不能 对话第一轮之后进入细粒度澄清。需要说清楚的四件事机器人要发什么内容是固定文案还是从某个数据源拼发到哪个群是群 ID 还是机器人所在的所有群是收到消息就回还是每天固定时间推群里要不要支持 机器人对话这决定了你要不要处理消息事件而不只是发消息。这四件事每一项都会改变代码结构。定时推送需要任务调度和去重 对话需要事件订阅加会话状态只发固定文案则简单得多。把它们一次说清避免生成到一半再回头改目录返工成本比说清楚高得多。4.3 生成物清单src/、config/、.env.example、QUICKSTART.md、README.md需求确认后让它按技能里的约定生成这几样东西src/放业务代码config/放配置结构和读取逻辑.env.example列出所有需要你填的变量名QUICKSTART.md写最短启动路径README.md写目录说明和扩展点。.env.example只放占位符真实值由你自己填进.env。拿到生成结果先扫一遍这几件事有没有硬编码密钥、App ID 之类的变量是不是都从环境读取、回调路径和事件类型是否和飞书后台配置一致。这里花五分钟比跑起来之后对着日志猜半小时划算。4.4 填 App ID、App Secret、Chat ID 再起服务把.env.example复制成.env填入飞书开放平台给你的 App ID、App Secret以及目标群的 Chat ID。这三样都在飞书后台不在模型通道里两者别互相顶替。填完启动服务确认监听端口和飞书事件订阅里填的回调地址能对上。启动日志里重点看两行服务是否正常监听、事件订阅是否被成功调用。前者是本地问题后者才和飞书配置有关。5. 验证与排障先确认通道再看飞书那侧5.1 用同一把 Key 发一条消息确认模型通道先别急着调机器人把模型通道单独验一次拿同一把YOUR_API_KEY在模型对话页里发一条最简单的消息确认能正常返回。这一步排除掉 Key 拼错、模型 ID 写错、Base URL 多带了/v1这类问题。如果对话正常、Claude Code 报 401多半是配置文件里的 Key 和对话页用的不是同一把或者环境变量被 shell 里更早的设置覆盖了。如果两个地方都报同样的错回 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 重新核对 Key 和模型列表别在本地反复改格式。5.2 报错对照表现象大概率原因处理方向401 未授权Key 写错、被覆盖、或复制时带了空格重新复制YOUR_API_KEY检查环境变量优先级404 路径不存在Base URL 后面多了/v1或斜杠改回https://taotoken.net/api模型不存在模型 ID 过时或拼错打开模型广场按当前列表重新选技能没被读取目录层级错、front matter 有问题检查~/.claude/skills/下的结构重开新会话回调验签失败签名拼接顺序或请求体取值方式不对以 Skill 里的约定为准不要自行调整服务起了但收不到事件飞书后台回调地址或事件类型没配这一条和模型通道无关去飞书后台查表的用法是先看现象落在哪一行再动手。看到 404 就去改飞书的回调地址或者看到验签失败就去换 API Key都是常见的误判方向。5.3 飞书那侧的错别往 Base URL 上甩事件回调验签失败、卡片回调收不到、群里 机器人没反应这些全都发生在飞书和你的服务之间和模型通道没有关系。反过来Claude Code 连不上、返回 401、生成到一半中断这些才是通道问题。把两类问题分开看排障时间会少一大半。判断方法很简单把飞书后台的事件订阅临时停掉只让 Claude Code 处理一次纯文本任务。如果这次正常说明通道没问题剩下的全在飞书侧。6. 跑通之后回头对一下这次调用6.1 在模型对话里复核这次调用整条链路跑通后回到 TaoToken 模型对话 用同一把 Key 再发一条测试消息确认模型 ID 和 Base URL 都没填错。想长期用它写代码可以打开 Coding Plan 看套餐是否够用后续要换 Key 或再建一把在 控制台 API Keys 创建即可。Claude Code 的环境变量对照见 接入文档。6.2 把这个骨架复制给第二、第三个机器人第一台机器人跑通之后Skill 的价值才真正显现新建一个空目录重复 2 到 4 章那套流程只是这次换成发到另一个群、换成每天早上推。目录结构、验签顺序、配置读取方式全都沿用你要改的只有业务参数。真正需要留意的只有两处每台机器人在飞书后台是独立的应用App ID 和 App Secret 不要复用同一个进程里跑多个机器人时事件回调路径要区分开否则会出现消息发错群这类很难查的问题。把这两条写进项目的 README下一个接手的人会省下不少时间。