Dify 插件开发实验(02):参数与凭证体系——插件参数和凭证如何声明、配置与管理?

Dify 实验系列 · 插件开发 02/12 | 实验编号:DIFY-106-02
基于 Dify 1.16.1 实测(2026-08)

1. 业务场景

先讲一个我们实际遇到的场景。

客服工单 SaaS 的客服每天要接几十通电话,用户开口第一句往往是「我的订单怎么还没处理」。客服要做的第一件事,就是打开工单系统,按用户报的工单号查状态——是正在处理、已完成,还是根本没查到。这个「按工单号查状态」的动作,背后是一次带密钥的系统调用:客服侧应用要拿一个 api_key 去访问工单系统,才能换回订单状态。

我们第一次接这类需求时,第一反应也是「调个接口而已,密钥写死在代码里不就行了」。真正动手才发现——密钥怎么放、参数怎么校验、错误怎么分层,每一件都比调通接口更磨人:密钥散落在代码和日志里,泄露一次就是安全事故;工单号格式错了没人知道错在哪;查询失败只有一句「查询失败」,客服和运维都只能干瞪眼。

这不是个例。任何「一个系统要调用另一个系统」的业务场景都是这个模式:CRM 查客户、财务查发票、物流查轨迹——调用方要传参数,还要带凭证,参数错了、凭证错了、业务不存在了,返回的错误各不相同。

2. 场景痛点

这个流程的痛点,在客服团队身上体现得最直接:

  • 密钥散落各处api_key 写死在代码里、贴在配置文件中、甚至跟着错误日志一起打印出来——泄露一次,工单系统的数据就被别人随意查。
  • 参数格式全靠人记:工单号必须是 WO- 开头加 8 位数字,客服手输、别的系统传错格式,查询直接失败,但没人知道错在哪。
  • 错误一团模糊:查询失败只给一句「查询失败」,到底是没有这个工单,还是密钥不对,还是系统挂了?客服只能反复重试,运维也无从下手。
  • 凭证配置混乱:同一个工具在不同环境(测试/生产)要用不同的密钥,写死在代码里就意味着每次换环境都要改代码重新发布。

本质上,参数与凭证是工具交付给下游的「接口契约」——契约不清晰、密钥不安全,工具就只是「能跑」,远谈不上「能交付」。

3. 方案:为什么是插件凭证体系

选插件凭证体系,我们实际对比过:

  • 平台原生凭证机制:插件 provider 层原生支持 secret-input 密钥型凭证——加密存储、UI 脱敏,密钥不进代码、不进日志;
  • 凭证一次配置、处处注入:provider 级凭证配一次,该插件所有工具共享,运行时自动注入,调用方完全不用碰密钥;
  • 错误可结构化、可分流:参数错/凭证错/业务错分层返回统一 {error:{code,message}},工作流 IF-ELSE 直接按 error 结构分支处理。

这篇文章我们就用它搭一个「工单查询」工具插件:必填参数 order_id(格式校验 WO- 开头 + 8 位数字)+ provider 级凭证 api_key,跑通「声明 → 配置 → 注入」的完整凭证链路,并用本地 mock 工单服务验证参数/凭证/业务三层错误的分层返回。

4. 整体架构

开始(order_id 输入)

工具节点 get_order_status(凭证注入 api_key)

IF-ELSE(输出文本包含 'error'?)

错误输出 end_error

正常输出 end_ok

IF-ELSE 分流用 contains / not contains "error" 判断(工具统一返回 {error:{code,message}} 结构)。

链路很清晰:入口收工单号 → 工具校验参数 → 注入凭证调工单系统 → 按 error 结构分流。关键设计是凭证与参数分离——参数随调用走,凭证在 provider 层配置,密钥永远不经过调用方。

5. 模块设计

5.1 凭证声明(provider/order_tool.yaml)

credentials_for_provider:
  api_key:
    type: secret-input          # 密钥型:加密存储、UI 脱敏
    required: true
    label:
      en_US: API Key
    placeholder:
      en_US: Please input your API Key
  base_url:
    type: text-input            # 普通文本:服务地址
    default: http://127.0.0.1:8002
    required: false
