Dify 中级实验(18):插件开发入门——如何把工作流变成 Agent 可调用的工具?
Dify 中级实验18插件开发入门——如何把工作流变成 Agent 可调用的工具Dify 实验系列 · 中级 18/20 | 实验编号DIFY-102-19基于 Dify 1.16.1 实测2026-081. 业务场景先讲一个我们实际遇到的场景。一家公司的内部 CRM 系统没有现成的插件销售团队的 AI 助手想查客户信息却查不了——模型只能闲聊一问「客户 1001 的订单情况」它就答「我无法访问你们的系统」。公司的 Agent 应用明明能力很强却因为接不上内部系统变成了一个高级聊天机器人。他们想过让开发团队写接口但排期要三周想过等官方插件但内部系统大概率永远不会有官方插件。我们第一次接这类需求时第一反应也是「等官方插件或者让开发排期写接口」。后来才想明白——内部系统大概率永远不会有官方插件等插件等于放弃好在 Dify 给了第三条路任何工作流发布即工具。这不是个例。任何「Agent 要对接公司内部系统」的场景都是这个模式查 CRM 客户、查 ERP 库存、查工单系统、查内部 Wiki——官方插件市场覆盖的是通用服务公司内部系统只能自己造工具。好在 Dify 给了答案任何工作流发布后都可以变成「自定义工具」被 Agent 自动发现和调用。2. 场景痛点这个场景的痛点在这家公司的销售 AI 助手项目上体现得最直接Agent 接不上内部系统模型能力再强没有工具就查不了数据Agent 对业务数据「睁眼瞎」销售问什么它都答不上来。等插件遥遥无期内部系统几乎不会有官方插件等插件等于放弃找开发排期写接口一个查询功能就要等几周。工具参数不可控就算接了接口如果参数设计随意Agent 会「自由发挥」——传错客户 ID、传错查询类型查询结果全乱。查询语义不诚实查不到客户时有的实现会返回一个「默认客户」的假数据糊弄过去——这在业务上是绝对不能接受的。本质上工具不在于复杂而在于输入输出契约清晰——把查询语义做真、把参数枚举收窄Agent 才能可靠地自主调用。3. 方案为什么是「工作流发布为自定义工具」Dify 的扩展机制很直接任何 Workflow 保存并发布后都可以变成自定义工具被 Agent/其他工作流调用。本实验就走通「构建 CRM 查询工作流 → 发布为工具 → 供 Agent 调用」的完整链路。选它的理由零等待自建工具不用等官方插件不用排期开发工作流搭好即发布即用输入输出契约天然清晰工具的入参就是工作流的开始变量用枚举select把参数收窄成合法值Agent 没有自由发挥的空间查询语义可控查不到就返回「未找到」语义foundfalse 空信息绝不塞默认数据——下游 LLM 会引导用户核对而不是编造答案。这篇文章我们就用它搭一个「CRM 查询工具」工作流输入customer_id和query_type查询客户基本信息/订单/工单发布为工具后挂载给 Agent 自主调用。4. 整体架构开始customer_id query_type模拟CRM APICode内置客户表按 query_type 分发found/data_json/summary格式化回复LLM把结构化结果转成自然语言结束链路很清晰入口收两个参数 → 代码节点按 query_type 分发查询 → LLM 把结构化结果格式化成自然语言。4 个节点、3 条边——工具不在于复杂而在于输入输出契约清晰发布后 Agent 只要知道「传 customer_id 和 query_type拿回文本」就能自主调用。5. 模块设计5.1 开始节点query_type用下拉枚举把 Agent 的「自由发挥」收窄成三个合法值——枚举约束是工具参数设计的第一原则-label:客户IDrequired:truetype:text-inputvariable:customer_id-label:查询类型options:[basic,orders,support]required:truetype:selectvariable:query_type5.2 模拟 CRM APICode核心真实 CRM 接口GET /customers/{id}在实验里用代码节点模拟重点是查询语义要真实——查不到就返回「未找到」绝不塞默认客户数据defmain(customer_id:str,query_type:str)-dict:importjson,time time.sleep(0.3)# 模拟真实 CRM API 延迟cidstr(customer_idor).strip()qtquery_typeorbasiccustomers{1001:{name:张三,level:vip,total_orders:12},1002:{name:李四,level:normal,total_orders:3},1003:{name:王五,level:new,total_orders:0},}customercustomers.get(cid)ifnotcustomer:return{found:false,data_type:qt,data_json:{},summary:未找到客户 {}.format(cid)}ifqtorders:data[{order_id:ORD-1001-1,product:产品A,amount:299.0,status:已完成}]summary客户 {} 的订单列表{} 笔.format(customer[name],len(data))elifqtsupport:data[{ticket_id:TK-9001,title:产品A 无法登录,status:处理中}]summary客户 {} 的支持工单{} 张.format(customer[name],len(data))else:datacustomer summary客户 {}等级 {}累计 {} 笔订单.format(customer[name],customer[level],customer[total_orders])return{found:true,data_type:qt,data_json:json.dumps(data,ensure_asciiFalse),summary:summary}要点found展平成 stringtrue/false——下游 IF-ELSE 才能判断boolean 类型在节点间不可见data_json输出 JSON 字符串保结构summary输出文本给 LLM——双形态输出是工具节点的通用约定5.3 发布为工具保存并发布这个 Workflow 应用进入「工具 → 自定义工具 → 通过工作流创建工具」选择刚发布的应用工具自动生成参数面板对应 start 变量配置后即可在 Agent 的「工具」列表里挂载⚠️ 发布为工具后工具内部注册 IDprovider_id是发布时生成的 UUID不是应用 ID子工作流重新导入并重新发布后注册 ID 会变化调用方必须同步更新。6. 运行验证场景输入预期实测结果查询基本信息customer_id1001, query_typebasicfoundtrue返回张三的等级与订单数模拟 API 命中LLM 正常格式化 ✓查询订单customer_id1001, query_typeorders返回订单列表 JSON 摘要订单分支触发 ✓客户不存在customer_id9999, query_typebasicfoundfalse提示「未找到客户 9999」未找到分支正确返回不编造数据 ✓Agent 调用在 Agent 应用挂载工具后说「查一下客户 1001」Agent 自动调用工具并组织回答Agent 识别意图并触发工具调用 ✓7. 实战坑坑现象修复模拟 API 查不到也返回默认客户问不存在的客户 ID得到一份「默认客户」的假信息兜底分支返回「未找到」语义foundfalse 空信息让下游 LLM 引导用户核对found用 boolean 输出下游 IF-ELSE 判断不到展平为 stringtrue/false用customer_id当参数名但代码签名写别的运行报main() got an unexpected keyword argumentcode 节点 variables 的 variable 名必须等于def main(...)签名参数名Dify 按名传参工作流发布为工具后 provider_id 写死旧值重新导入发布后调用方报「workflow provider not found」每次重新发布后从工具列表动态查询最新 provider_id 并同步真实 API 场景直接写 http-request 没接降级外网 CRM 超时整条链路失败生产接入时用 http-request 超时重试 失败分支见实验 17 容错架构采坑点来自本实验 DSL 生成与运行验证的真实记录代码模拟 API 约定、found 语义、按名传参、provider_id 变化。8. 实验文档及源码获取实验文档完整操作步骤DIFY-19插件开发入门.md源码可直接导入dify102_19_CRM查询工具.ymlDSL 目录dify-102/dsl/文章聚焦核心配置与采坑点实验文档还包含正式插件开发plugin.json/main.py/providers/tools 结构、凭据 secret-input、OpenAPI/Swagger 导入建工具、多工具组合插件包的完整示例。下一篇Dify 中级实验19综合实战——如何把 19 个实验串成一条生产级流水线 你在这个实验的场景里踩过什么坑欢迎评论区分享你的实战经验。

