Dify 插件系统如何工作?开发插件时要注意哪些边界?
Dify 插件系统的作用,是把模型、工具、数据源和外部服务封装成可安装、可配置、可复用的能力,而不是把所有逻辑写死在某个工作流节点里。对开发者来说,插件至少包含三件事:声明自己提供什么能力,定义用户需要填写哪些参数,在运行时代码里执行调用并返回结构化结果。这样同一个搜索、工单、数据库或消息推送能力,可以被多个应用复用。
插件由清单、定义和运行时代码组成
插件清单描述名称、版本、作者、图标、权限和配置项;工具定义描述参数类型、是否必填、前端如何展示;运行时代码负责调用外部 API、处理文件或返回模型结果。以工具插件为例,如果要接入内部工单系统,可以把“查询工单”“创建工单”“追加评论”拆成不同工具,而不是让每个工作流都手写 HTTP 请求。
yamlidentity: name: ticket_query author: platform-team label: zh_Hans: 查询工单 parameters: - name: ticket_id type: string required: true label: zh_Hans: 工单 ID
运行时代码要处理异常和敏感字段
插件调用外部服务时,不能把所有失败都包装成“系统错误”。参数缺失、鉴权失败、限流、超时、业务数据不存在,对用户的提示和重试策略都不一样。返回结果也要裁剪,模型只需要完成任务所需字段,不应该拿到 token、手机号、内部备注等敏感信息。
pythonfrom dify_plugin import Tool class TicketQueryTool(Tool): def _invoke(self, tool_parameters): ticket_id = tool_parameters.get("ticket_id") if not ticket_id: yield self.create_text_message("ticket_id 不能为空") return data = self.session.get(f"/tickets/{ticket_id}", timeout=8).json() yield self.create_json_message({ "id": data["id"], "status": data["status"], "summary": data.get("summary", "") })
使用插件要控制权限和耗时
能查客户资料、发消息、执行 SQL 的插件,本质上都是可被模型间接触发的操作入口。凭证要放在平台安全配置里,scope 尽量小,高风险动作最好增加人工确认。性能上也要设置超时、缓存和输入大小限制;几分钟的离线任务不适合同步插件调用,否则用户体验和排错都会很差。
插件发布前还要准备最小可用示例和失败样例。前者帮助使用者快速验证凭证和参数,后者能说明哪些错误需要用户处理、哪些应该找平台排查。没有这些样例,插件一旦进入多个工作流,维护者很难判断问题来自配置、外部 API 还是插件代码。插件版本升级时也要说明兼容性,尤其是参数名、返回字段和权限 scope 的变化。否则旧工作流可能还能运行,但模型收到的数据结构已经变了。
追问
Dify 插件和普通工作流节点有什么区别?
普通节点更像一次具体编排,插件是可复用能力封装。插件能统一鉴权、参数校验、错误处理和返回格式,适合多个应用复用。取舍是一次性小需求用 HTTP 节点更快,长期能力或敏感凭证更适合做插件。
工具插件、模型插件、数据源插件怎么选?
调用外部 API 或执行动作,通常做工具插件。接入新的 LLM、Embedding 或重排序服务,应做模型插件;接入外部知识库、文档系统或数据库检索,更适合数据源插件。边界是不要用工具插件硬模拟模型,也不要让数据源插件承担复杂写操作。
插件凭证应该怎么管理?
凭证不要写进代码、提示词或工作流变量,应放在插件配置或平台安全存储中。多租户环境还要区分 workspace 级和用户级凭证。踩坑最多的是把测试 token 打进插件包,发布后所有环境都误用同一份凭证。
插件返回给模型的数据要裁剪吗?
要裁剪。返回太多会浪费 token,也可能暴露敏感信息;模型通常只需要状态、摘要、原因和可追踪 ID。边界是不能裁剪到不可解释,否则用户和开发者都不知道插件为什么给出这个结果。