ARTICLE · 1106056
第8篇 :自定义插件:对接任意API
自定义插件:对接任意API
—— Coze智能体开发系列 · 第8篇
💡 写在前面 先说一个真实场景。 上个月有个读者给我留言:"老师,扣子插件市场里的天气插件不好用,我想用公司买的某天气API, 能不能接进去?" 我说:能。自定义插件就是干这个的。 他又问:"可是我完全不懂API是什么,听着就像程序员的黑话……" 这一篇就是为他写的。 如果你以为自定义插件需要你会写后端、会搭服务器、会写接口文档——那你想复杂了。 扣子把这件事做得非常傻瓜化:你只要知道一个API的地址、它要什么参数、它返回什么, 填进表单里就能用。不需要你写一行服务端代码。 上一篇学了代码节点,你能在工作流内部"算"数据了;这一篇学完自定义插件, 你就能把扣子外面整个互联网的数据都"拉"进来。内外打通,你能做的事情直接翻十倍。 本篇你会学到:API是什么/HTTP基础(GET/POST/Header/Body/鉴权);扣子自定义插件创建全流程; 三种鉴权方式怎么配;三个实战(公开API/带Key的API/带Token的内部API); 8个常见坑和排错方法;小Co升级接入真实面经数据库。 跟着做一遍,你会发现"对接API"这件事真的没那么玄乎。 |
一、为什么需要自定义插件?
先回答一个灵魂问题:扣子插件市场里已经有几百个插件了,搜索、天气、新闻、图片、计算……几乎你能想到的都有,为什么还要自己做?
1.1 现成插件不够用的三个场景
我自己做项目时,遇到现成插件搞不定的情况,基本是这三类:
场景一:公司/团队内部系统。比如你公司有个CRM系统,里面存着所有客户信息;或者有个内部的订单查询接口、库存查询接口。这些系统根本不会出现在公开插件市场里,但又是你最想让Bot能访问的。
场景二:小众/垂直领域的公开API。比如你想查某个行业的专业数据、某个小众平台的数据、某个地区特定的服务——插件市场可能没收录,但网上确实有公开API可以用。
场景三:对现有插件的"定制化封装"。比如官方的搜索插件返回20条结果,但你每次只想取Top3并且过滤掉某些站点;或者你想把几个插件串起来做成一个"一站式查询"工具——这时候自己封一个插件更顺手。
说白了:现成插件是"超市买菜",方便但选择有限;自定义插件是"自己种菜",想吃什么种什么——前提是你得有种子(API地址)。
1.2 自定义插件能做什么
理论上,任何一个提供HTTP接口的服务,你都能封装成扣子插件。举几个我自己做过的:
• 公司内部OA:查请假余额、提交报销单(内网API+Token鉴权);
• 行业数据库:查某行业的企业工商信息、招投标数据(付费API+API Key鉴权);
• 第三方SaaS:飞书多维表格读写、Notion页面查询、GitHub仓库操作(OAuth鉴权);
• 个人小工具:随机猫图、每日英语、名言警句(公开免费API,无鉴权);
• 硬件IoT:查自家智能摄像头状态、控制智能灯(局域网API)。
1.3 自定义插件不能做什么
提前说清楚边界:
能做 ✅ | 不能做 ❌ |
调用任何提供HTTP接口的外部服务 | 不能在插件里写复杂业务逻辑(那是工作流/代码节点的事) |
支持GET/POST/PUT/DELETE等标准HTTP方法 | 不能直接访问数据库(需要通过后端API间接访问) |
传递Query/Header/Body/Path参数 | 不能绕过CORS或浏览器同源策略限制(服务端调用不受此限) |
处理JSON/FormData等格式的请求和响应 | 不能调用需要客户端证书/复杂签名的非标准API(部分可通过自定义代码实现) |
配置API Key/Bearer Token/OAuth等鉴权 | 不能长连接/不能WebSocket/不能流式(需要插件支持流式的特殊配置) |
⚠️ 自定义插件本质是"扣子帮你发HTTP请求"。如果你的目标服务本身不提供HTTP API,那插件也无能为力。这种情况得先让后端同学把功能封装成API。 |
二、API速成:10分钟搞懂HTTP
要做自定义插件,你必须先懂点HTTP基础。别怕,我用"餐厅点菜"给你类比,看完就明白了。
2.1 什么是API?用餐厅点菜类比
API全称Application Programming Interface,翻译成人话就是"两个软件之间沟通的规矩"。
你去餐厅吃饭:
• 你(客户端/Bot)不直接进厨房炒菜,而是叫服务员;
• 你照着菜单点菜(按API文档发请求);
• 服务员把你的订单送到厨房(HTTP请求发出去);
• 厨房做好菜,服务员端给你(服务器返回响应);
• 你不能点菜单上没有的菜(请求参数不对会报错);
• VIP客户要出示会员卡才能点隐藏菜(鉴权)。
API就是那个"服务员+菜单"——你按规矩点菜,厨房按规矩上菜,你不需要知道厨房怎么炒菜。
在扣子自定义插件里:
• 你(插件配置者)就是那个"点菜的人";
• 扣子就是"服务员",帮你把请求送到目标服务器;
• 目标API服务器就是"厨房",处理请求后返回数据;
• 返回的数据(通常是JSON)就是"菜",你可以在工作流里继续加工。
2.2 HTTP请求四要素
每一个HTTP请求就像一张点菜小票,上面有四个关键信息:
① 请求方法(Method):你要做什么动作?是"看一眼菜单"(GET,拿数据)、还是"点个新菜"(POST,提交数据)、还是"换个菜"(PUT,更新数据)、还是"退菜"(DELETE,删除数据)。做插件90%的情况用GET和POST。
② 地址(URL):厨房在哪?比如 https://api.example.com/weather 就是一个典型的API地址。URL里还能藏参数。
③ 请求头(Header):"附加信息",比如你是VIP要带会员卡(鉴权Token放这)、你要什么口味(Content-Type说明你发的数据格式)、你能接受什么语言(Accept-Language)。
④ 请求体(Body):"具体点什么菜",也就是你要提交给服务器的数据。GET请求通常没有Body(参数放在URL里),POST请求的参数通常放在Body里,格式一般是JSON。
2.3 GET vs POST:到底用哪个?
这是新手最纠结的问题。其实就一个简单判断:
对比项 | GET | POST |
用途 | 获取数据(查) | 提交数据(增/改) |
参数位置 | URL后面 ?key=value&... | 请求体Body里(通常JSON) |
参数长度 | 有限制(URL不能太长) | 几乎无限制 |
安全性 | 参数暴露在URL里 | Body里,相对隐蔽(但仍需HTTPS) |
可否重复 | 重复调用结果一样(幂等) | 重复调用可能重复提交(如重复下单) |
举例 | 查天气、查新闻、搜商品 | 发消息、提交表单、创建订单 |
简单记:要拿数据用GET,要提交/修改数据用POST。API文档会明确告诉你用哪个方法。
2.4 URL里藏参数:Query和Path
GET请求的参数有两种放法,你得能看懂:
第一种叫Query参数——URL后面跟问号,参数用&连接:
https://api.example.com/weather?city=beijing&key=abc123 ^^^^^^^^^^^^^^^ ^^^^^ ^^^^^^ 路径?开始参数1参数2 |
这里city=beijing和key=abc123就是两个Query参数。在扣子插件配置时,你会看到"Query参数"那一栏,把参数名和值填进去就行。
第二种叫Path参数——参数直接嵌在URL路径里:
https://api.example.com/user/12345/orders ^^^^^ 用户ID直接嵌在路径里 |
这里12345是用户ID,属于URL的一部分。配置时需要在URL里用{变量名}占位,扣子会让你填写这个变量对应的输入。
2.5 请求头Header:最常见的三个
Header是请求的"附加信息",你最常碰到的就这几个:
Header名 | 作用 | 典型值 |
Content-Type | 告诉服务器你发的Body是什么格式 | application/json(JSON格式,最常用) |
Authorization | 鉴权凭证(证明你是谁) | Bearer sk-xxx 或 Apikey xxx |
User-Agent | 告诉服务器你是什么客户端 | Coze-Plugin/1.0(一般不用改) |
Content-Type和Authorization是你配插件时一定会遇到的。前者基本都是application/json,后者下一节专门讲鉴权。
2.6 请求体Body:JSON是主角
POST请求提交数据,90%以上用JSON格式。JSON长啥样?就是键值对,用大括号包起来,键用双引号:
{ "city":"北京", "days":3, "extensions":"all" } |
这就是一个典型的JSON请求体。在扣子插件配置里,你会定义Body的结构,告诉扣子"这个请求需要传哪些字段、每个字段是什么类型",扣子会自动帮你组装成JSON发出去。
2.7 响应:状态码和返回数据
服务器收到请求后,会返回一个"响应"。响应分两部分:
状态码(Status Code):一个三位数,告诉你这次请求成没成功。
常见状态码必须认识:
状态码 | 含义 | 你该怎么办 |
200 | 成功 | 正常处理返回数据 |
201 | 创建成功(POST常见) | 正常处理 |
400 | 请求参数错误 | 检查参数名/类型/必填项 |
401 | 未授权(没带鉴权或鉴权错了) | 检查API Key/Token配置 |
403 | 禁止访问(有鉴权但没权限) | 检查账号权限/IP白名单 |
404 | 地址不存在 | 检查URL拼写 |
429 | 请求太频繁被限流 | 减少调用频率/等一会再试 |
500 | 服务器内部错误 | 不是你的问题,联系API提供方 |
502/503/504 | 网关/服务不可用/超时 | 重试/检查网络/联系提供方 |
返回数据(Body):通常是JSON格式,就是你真正要用的东西。你需要在插件配置里"告诉扣子"返回的结构长啥样,扣子才能把返回数据解析成后续节点能用的变量。
一个典型的成功响应长这样:
{ "code":0, "msg":"success", "data":{ "city":"北京", "temperature":22, "weather":"晴", "wind":"东北风3级" } } |
你需要在插件配置时,把data里面的字段(city/temperature/weather/wind)定义成输出参数,这样后续工作流节点才能用这些字段。
三、鉴权:API的"门禁卡"
很多API不是谁都能调的——你得证明你是谁、有没有权限。这就是鉴权(Authentication)。扣子自定义插件支持四种鉴权方式,我从最简单的讲起。
3.1 无鉴权(None)
最简单的公开API,什么都不用带,直接发请求就行。比如后面实战1要做的"每日一言"。
这种情况你在插件配置里选"无鉴权"即可,不需要任何额外配置。
3.2 API Key
最常见的鉴权方式。API提供方会给你一长串字符(Key),你每次请求都要带上它,服务器看到这串字符就知道"哦,这是付费用户xxx"。
API Key有两种常见传递位置:
方式一:放在Query参数里。就是URL后面加个?key=xxxx。比如和风天气的API就是这种。配置时在Query参数里加一个key字段,值填你申请到的Key。
https://devapi.qweather.com/v7/weather/now?location=101010100&key=你的Key |
方式二:放在Header里。在请求头里加一个特定名字的Header,值是你的Key。不同API要求的Header名不一样,常见的有X-API-Key、api-key、apikey等——以API文档为准。
Header: X-API-Key:你的Key |
在扣子插件配置里选"API Key"鉴权,然后按文档选择"放在Query"还是"放在Header"、参数名叫什么,把你的Key填进去。之后插件每次调用都会自动带上,不用你手动管。
💡 怎么申请API Key? 大多数API服务都需要你去官网注册账号,然后在"开发者中心/控制台"里创建一个应用, 系统会生成一串Key给你。免费档通常有每日调用次数限制(比如1000次/天),个人使用完全够用。 付费档根据调用量计费。第一次做建议先用免费API练手。 |
3.3 Bearer Token
Bearer Token和API Key很像,也是一长串字符串,但它有固定的传递方式:必须放在Header的Authorization字段里,格式是"Bearer 你的Token"(注意Bearer后面有个空格)。
Header: Authorization:Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... |
Bearer Token常见于:
• 公司内部系统(登录后返回Token,后续请求都带这个Token);
• OpenAI等大模型API(sk-xxx其实也常以Bearer方式传);
• 很多SaaS平台的开放API。
在扣子里选"Bearer Token"鉴权,把Token填进去,扣子每次请求会自动加上Authorization: Bearer xxx的Header。
3.4 OAuth 2.0
OAuth是最复杂也最安全的鉴权方式,用于"用户授权第三方应用访问自己的数据"。比如你做一个插件要访问用户的飞书文档、GitHub仓库、Google日历——你不能让用户把密码给你,而是让用户在对方平台上点"授权",然后拿到一个有时效的Token。
扣子支持OAuth 2.0的Authorization Code模式,配置时需要填:
• Client ID和Client Secret(在目标平台申请应用时获得);
• Authorization URL(授权页面地址);
• Token URL(换取Token的地址);
• Scope(需要申请哪些权限)。
普通个人开发者做内部工具很少需要配OAuth(除非你要接入飞书/企业微信/钉钉这类平台的用户级数据)。所以这个你先知道有这么个东西就行,真要配的时候照着API文档一步步填,扣子会引导你完成授权流程。
3.5 四种鉴权怎么选?一张图说清楚
鉴权方式 | 适用场景 | 难度 | 安全性 |
无鉴权 | 公开免费API(如名言、随机图片) | 极低 | 低(谁都能调) |
API Key | 大多数商业API(天气、新闻、数据服务) | 低 | 中(Key泄露别人可盗用) |
Bearer Token | 内部系统/SaaS平台/登录态API | 中 | 中高 |
OAuth 2.0 | 需要用户授权的第三方平台(飞书/GitHub等) | 高 | 高 |
⚠️ API Key和Token就像你的家门钥匙——千万别把它写在代码里提交到GitHub,也别在截图里暴露。扣子插件的鉴权信息是加密存储的,不会出现在配置导出里,可以放心用。如果Key不小心泄露了,立刻去API提供方的控制台作废并重新生成。 |
四、扣子自定义插件创建全流程
终于到动手环节了。我按"从零到能用"的顺序,一步步带你走一遍创建流程。先用最简单的公开API(无鉴权)练手,后面实战再讲带鉴权的。
4.1 入口在哪
登录扣子,左侧导航栏找到"插件",点进去。你会看到两个Tab:
• "已安装"——你之前用过的官方/第三方插件;
• "我的"——你自己创建的自定义插件(一开始是空的)。
点"创建插件"按钮,进入创建页面。
4.2 填写插件基础信息
第一步是填插件的基本信息:
• 插件名称:起个好记的名字,比如"每日一言";
• 插件描述:一句话说明这个插件干嘛的,比如"每天返回一条励志名言,中英文对照";
• 插件头像:上传一个图标,不上传会用默认图标;
• 插件介绍:详细说明(选填,但如果要发布到插件市场必须写)。
填完点"确定",进入插件编辑页面。
4.3 创建工具(Tool)
一个插件可以包含多个"工具"——你可以理解为"一个插件=一组相关功能"。比如一个"天气插件"可能有三个工具:实时天气、未来7天预报、空气质量查询。
点"创建工具",会让你填这个工具的信息。核心是这几块:
① 工具名称和描述:名称要简短(英文,如get_daily_quote),描述要写清楚"这个工具干什么、什么时候该用它"——Bot会根据描述决定要不要调用这个工具,描述写得好Bot调用准确率更高。
② 请求配置:选择请求方法(GET/POST),填写URL。如果URL里有Path参数,用{变量名}占位。
③ 输入参数:告诉扣子这个工具需要哪些输入。每个参数要填:参数名、类型(String/Number/Boolean/Object/Array)、是否必填、描述、默认值(可选)。
④ 输出参数(返回结构):告诉扣子返回的JSON长啥样。你可以手动一个个字段加,也可以点"从示例导入"——粘一段真实返回的JSON,扣子会自动解析出字段结构,非常方便。强烈推荐用后者。
4.4 配置鉴权
如果你的API需要鉴权,在插件设置里找到"鉴权"配置项,选对应的鉴权方式(API Key/Bearer Token/OAuth),填上凭证。这个配置是整个插件级别的,插件下所有工具共享同一份鉴权。
4.5 测试调试
填完所有配置后,一定要在右侧的"调试"面板测一下!
调试面板会自动根据你定义的输入参数生成表单,你填一组测试值,点"运行",扣子会真的发一次HTTP请求,然后展示:
• 请求详情:实际发出的URL、Header、Body;
• 响应详情:状态码、返回Header、返回Body(原始JSON);
• 解析结果:按你定义的输出参数解析后的结构化数据。
测试成功后再点"保存"。如果失败,看返回的状态码和错误信息——后面第八节专门讲排错。
4.6 在Bot和工作流里使用
插件创建好、测试通过后,就可以像用官方插件一样用了:
• 在Bot编排页:点"插件"→"我的",勾选你的自定义插件,Bot在对话中就可以自动调用它;
• 在工作流里:拖一个"插件节点"到画布,选择你自己的插件和对应的工具,连好输入输出即可。
💡 关于"是否发布" 刚创建的自定义插件默认只有你自己能用(个人插件)。如果你想分享给团队其他人用, 可以点"发布到团队空间";如果你想发布到公开插件市场让所有人用,需要填更详细的介绍、 经过审核。自己用的话不需要发布,保存了就能在自己的Bot/工作流里调用。 |
五、实战1:做一个"每日一言"插件(无鉴权)
第一个实战,选最简单的公开免费API——"每日一言"(也叫"每日一句")。这类API网上很多,我选一个稳定好用的:https://v1.hitokoto.cn (一言API,免费、无鉴权、文档清晰)。
5.1 先看API文档
打开它的文档页面(可以直接搜"一言API文档"),我们关心这几个信息:
• 请求地址:https://v1.hitokoto.cn/
• 请求方法:GET
• 是否需要鉴权:不需要
• 输入参数(都是可选):c(类型,a动画/b漫画/c游戏/d文学/e原创/…)、encode(返回格式,默认json)、charset(字符编码,默认utf-8)、min_length/max_length(句子长度范围)等;
• 返回示例:
{ "id":7207, "uuid":"e66c4c4e-...", "hitokoto":"如果你认识从前的我,那么你就会原谅现在的我。", "type":"k", "from":"倾城之恋", "from_who":"张爱玲", "creator":"CheriOl", "creator_uid":0, "reviewer":0, "commit_from":"web", "created_at":"1468605906", "length":24 } |
我们主要关心这几个返回字段:hitokoto(名言正文)、from(出处)、from_who(作者)、type(分类)。
5.2 创建插件
按上面的流程创建:
• 插件名称:每日一言;
• 工具名称:get_quote;
• 工具描述:获取一条随机名言警句,可指定分类(动画/漫画/游戏/文学/原创/网络/影视/诗词/网易云/哲学/抖机灵)。用于给用户每日一句、随机励志语录、文章金句素材等场景;
• 请求方法:GET;
• URL:https://v1.hitokoto.cn/
输入参数配置(都是可选,用户不填就随机返回):
参数名 | 类型 | 是否必填 | 描述 | 位置 |
c | String | 否 | 名言分类:a动画/b漫画/c游戏/d文学/e原创/f网络/g影视/h诗词/i网易云/j哲学/k抖机灵 | Query |
min_length | Number | 否 | 句子最小长度 | Query |
max_length | Number | 否 | 句子最大长度 | Query |
输出参数——最方便的方式是点"从示例导入",把上面那段返回JSON粘进去,扣子会自动识别所有字段。你可以删掉不需要的(id/uuid/creator/creator_uid/reviewer/commit_from/created_at这些用不上的可以删掉,只保留核心字段)。
5.3 测试
在调试面板,什么参数都不填,点运行——应该能看到返回一条随机名言。再试试c=d(文学分类),看返回的是不是文学类句子。
测试通过后保存。
5.4 用在Bot里
新建一个Bot,在插件里勾选"每日一言",提示词里加一句:"当用户说"来一句"或"每日一句"时,调用get_quote工具获取一条名言,按「名言」——出处《xxx》·作者 的格式展示给用户。"
发布到豆包测试一下,是不是能正常返回名言?第一个自定义插件,搞定!
整个过程你没写一行代码、没配服务器、没花一分钱——就填了个表单。这就是扣子自定义插件的魅力。
六、实战2:做一个"天气查询"插件(API Key鉴权)
第二个实战来个带API Key的——天气查询。公开免费的天气API我推荐两个:和风天气(devapi.qweather.com)和心知天气(seniverse.com)。我以和风天气为例,因为它免费档比较慷慨、文档中文、注册简单。
6.1 申请API Key
第一步先去和风天气控制台(console.qweather.com)注册账号,创建一个"项目",选择"免费开发版",会生成一个Key(一长串字母数字)。保存好这个Key,等会要用。
免费版每天1000次调用,个人学习完全够。
6.2 看API文档
和风天气的实时天气API文档核心信息:
• 请求地址:https://devapi.qweather.com/v7/weather/now
• 请求方法:GET
• 鉴权方式:API Key,放在Query参数里(参数名为key)
• 输入参数:
参数名 | 类型 | 必填 | 说明 |
location | String | 是 | 城市LocationID(如北京101010100)或经纬度坐标 |
key | String | 是 | 你的API Key |
lang | String | 否 | 语言,zh=中文(默认) |
unit | String | 否 | 单位,m=公制(默认) |
等等,location不是直接填城市名——它要求的是"LocationID",这有点麻烦。没关系,和风天气还提供了一个"城市搜索"API,可以用城市名查到对应的LocationID。所以我们的插件需要做两个工具:
• 工具1:lookup_city——输入城市名,返回LocationID;
• 工具2:get_weather——输入LocationID,返回实时天气。
(或者你可以在插件里只做get_weather,location参数直接让用户传LocationID——但那样用户体验不好,用户哪知道北京的ID是101010100?最好两个工具都做。)
6.3 创建插件
插件名称:和风天气查询。先配置鉴权:选"API Key",位置选"Query参数",参数名填"key",值填你申请到的Key。
然后创建第一个工具lookup_city:
• 工具名:lookup_city;
• 描述:根据城市中文名查询对应的LocationID,用于后续调用天气API。当用户说"XX天气"时先调用此工具获取ID;
• 方法:GET;
• URL:https://geoapi.qweather.com/v2/city/lookup
输入参数:
• location(String/必填/Query):城市名,如"北京""上海";
• key(String/必填/Query):你的API Key(注意:因为你已经在插件级鉴权里配了key,这里不需要再配——鉴权配置会自动注入所有请求。但和风天气的Geo API和天气API是不同的子域名,鉴权配一次就行)。
💡 关于GeoAPI的key 和风天气的GeoAPI(地理信息服务)和天气API使用同一个Key,但是请求域名不同。 在扣子插件里,不同工具可以填不同的URL(域名可以不同),鉴权是插件级共享的, 所以Key只需要配一次,所有工具都会自动带上。 |
创建第二个工具get_weather:
• 工具名:get_weather_now;
• 描述:根据LocationID获取城市实时天气,包括温度、体感温度、天气状况、风向风力、湿度、能见度等。必须先调用lookup_city获取ID后再调用本工具;
• 方法:GET;
• URL:https://devapi.qweather.com/v7/weather/now
输入参数:
• location(String/必填/Query):和风天气LocationID,由lookup_city返回;
• lang(String/选填/Query):语言,默认zh。
输出参数还是用"从示例导入",你在调试面板跑一次成功的请求,把返回JSON粘进去自动识别。返回结构大概是:
{ "code":"200", "updateTime":"2024-05-20T14:30+08:00", "now":{ "obsTime":"2024-05-20T14:20+08:00", "temp":"24", "feelsLike":"25", "icon":"100", "text":"晴", "wind360":"180", "windDir":"南风", "windScale":"3", "windSpeed":"15", "humidity":"45", "precip":"0.0", "pressure":"1012", "vis":"30", "cloud":"10", "dew":"-" } } |
6.4 测试
先测试lookup_city:location填"北京",运行,看返回里的id是不是101010100。
再测试get_weather_now:location填"101010100",运行,看返回的now.temp是不是有值。
两个都测试通过后保存。
6.5 在工作流里串联
单测通过后,建议在工作流里把两个工具串起来,做一个"查天气"工作流,这样Bot不用自己判断先调哪个:
• 开始节点:输入参数city(String,用户输入的城市名);
• 插件节点1:调用lookup_city,参数location=开始节点的city,输出取第一个城市的id;
• 插件节点2:调用get_weather_now,参数location=插件节点1的id,输出now对象;
• 代码节点(可选):把返回的天气数据格式化成自然语言,如"北京当前晴,气温24度,南风3级,湿度45%,适合出行。";
• 结束节点:返回格式化后的天气文本。
在Bot里就不用直接调两个插件了,而是调用这个"查天气"工作流,Bot只需要传city一个参数。这就是"插件+工作流"组合的威力:把多步调用封装成一个简单入口。
七、实战3:对接公司内部系统(Bearer Token鉴权)
第三个实战模拟最常见的企业场景——对接内部CRM系统查询客户信息。这一类API通常需要先登录获取Token,后续请求用Bearer Token鉴权。
7.1 场景描述
假设你们公司的CRM系统有以下两个API(实际场景中请找你们后端同学要API文档):
• 登录接口:POST https://crm.yourcompany.com/api/login,传username和password,返回access_token;
• 客户查询接口:GET https://crm.yourcompany.com/api/customer/{id},Header带Authorization: Bearer {token},返回客户详情。
⚠️ 注意:公司内部系统通常部署在内网,扣子作为云端服务可能无法直接访问内网地址。这种情况有两种解决方案:①让IT把API通过网闸/反向代理暴露到公网(配好白名单和HTTPS);②使用扣子企业版的私有化部署。本篇先假设你的API已经可以从公网访问。 |
7.2 Token获取的问题
这里有个实际问题:Bearer Token通常是有时效的(比如2小时过期),你不能在插件里把Token写死——过期了就调不通了。
解决方案分两种情况:
情况A(推荐):你们后端支持"长期Token"或"API Key模式"——直接给你一个不过期的Token或永久API Key,那最简单,直接在插件鉴权里配Bearer Token,把这个长期Token填进去,不用管过期问题。
情况B:必须通过登录接口获取短期Token——这种情况不能只用自定义插件,需要结合工作流:先调登录接口拿到Token,再把Token作为变量传给客户查询接口。但扣子自定义插件的鉴权配置不支持"动态Token"(Token值不能是变量)。变通做法是:在客户查询工具里,不使用插件级Bearer鉴权,而是把Authorization作为一个自定义Header手动配,Header值填成变量(从登录节点的输出取)。
7.3 配置插件(情况A:长期Token)
如果你们后端提供了长期Token,配置非常简单:
• 创建插件"CRM客户查询";
• 鉴权方式选"Bearer Token",值填你的长期Token;
• 创建工具get_customer:方法GET,URL=https://crm.yourcompany.com/api/customer/{customer_id};
• 输入参数:customer_id(String/必填/Path)——客户ID,URL里用{customer_id}占位;
• 输出参数:根据API文档定义返回字段(客户名/联系人/电话/行业/跟进状态等),或用"从示例导入"。
7.4 配置插件(情况B:动态Token)
如果必须用登录接口动态获取Token,插件就不配置鉴权了,改由工作流处理:
第一步:创建两个工具都不配鉴权。
工具1 login:
• 方法POST,URL=https://crm.yourcompany.com/api/login
• 输入参数放在Body里(JSON格式):username(String)、password(String)
• 输出:access_token(String)、expires_in(Number,秒数)
工具2 get_customer:
• 方法GET,URL=https://crm.yourcompany.com/api/customer/{customer_id}
• 输入参数:customer_id(Path参数)、Authorization(Header参数,String类型,值"Bearer {token}",这里token要从login输出拼)
💡 怎么把Token拼到Header里 在扣子工作流里,get_customer工具的Authorization参数不能直接引用login的access_token, 因为需要加"Bearer "前缀。这时候有两种做法: 1. 在login和get_customer之间加一个代码节点,把"Bearer " + token拼接好,输出auth_header变量, get_customer的Authorization参数引用代码节点的auth_header; 2. 如果get_customer工具的Authorization参数支持模板变量,可以直接填 "Bearer {{login.access_token}}" (具体支持情况看扣子版本,用代码节点最稳妥)。 |
工作流整体串起来:
开始 → login插件(拿token)→ 代码节点(拼Bearer头) →get_customer插件(带动态Token查客户)→ 结束(返回客户信息) |
这种做法比直接配静态Token灵活,但多了一步登录调用。实际项目中如果后端能提供长期Token,强烈建议用静态Token方案,省得处理Token过期和刷新。
7.5 在Bot里用
把CRM插件挂到Bot上,提示词里加:"当用户询问客户信息时(如「查一下客户A的情况」),调用get_customer工具,需要客户ID时先询问用户。返回客户信息时以清晰的字段列表展示,重点突出跟进状态和最近联系时间。"
如果是动态Token方案,就不直接挂插件,而是把上面的工作流挂到Bot上,用户完全感觉不到背后有登录这一步。
八、插件排错指南:8个最常见的坑
调API是个"看文档+反复试"的活,第一次做几乎一定会遇到报错。别慌,绝大多数问题都是这8个坑之一。
坑1:401 Unauthorized —— 鉴权失败
症状:调试返回401状态码。
排查清单:
• Key/Token是否填对位置了?是Query参数还是Header?名字有没有拼错?(比如文档写的是X-API-Key你写成了api-key);
• Key/Token有没有多复制空格?(有时候从网页复制会带前后空格);
• Key有没有过期/被作废?去API控制台确认Key状态;
• 如果是Bearer Token,值前面是不是少了"Bearer "前缀?(注意Bearer后面有一个空格);
• 免费额度是不是用完了?去控制台看调用量统计。
坑2:400 Bad Request —— 参数错误
症状:返回400,通常会带错误提示"missing parameter xxx"或"invalid parameter xxx"。
排查清单:
• 必填参数是不是都传了?对照文档一个个核对;
• 参数类型对不对?文档要求Number你传了String(比如把数字加了引号);
• 参数位置对不对?文档说放Query你放了Body,或者反过来;
• JSON格式对不对?Body里的JSON有没有语法错误(少逗号、少引号、中文引号等);
• 参数值是否在合法范围内?比如有些API要求page从1开始,你传了0。
坑3:404 Not Found —— 地址错了
症状:返回404。
排查清单:
• URL拼写对不对?有没有多斜杠少斜杠?http和https有没有搞混?
• URL里的版本号对不对?比如文档是/v2/xxx你写成了/v1/xxx;
• Path参数是不是漏了?比如URL里有{id}占位符但你没传值;
• API是不是换域名了?去文档再确认一遍最新地址。
坑4:CORS/跨域错误
症状:在浏览器端直接调用时报CORS错误,但在扣子插件里调却正常?——放心,扣子插件是服务端发起请求,不受浏览器CORS限制。所以如果你在插件里调不通,问题不在CORS。
如果你是在自己的网页应用里调API才会遇到CORS,那时需要后端配置Access-Control-Allow-Origin。
坑5:超时(Timeout)
症状:请求一直pending,最后超时报错。
排查清单:
• API服务是不是挂了?用浏览器或Postman直接访问URL试试;
• URL是不是内网地址?(云端扣子访问不到192.168.x.x/10.x.x.x/localhost);
• 网络是否需要代理?公司内部API可能需要走VPN;
• API响应太慢?有些免费API服务器在国外,第一次请求可能需要几秒。
💡 调API必备工具:Postman/Apifox 强烈建议你在做插件之前,先用Postman或Apifox(国产免费替代品)把API调通。 这些工具可以清晰地看到每个参数怎么填、返回是什么、错误信息是什么。 在Postman里能调通的API,搬到扣子里99%也能通。如果Postman都调不通, 别先怀疑扣子,先怀疑你的参数/Key/URL。 |
坑6:返回数据解析不出来
症状:调试里明明看到返回了JSON数据,但输出参数都是空的。
原因通常是你定义的输出结构和实际返回结构不匹配:
• 字段名拼写错了?大小写对不对?(JSON是大小写敏感的,data和Data是两个东西);
• 嵌套层级对不对?比如实际返回是{ "data": { "user": { "name": "xxx" } } },你直接定义name字段在最外层,肯定取不到;
• 返回的不是JSON?有些老API返回XML或纯文本,扣子默认按JSON解析就会失败;
• 返回有数组但你定义成了Object?比如返回的是data: [{...}, {...}]数组,你需要定义Array[Object]类型。
解决办法:在调试面板看"原始响应",对照着一层层核对字段路径。用"从示例导入"生成的输出结构基本不会错。
坑7:Bot不调用你的插件
症状:插件在调试面板单独调用是好的,但挂到Bot上,用户问相关问题Bot不调用,而是胡编答案。
这不是插件的问题,是Bot"不知道什么时候该用"你的插件。解决办法:
• 工具描述写清楚!Bot是根据工具的名称和描述来判断是否调用的。描述里要包含触发关键词。比如不要只写"查询天气",要写"查询城市实时天气,包括温度、天气状况、风力等。当用户询问任何城市的天气、气温、是否下雨、穿什么衣服等问题时调用此工具。"
• 在Bot提示词里明确告诉它什么时候用你的插件;
• 插件不要挂太多——如果Bot上挂了20个插件,它容易"选择困难"。相关插件可以合并或用工作流封装。
坑8:中文乱码或编码问题
症状:返回的中文是乱码(一堆????或中文)。
排查清单:
• 是不是没加charset=utf-8?有些API默认返回GBK编码;
• 请求Header里有没有Accept-Charset或Accept-Encoding相关配置;
• 如果API支持lang参数,设为zh或cn;
• 返回的Unicode编码(形如\u4e2d\u6587)是正常的——扣子会自动解码,你在工作流里用的时候看到的是正常中文。
另外还有几个小坑快速提一嘴:
• HTTPS证书问题:有些内部API用自签名证书,扣子可能校验不过——需要让后端换成正规CA证书;
• 请求频率限制:免费API一般有QPS限制(每秒最多N次),被限流会返回429,做个简单的限流或重试就行;
• 返回字段名是数字开头或含特殊字符:极少见,遇到了用代码节点手动取值。
九、几个高级技巧
9.1 一个插件多个工具 vs 多个插件
一个插件可以包含多个工具,什么时候该合并、什么时候该分开?我的经验:
• 同一服务、同一组鉴权下的相关功能,放一个插件里。比如"和风天气"插件包含实时天气/7天预报/空气质量三个工具;
• 不同服务或不同鉴权,分成不同插件。比如"和风天气"和"每日一言"肯定是两个插件;
• 工具数量不要太多——一个插件超过5个工具,Bot选择准确率会下降。如果功能太多,按场景拆成多个插件。
9.2 用"输出示例"替代手动定义字段
前面提过"从示例导入"这个功能,我要再强调一次:这是神器。
与其手动一个个字段加输出参数(还容易拼错),不如:
• 先用Postman或扣子调试面板跑一次成功请求;
• 复制返回的JSON;
• 在输出参数配置里点"从示例导入",粘贴JSON,一键生成所有字段;
• 删掉你不需要的字段,保留核心字段就行。
10秒钟搞定,零拼写错误。
9.3 用代码节点做"二次加工"
插件返回的原始数据有时候不好用,比如返回一堆字段你只需要其中两个;或者返回的时间是时间戳需要转成可读格式;或者你想把多个字段拼成一句自然语言。
这时候不要在插件层面折腾——插件的职责就是"忠实地拿回数据",加工处理交给代码节点。上一篇学的代码模板(JSON解析/格式化/过滤/排序)在这里正好用上。
举个例子:和风天气返回的icon字段是数字编码(100=晴、101=多云等),你可以在代码节点里建一个映射字典,把数字转成中文描述,再拼出"北京当前晴,24度"这样的自然语言。
9.4 插件+工作流组合拳
一个很有用的模式:把复杂的多步API调用封装在工作流里,对外暴露一个简单接口。
比如"查天气"工作流对外只需要city一个参数,内部完成lookup_city→get_weather→格式化输出三步。Bot只需要调用一个工作流,不用关心底层细节。
这种模式还有个好处:如果以后你换了天气服务商(比如从和风天气换成心知天气),只需要改工作流内部,Bot提示词和用户交互完全不用动——这就是"封装"的价值。
十、小Co升级:接入真实面经数据库
回到我们贯穿系列的"面试教练小Co"。前几篇的小Co,面试题是大模型自己生成的——虽然也能出像样的题,但不够"真"。如果能接入真实的大厂面经数据库,面试体验会好很多。
这一篇我们用自定义插件把真实面经API接入小Co。
10.1 思路
市面上有一些提供面试题API的服务(比如面试鸭、牛客网开放API,或者你自己用爬虫收集整理后部署成API)。为了演示,我假设你已经有一个面试题API,提供以下接口:
• GET https://api.interview.com/questions——按岗位/难度/公司随机抽题,参数position(岗位)、difficulty(easy/medium/hard)、company(公司名,可选),返回{id, question, answer, company, position, difficulty, tags};
• 鉴权:API Key,放在Header的X-API-Key里。
(实际你可以找公开的面试题API或者自己搭一个。自己搭API用FastAPI或Flask写个简单的Python服务就行——这个等你学到第12篇API/SDK章节会讲。)
10.2 创建"面经题库"插件
按前面的流程:
• 插件名:面经题库;
• 鉴权:API Key,位置Header,参数名X-API-Key;
• 工具1:get_random_question——随机抽题,参数position/difficulty/company;
• 工具2:get_question_by_id——按ID查题(用于题目详情和答案);
• 工具3:search_questions——按关键词搜题(用于针对性练习)。
输出字段按"从示例导入"配置,核心字段:id/question/answer/company/difficulty/tags。
10.3 改造generate_question工作流
之前的generate_question工作流是"大模型节点出题"。现在升级一下:
开始(position/difficulty)→ 插件节点(get_random_question,从真实题库抽题) → 判断节点:如果返回了题目(有id)→ 直接用这道题 如果没返回(题库里没有对应岗位/难度)→降级到大模型出题 → 结束(返回题目) |
为什么加一个"降级到大模型"的分支?因为真实题库覆盖面有限,冷门岗位或细分领域可能没题——这时候让大模型兜底出题,保证面试不会卡壳。这就是"确定性数据+大模型兜底"的经典模式。
10.4 升级evaluate_answer评分工作流
有了真实题库,评分时可以参考标准答案:
• 在evaluate_answer工作流里,增加一步:调用get_question_by_id拿到题目的标准答案(answer字段);
• 把用户答案和标准答案一起传给大模型评分节点,提示词改为:"请对比用户答案和参考答案,从准确性/完整性/逻辑性/深度四个维度打分(1-10分),给出改进建议。参考答案仅作参考,用户答案如果思路不同但正确,同样给高分。"
这样评分会更靠谱,因为有标准答案作为参照系,大模型不会"自己出题自己判卷"了。
10.5 更新Bot提示词
在小Co的提示词里追加:
模拟面试升级说明: - 面试题目优先调用"面经题库"插件的get_random_question,从真实面经中抽题 - 如果题库返回为空(无匹配题目),再自行生成题目 - 评分时传入题目ID,评分工作流会自动获取参考答案作为评分参照 - 面试结束后的报告里,标注每道题来自哪家公司的真实面经(如果有company字段) - 用户说"来道阿里的Java题"这类指定公司的请求时,优先调用search_questions按公司筛选 |
现在小Co的题目是"真题"了,答案评分有"参考答案"对照——面试教练的专业度直接上一个台阶。
这就是自定义插件的价值:你可以把任何外部数据源接入Bot,让你的AI应用从"只会聊天"变成"有数据支撑的专家"。
十一、本篇小结
这一篇知识点密度很大,帮你拉一条主线:
• 自定义插件本质是"扣子帮你发HTTP请求"——任何有HTTP API的服务都能接入;
• HTTP请求四要素:方法(GET/POST)、URL、Header、Body;
• 返回看状态码(2xx成功/4xx你的错/5xx服务器错)和JSON Body;
• 四种鉴权:无/API Key/Bearer Token/OAuth,按文档选;
• 创建插件流程:填基础信息→建工具(配URL/参数/输出)→配鉴权→调试→保存;
• 输出参数用"从示例导入"最快最准;
• 三个实战从易到难:公开无鉴权→API Key→Bearer Token;
• 排错8个坑:401鉴权/400参数/404地址/超时/解析失败/Bot不调用/乱码/限流;
• 插件拿回数据后,加工处理交给代码节点——职责分离;
• 复杂调用封装成工作流,对Bot暴露简单接口。
到这一篇为止,你已经掌握了智能体开发的"四大件":提示词(第2篇)、插件(第3、8篇)、知识库(第4篇)、工作流+代码(第6、7篇)。这些能力组合起来,你已经能做出80%的实用Bot了。
🔮 下一篇预告
前面我们做的所有Bot都是"被动响应"——用户问一句Bot答一句。但很多场景你需要Bot"主动找你":每天早上8点推送当日新闻、每小时监控一次竞品价格、有人提交表单时立刻通知你……
下一篇《第9篇 - 触发器与定时任务:让AI主动找你》,我们学习怎么让Bot不需要你说话就能自动干活。
你将学到:
• 什么是触发器?定时触发 vs 事件触发的区别和应用场景;
• 定时任务配置:Cron表达式基础(每天/每周/每月/工作日怎么配);
• 实战1:做一个"每日早报"定时推送——每天早上8点自动生成新闻简报发给你;
• 事件触发:Webhook触发——外部系统发生事件时自动启动Bot/工作流;
• 实战2:表单提交自动回复——有人填了你的问卷,Bot自动发感谢+回复常见问题;
• 定时+工作流+插件的组合拳:打造7x24小时自动运转的AI助手;
• 触发器的5个常见坑:时区问题/重复触发/漏触发/推送失败/成本控制;
• 小Co升级:每天定时给用户发一道"每日一题",持续陪练。
学会触发器,你的Bot就从"应答机"进化成了"主动助手"——它会自己定时干活、自己响应外部事件、自己在你需要的时候主动出现。这是从"工具"到"助手"的关键一步。
发布时间:下周更新,记得点赞+在看+星标公众号不迷路~
📚 本系列完整目录预告
「Coze智能体开发系列」规划目录(根据反馈持续更新):
阶段 | 篇号 | 标题 | 核心内容 |
一·入门 | 第1篇 | 扣子入门:从零认识智能体开发 | 概念辨析+平台介绍+第一个Bot |
一·入门 | 第2篇 | 提示词工程:写出让AI乖乖听话的指令 | 万能公式+10套模板+调试方法 |
二·基础 | 第3篇 | 插件使用:给智能体装上100种能力 | 常用插件+组合调用+控制策略 |
二·基础 | 第4篇 | 知识库与数据库:让AI读你的书、记你的事 | RAG原理+分段调优+数据表设计 |
二·基础 | 第5篇 | 第一次发布:把Bot推到豆包/飞书/微信 | 全渠道发布+冷启动+数据观察 |
三·进阶 | 第6篇 | 工作流入门:用流程图实现自动化 | 节点/连线/变量/调试全攻略 |
三·进阶 | 第7篇 | 代码节点:会几行Python就能开挂 | Python/JS基础+数据处理实战 |
三·进阶 | 第8篇 | 自定义插件:对接任意API | API原理+鉴权+插件创建+调试(本篇) |
三·进阶 | 第9篇 | 触发器与定时任务:让AI主动找你 | 定时/事件触发+每日简报实战 |
四·高级 | 第10篇 | 多智能体协作:组建AI团队 | 主编/写手/审核多Agent模式 |
四·高级 | 第11篇 | RAG调优:让知识库回答精准不胡说 | 分段策略+混合检索+召回优化 |
四·高级 | 第12篇 | API与SDK:把智能体接入你的产品 | 开放API+Webhook+网页嵌入 |
五·实战 | 第13篇 | 实战项目一:企业FAQ客服机器人 | 知识库+人工转接+数据统计 |
五·实战 | 第14篇 | 实战项目二:AI周报/日报生成器 | 飞书/钉钉集成+文档生成 |
五·实战 | 第15篇 | 实战项目三:英语口语陪练 | 语音多轮+评分反馈+水平定级 |
五·实战 | 第16篇 | 实战项目四:自媒体内容生产线 | 选题→写作→审核→发布全链路 |
五·实战 | 第17篇 | 实战项目五:热点追踪与简报推送 | 定时爬取+分析总结+邮件推送 |
六·成长 | 第18篇 | 调试优化:让Bot从能用变好用 | 日志分析+AB测试+成本控制 |
六·成长 | 第19篇 | 商业化路径:用扣子怎么赚钱 | 模板付费/接单/咨询/培训全解析 |
六·成长 | 第20篇 | 持续成长:从扣子到Agent生态 | 作品集+社区+前沿跟进+学习路径 |
💡 本篇练习作业 1. 跟着实战1做一遍"每日一言"插件——从注册到创建到调试到挂到Bot上完整走一遍, 这是你第一个自定义插件,跑通了就有手感; 2. 注册一个和风天气或心知天气免费账号,做一个自己的天气查询插件, 包含"城市搜索+实时天气"两个工具,用工作流串联起来; 3. 找一个你自己感兴趣的公开API(推荐去"公开API大全"这类网站搜,比如随机猫图、 网易云音乐、星座运势、历史上的今天、快递查询、IP归属地等),做一个属于你自己的 专属插件,挂到Bot上试试效果; 4. (选做挑战)如果你有公司内部系统的访问权限,尝试对接一个内部API—— 比如查请假余额、查工单状态、查知识库文档。做成插件后挂到Bot上, 你会发现办公效率提升一大截(前提是找IT确认权限和安全策略); 5. (选做挑战)把小Co升级部分的"面经题库"插件做出来——你可以先用一个公开的 面试题API或自己整理一份JSON作为数据源(数据放在代码节点里也行), 让小Co的出题从"AI生成"升级到"真题抽选"。 做插件最重要的是"敢试"。报错不可怕,照着第八节的排错清单一条条对,90%的问题 都能自己解决。做出来第一个插件的那一刻,你会发现整个互联网都是你的插件库。 |
📌 本篇是「Coze智能体开发系列」第8篇,原创首发,转载请注明出处。
API是智能体连接世界的桥梁——学会自定义插件,你的Bot就能和全世界对话。下一篇学触发器,让Bot从"被动应答"变"主动干活"。觉得有用就点赞、在看、转发给身边学AI的朋友,我们第9篇见!🚀