相关新闻

Codex AI编程助手:本地部署、功能测试与集成指南

Codex AI编程助手:本地部署、功能测试与集成指南

这次我们来看一个名为 Codex 的 AI 助手项目。从标题和网络热度来看,它被冠以“最强AI助手”的名号,并提供了从入门到进阶的完整教程和安装包。对于开发者、学生或任何希望提升编码效率的人来说,一个能本地部署、功能强大的 AI 编程助手无疑极…

2026/10/18 5:53:14 阅读更多 →
5分钟搞定Windows和Office激活:KMS_VL_ALL_AIO智能激活工具完全指南

5分钟搞定Windows和Office激活:KMS_VL_ALL_AIO智能激活工具完全指南

5分钟搞定Windows和Office激活:KMS_VL_ALL_AIO智能激活工具完全指南 【免费下载链接】KMS_VL_ALL_AIO Smart Activation Script 项目地址: https://gitcode.com/gh_mirrors/km/KMS_VL_ALL_AIO 还在为激活 Windows 和 Office 发愁?今天推荐一款开源…

2026/10/18 0:12:08 阅读更多 →
昇腾NPU智能体部署实战:算力亲和优化首token时延降低50%

昇腾NPU智能体部署实战:算力亲和优化首token时延降低50%

大家好,我是长期关注AI技术栈落地的开发者。最近在部署大模型智能体时,一个核心痛点始终绕不开:推理性能与成本。尤其是在国产化硬件平台上,如何让智能体应用跑得更快、更省资源,是很多团队面临的现实挑战。最近&#…