tools:
  - tools/get_order_status.yaml

5.2 参数声明(tools/get_order_status.yaml)

parameters:
  - name: order_id
    type: string
    required: true
    form: llm
    llm_description: 'Order id, must match format WO- followed by 8 digits, e.g. WO-20260805'

注意:schema 层没有 pattern 字段,格式校验在工具代码内做(ORDER_ID_PATTERN = re.compile(r"^WO-\d{8}$"))。

5.3 凭证三要素 API 流程(实测)

声明 → 配置 → 注入,三步缺一不可:

  1. 声明:provider yaml 的 credentials_for_provider(secret-input / text-input)。
  2. 配置:控制台插件凭证页录入(POST /tool-provider/builtin/order_tool/add 创建凭证记录)。
  3. 必须设为默认:POST /tool-provider/builtin/order_tool/default-credential(body {id: credential_id})——实测 add 之后 is_default=false,运行时不注入;set 之后才注入。

5.4 错误分层(tools/get_order_status.py)

if not order_id:
    yield ... {"error": {"code": "param_invalid", "message": "order_id is required"}}
if not ORDER_ID_PATTERN.match(order_id):
    yield ... {"error": {"code": "param_invalid", "message": "order_id must match WO-XXXXXXXX"}}
api_key = self.runtime.credentials.get("api_key", "")
if not api_key:
    yield ... {"error": {"code": "auth_failed", "message": "api_key is not configured"}}
# 调工单系统:401 → auth_failed;404 → not_found;非 200 → upstream_error
# RequestException 异常 → upstream_error(含超时)

四 code 统一:param_invalid(调用前可拦截)/ auth_failed(认证失败)/ not_found(业务不存在)/ upstream_error(上游故障),不抛裸异常。

6. 运行验证

输入 预期 结果
WO-20260805(合法工单) 返回 processing 通过
WO-20260804(合法工单) 返回 done 通过
缺 order_id / 非法格式 abc param_invalid 通过
未配置凭证 / 错误凭证 auth_failed 提示去配置 通过
WO-99999999(不存在) not_found(区分于参数错) 通过
workflow 集成 IF-ELSE 按 error 分流(end_ok/end_error 正确) 通过
日志检查 无 api_key 明文 通过(DB 密文 HYBRID 前缀 + UI 脱敏 mo******06)

7. 实战坑

现象 修复
provider_type 写 plugin DSL 校验能过但运行时凭证永远空,报 auth_failed「api_key is not configured」 必须写 builtin——ToolManager match 只认 BUILT_IN case,凭证注入在该分支内 isinstance 处理(实测,重大修正)
凭证配置后未注入 add 创建凭证记录后 is_default=false(DB 实测),运行时不注入 必须 POST default-credential 设为默认(实测)
插件访问宿主机不通 127.0.0.1 指向 daemon 容器自己 → ConnectionError upstream_error 宿主机服务用 http://host.docker.internal:端口(实测)
schema 无 pattern 字段 参数格式校验无处声明 工具代码内 ORDER_ID_PATTERN re.match 校验(实测)
错误结构不统一 下游分支难以处理 统一 {error:{code,message}} 四 code,IF-ELSE contains ‘“error”’ 分流(实测)
凭证泄漏进日志 api_key 明文暴露风险 加密存储(DB 密文)+ UI 脱敏,工具错误信息不含密钥(实测)

8. 实验文档及源码获取

文章聚焦核心配置与采坑点;实验的完整分步操作(节点搭建/参数表/调试指引)见实验文档原文。


下一篇:Dify 插件开发实验(03):工具接入工作流与Agent——插件工具如何在工作流和 Agent 中使用?

💬 你在这个实验的场景里踩过什么坑?欢迎评论区分享你的实战经验。

Logo

欢迎加入 MCP 技术社区!与志同道合者携手前行,一同解锁 MCP 技术的无限可能!

更多推荐