自定义插件六步:找到接口、写描述、填参数、校验、真调一次、把返回解析成下游能用的形状。 前四步是填表,第五步是验证,第六步最容易被跳过——也是故障最多的地方。 这一节真起一个服务、真发一次请求,最后把接口那边的字段改个名,看链怎么坏。
上一节讲怎么用现成插件,这一节讲怎么做自己的。 这一节是全章最实操的一节,也是后面第 10 章(视频解析插件)、 第 13 章(多维表格节点)的前置——那两个案例卡住的地方,都是这一节的第六步。 沙箱里真起了一个本地 HTTP 服务当「股票接口」,所以下面的每一步都是真跑的。
一、第一步:找到接口,先看它返回什么
做插件之前先拿到接口文档,看清楚三件事:请求地址、要哪些参数、返回什么结构。 最重要的是第三件。 因为插件配好之后,下游节点要从返回里取字段。返回结构不清楚,下游就没法写。 演示里本地起了一个服务,访问 /stock?code=600519 返回一段 JSON:代码、名称、最新价、涨跌幅。
四个字段里,下游真正要用的往往只有两个:名称和最新价。剩下两个是给别的地方用的。 先想清楚你要哪两个,再动手配。
二、第二步:写描述
描述要写「用户会怎么说」。 查股价这件事,用户会说「茅台今天多少钱」「600519 现在多少」,不会说「查询证券行情数据」。 所以描述写成「按六位股票代码查询最新价、名称与涨跌幅」,比「股票行情接口」好得多。 描述里还要写清「输入什么」:六位代码。 不写这一句,模型可能拿「茅台」这两个字去填 code,接口当然查不到。
三、第三步到第五步:参数、校验、真调
参数只有一个:code,类型 string,必填。类型写错平台会拦——把 string 写成 text 就存不进去。 填完点保存,平台跑一遍校验。校验通过不等于能用,还要真调一次。 真调的时候填一个真实的代码,看返回对不对。 这一步必须做,不能跳过。很多人配完直接去工作流里试, 结果报错时不知道是插件的问题还是节点的问题。
演示里调 600519,返回贵州茅台 1688.5 元,涨 1.23%。到这儿插件就算能用了。
四、第六步:把返回解析成下游能用的形状
插件节点吐出来的是一整段 JSON,下游要大模型节点读它,得先拼成一句话。 拼的时候就要取字段。这时候如果字段名对不上,问题就来了。 演示里把接口的 price 改成了 last_price,下游还在取 price,取到的是空值, 于是拼出「贵州茅台 现价 元,涨 1.23%」。
注意它没有报错。 链是通的,日志是绿的,只是那句话缺了个数。这是插件最常见也最难查的故障形态。 防它的办法只有一个:把「取不到值」当错误处理。 取不到就停,别往下走。 宁可报错,也别吐一句缺了角的答案。
五、什么样的插件值得自己做
平台已有的别做。官方插件稳定,第三方插件有人维护,只有平台没有的才值得自己做。 值得做的三类:自家系统的接口(查订单、查库存)、垂直领域的数据源(行业数据库、内部文档)、 有特殊格式的转换(平台不支持的文件类型)。 不值得做的两类:通用能力(搜索、翻译、画图,平台都有)、一次性的小工具(用完就扔, 不如手工做一次)。
这条判断能省很多时间。做插件最贵的不是写,是之后接口变了要跟着改。
六、动手 Demo:从一份接口到一次真调用,再到一次静默失败
本地起一个服务当股票接口,看它返回什么;写成插件描述;真调一次。 最后把接口的字段改个名,看下游会出什么事。
base, stop = serve({'/stock': (200,
'{"code":"600519","name":"贵州茅台","price":1688.5,"pct":1.23}')})
s = spec('股票行情', '按六位股票代码查询最新价、名称与涨跌幅',
base + '/stock', [('code', 'string', True, '六位股票代码')])
code, data = call_plugin(s, arg={'code': '600519'})
print(code, data['name'], data['price'], data['pct'])
# 接口那边把 price 改成了 last_price
s2 = spec('股票行情', '按六位股票代码查询最新价',
base2 + '/stock', [('code', 'string', True, '六位股票代码')])
_c, data2 = call_plugin(s2, arg={'code': '600519'})
v = data2.get('price') # None,但不报错
实跑输出:
--------------------------------------------------------------------
自定义插件:从一份接口到一次真调用
--------------------------------------------------------------------
① 目标接口返回什么
--------------------------------------------------------------------
本地起了一个服务,地址 http://127.0.0.1:62459/stock?code=600519。
HTTP 200,返回 {"code":"600519","name":"贵州茅台","price":1688.5,"pct":1.23}
② 把它写成插件描述
--------------------------------------------------------------------
名字:股票行情
描述:按六位股票代码查询最新价、名称与涨跌幅(19 个字,模型靠它决定用不用)
地址:GET/62459/stock
参数:code(string,必填)
校验:通过
③ 真调一次
--------------------------------------------------------------------
HTTP 200
返回:{"code": "600519", "name": "贵州茅台", "price": 1688.5, "pct": 1.23}
拼成一句话:贵州茅台 现价 1688.50 元,涨 1.23%
④ 接口那边改了个字段名
--------------------------------------------------------------------
HTTP 200,返回里没有 price 这个键了
下游取 data['price'] → None
于是拼出:贵州茅台 现价 元,涨 1.23%——数字位置空着,但整句话照样吐出去了。
! 这就是插件最常见的故障形态:不报错,只是少了一段。链路通、日志绿,答案缺个角。
防它的办法只有一个:把返回结构的校验也写进链里,取不到就停,别往下走。
①第一段先看接口返回什么。四个字段里下游真正要用的往往只有两个,先想清楚要哪两个再动手。
②描述那段:「按六位股票代码查询最新价、名称与涨跌幅」比「股票行情接口」好——前者是用户的话,
后者是接口的学名。
③真调那一次返回 200,四个字段都在。到这儿插件能用了。
这一步不能跳,跳了后面报错时分不清是插件的问题还是节点的问题。
④最后一段是本节的重点。
字段名改了,请求照样成功,data2.get('price') 返回 None,整条链一路绿灯。
⑤真机上这表现成「答复里少了个数」或者「现价 元」。查起来很费劲,因为没有任何报错。
所以取不到值要当错误处理。
30 秒实验
- 拿一个你能接触到的接口,把它的返回字段数一遍。数完问:我真正要哪两个。
- 给你现有的插件加一句判断:取不到值就停。加完再看一遍日志。
- 找三个平台已有的插件,看看它们能不能替掉你手上那个自定义插件。
常见误区
- 「配完直接去工作流里试。」报错时分不清是插件还是节点。先在插件页面单独调一次。
- 「返回字段差不多就行。」字段名差一个字母,取到 None,链照样跑完。差别在答复里少了一个数。
- 「什么都自己写插件。」通用能力平台都有,自己写要长期维护接口变更。只有平台没有的才值得做。
自测三问(点开对答案)
1. 做插件之前先看接口文档的哪一项? —— 返回结构。因为下游要从里面取字段,取哪几个决定了插件该怎么配。 2. 为什么插件页面要单独真调一次? —— 分开验证。配完直接进工作流,报错时分不清是插件的问题还是节点的问题。 3. 接口改了字段名,链会怎么表现? —— 不报错。请求成功,只是取到空值,答复里少一段——链通、日志绿、答案缺个角。插件让它能办事,但办完怎么把结果摆给用户看? 纯文字排下来又挤又乱,下一节讲卡片——一种结构化的回复形状。
- ☐ (本篇完,下一篇 3.4 什么是卡片)
相关笔记
- 什么是插件:插件是说明书
- 如何使用插件:两种接法怎么选
- 37 图解 HTTP · 索引
- 🐦 扣子开发 AI Agent · 索引