2026/10/17 21:03:42 阅读更多 →

最新新闻

前端任务进度卡0/1:三个静默失败点的定位与工程修复

前端任务进度卡0/1:三个静默失败点的定位与工程修复

1. 现象确认:任务卡在 0/1,但不是没跑先说明一下背景。我这边内部效率工具里有一个叫 WorkBuddy 的模块,每天会推一批小任务,其中有一个“探索优秀灵感”的任务,规则是:从推荐卡片里点开一篇内容&#xff0…

2026/10/18 9:40:32 阅读更多 →
高德地图SDK反编译解析:RouteOverlay与AMapUtil核心逻辑还原

高德地图SDK反编译解析:RouteOverlay与AMapUtil核心逻辑还原

简介:本资源是一套面向Android开发者与GIS初学者的高德地图集成实战资料包,聚焦地图标注、路线规划及定位功能的代码级实现。适用于导航类App开发、校园/园区位置服务系统搭建等场景,帮助开发者快速掌握高德地图SDK核心API调用与UI交互逻辑。…

2026/10/18 9:40:32 阅读更多 →
PHP缓存与数据库不一致:从原理到实战的解决方案详解

PHP缓存与数据库不一致:从原理到实战的解决方案详解

1. 从一次线上事故说起:缓存和数据库为什么总是“打架”这张标题我盯了很久,因为“缓存与数据库不一致”几乎是每个PHP开发者在业务量上去之后都会撞上的墙。先讲个我亲历的场景:某个电商项目的商品详情页,Redis里存了一份商品库存…

2026/10/18 9:40:32 阅读更多 →
AI辅助开题报告写作:三步生成导师认可的框架与学术诚信指南

AI辅助开题报告写作:三步生成导师认可的框架与学术诚信指南

1. 为什么你的开题报告被导师批得体无完肤,而别人的一次就过每年开题季,总有一批人被导师在文档里画满红圈:"研究意义太空泛""技术路线不清晰""创新点不明确""研究方法写得像菜单"。说句扎心的&…

2026/10/18 9:40:32 阅读更多 →
DeerFlow 2.0深度研究框架:从规划器到反思循环的SuperAgent实战

DeerFlow 2.0深度研究框架:从规划器到反思循环的SuperAgent实战

这两个月我反复在研究同一个问题:怎么让大模型不要只会“聊天”,而是真的把一份调研报告、一套竞品分析、一次技术选型评估“做完”。单纯套提示词是解决不了的,单轮问答的Agent也解决不了。直到我把 DevOps 那套“计划-执行-验证-修正”的思…

2026/10/18 9:40:32 阅读更多 →
2026课堂笔记录音工具推荐:实测5款热门APP,学生党别再踩坑了|TaoToken统一Key接入AI转写

2026课堂笔记录音工具推荐:实测5款热门APP,学生党别再踩坑了|TaoToken统一Key接入AI转写

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 9:39:32 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 0:55:02 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →