夜雨聆风学习资料网

ARTICLE · 1106056

第8篇 :自定义插件:对接任意API

第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篇见!🚀

相关学习资料