Dify-触发器

本文基于 Dify 官方文档整理,聚焦”如何让一个工作流自动跑起来”这件事。为了方便理解,全文会用一个贯穿始终的例子:每天早上 9 点,自动抓取行业新闻、用 LLM 生成一份早报摘要,推送到企业微信群。


为什么需要触发器?

当你在 Dify 画布上搭建好一个工作流后,它就像一台精密的机器,各个节点是齿轮,连线是传动带。但这台机器需要一个”启动按钮”——触发器就是那个按钮。

没有触发器,工作流只能静静地躺在画布上,等着你来手动点击”运行”。有了触发器,它就能根据你的设定自动启动,真正实现自动化。

回到我们的早报场景:你总不能每天早上 9 点准时坐在电脑前,打开 Dify 点击运行吧?这时候就需要一个触发器,到点自动帮你按下那个按钮。


触发器是什么?

触发器是工作流画布上的”开始节点”,它定义了工作流何时、以何种方式被启动。

如果你用过 Flask 框架,触发器就像是 @app.route() 装饰器——它监听某个条件,条件满足时就执行后面的逻辑。区别在于 Flask 监听的是 HTTP 请求,而 Dify 触发器监听的是时间或外部事件。

Dify 官方文档里没有独立的”hooks”模块,但触发器承担着类似的角色——当某个条件满足时,自动触发一段逻辑。

四种触发方式

Dify 提供四种主要的触发方式,可以用生活中的场景来理解:

  • 定时触发器(Schedule Trigger):像墙上的闹钟,到点就响。你设置好时间,它就按时启动工作流,不需要外部干预。
  • Webhook 触发器(Webhook Trigger):像家门口的门铃,有人按才响。外部系统发送请求到指定 URL,工作流才会启动。
  • 插件触发器(Plugin Trigger):像装了智能门禁系统,外部系统通过插件订阅事件来敲门。比如安装了 GitHub 插件后,仓库有新的 Pull Request 时会自动触发工作流,例如GitHub Actions 等事件。
  • 外部定时 + API:像你自己定闹钟,到点后亲自去按别人的门铃。你用外部调度系统(Linux cron、GitHub Actions 等)到点后调用 Dify 的 API,触发工作流。

需要注意的是,触发器只在工作流应用(Workflow App)里可用,聊天流和对话型应用用不了。每个工作流最多只能有一个定时触发器,但可以有多个 Webhook 触发器和插件触发器。


方案一:Schedule Trigger 定时触发器

这是最直接的方案:在工作流里拖一个定时触发器,配置好时间,工作流就会自动跑。

配置步骤

  1. 打开工作流应用(必须是 Workflow 工作流 类型)。
  2. 在画布上右键,选择 Add Node -> Start -> Schedule Trigger。
  3. 在右侧面板选择配置方式:Visual Picker(可视化选择)或 Cron Expression(Cron 表达式)。
  4. 配置完成后,面板下方会显示接下来 5 次的执行时间,方便确认。

对于”每天早上 9 点”这种简单需求,用 Visual Picker 就够了:频率选 Daily,时间设 09:00。

定时触发器不产生任何输出变量,它只负责启动。但每次触发时,系统变量 sys.timestamp 会被更新为本次执行的开始时间,你可以在下游节点里引用它,比如用 LLM 节点把时间格式化成”2026 年 6 月 17 日 早报”。

Cron 表达式详解

如果需求比较复杂,比如”工作日 9 点到 17 点每 15 分钟一次”,就需要用 Cron 表达式了。

Cron 表达式是 5 段,从左到右依次是:

1
2
分  时  日  月  周
* * * * *

用早报场景举例:

  • 0 9 * * * —— 每天 9 点 0 分跑(最常用,对应”每日早报”)
  • 0 9 * * MON-FRI —— 周一到周五 9 点跑(工作日早报)
  • */15 9-17 * * MON-FRI —— 工作日 9 点到 17 点,每 15 分钟一次(适合实时舆情监控)
  • 0 0 1 * * —— 每月 1 号 0 点跑(月度汇总)
  • 0 17 L * * —— 每月最后一天 17 点跑(L 表示 last)

几个特殊字符的含义:

  • * 表示”每”。写在”时”的位置就是”每小时”。
  • , 表示”和”。1,3,5 写在”周”的位置就是”周一、周三、周五”。
  • - 表示”到”。9-17 写在”时”的位置就是”9 点到 17 点”。
  • / 表示”每隔”。*/15 写在”分”的位置就是”每 15 分钟”。
  • L 表示”最后一个”。写在”日”的位置就是”本月最后一天”。

还有几个预定义的快捷写法:

  • @daily 等价于 0 0 * * *(每天 0 点)
  • @hourly 等价于 0 * * * *(每小时整点)
  • @weekly 等价于 0 0 * * 0(每周日 0 点)
  • @monthly 等价于 0 0 1 * *(每月 1 号 0 点)
  • @yearly 等价于 0 0 1 1 *(每年 1 月 1 号 0 点)

Dify 的 Cron 表达式输入框旁边有个”用 LLM 生成”的按钮,你直接用自然语言说”每个工作日早上 9 点”,它会帮你生成表达式。

测试方法

定时触发器有两种测试方式:

  • Run this step(单步运行):立刻执行一次,忽略你配的定时。适合调试工作流本身。
  • Test Run(整体试跑):会真的等到下一个定时点才跑。适合验证时间配置是否正确。

调试阶段用第一种,确认时间配置用第二种。


方案二:外部定时 + Workflow Run API

如果你是自部署 Dify,或者想把定时逻辑放在自己的服务器上,可以用外部定时器到点后调用 Dify 的 API 来触发工作流。

这种方式和方案一的本质区别是:方案一的闹钟装在 Dify 内部,方案二的闹钟装在外部,到点后外部”敲门”叫醒 Dify。

方案二的好处是定时逻辑完全在你手里,可以用任意语言、任意调度系统,甚至接入更复杂的企业级调度(如 Airflow)。坏处是你得自己维护一个外部服务。

Workflow Run API 调用详解

核心接口是 POST /workflows/run,用于执行一个已发布的工作流。调用前必须先在 Dify 里把工作流”发布”,否则会报错。

请求示例

1
2
3
4
5
6
7
8
9
10
11
curl --request POST \
--url https://api.dify.ai/v1/workflows/run \
--header 'Authorization: Bearer app-你的API密钥' \
--header 'Content-Type: application/json' \
--data '{
"inputs": {
"topic": "人工智能"
},
"response_mode": "blocking",
"user": "cron-job-001"
}'

关键参数说明:

  • inputs:工作流的输入变量,键值对形式。变量名要和工作流开始节点里定义的一致。如果没有输入变量,传 {}
  • response_mode:响应模式,有 blocking 和 streaming 两种,下面会详细说明。
  • user:用户标识符,必填。用于区分是谁触发的这次执行,比如定时任务就用 cron-job-001

响应示例(blocking 模式)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"task_id": "c3800678-a077-43df-a102-53f23ed20b88",
"workflow_run_id": "fb47b2e6-5e43-4f90-be01-d5c5a088d156",
"data": {
"id": "fb47b2e6-5e43-4f90-be01-d5c5a088d156",
"workflow_id": "7c3e33d4-2a8b-4e5f-9b1a-d3c6e8f12345",
"status": "succeeded",
"outputs": {
"result": "今日早报:人工智能领域动态..."
},
"error": null,
"elapsed_time": 1.23,
"total_tokens": 150,
"total_steps": 3,
"created_at": 1705407629,
"finished_at": 1705407630
}
}
  • workflow_run_id:本次执行的唯一 ID,后续查日志、查详情都用它。
  • data.status:执行状态,succeeded / failed / stopped
  • data.outputs:工作流最终输出的变量,对应结束节点里定义的输出。

blocking 和 streaming 的区别

这两个模式是 Dify API 里最容易混淆的概念,可以用”取快递”来理解:

  • blocking(阻塞模式):你下单后站在门口等,快递员把东西送到手你才走。API 调用会一直等,直到工作流跑完才返回最终结果。
  • streaming(流式模式):你下单后,快递员每装好一箱就给你发个短信,你边收短信边看进度。API 会持续返回一个个事件。

对于定时任务,绝大多数情况用 blocking 就够了——你只关心最终结果,不需要看中间过程。Dify Cloud 上 blocking 模式有 100 秒的超时限制,如果工作流跑得超过 100 秒,就得改用 streaming,或者把工作流拆短。

Python 脚本示例

下面是一个 Linux cron + Python 的完整例子,每天早上 9 点调用 Dify 工作流生成早报。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import requests
import json
from datetime import datetime

DIFY_API_URL = "https://api.dify.ai/v1/workflows/run"
DIFY_API_KEY = "app-你的API密钥"

def run_brief_workflow():
headers = {
"Authorization": f"Bearer {DIFY_API_KEY}",
"Content-Type": "application/json"
}
payload = {
"inputs": {
"topic": "人工智能",
"date": datetime.now().strftime("%Y-%m-%d")
},
"response_mode": "blocking",
"user": "cron-job-001"
}

response = requests.post(DIFY_API_URL, headers=headers, json=payload, timeout=120)
result = response.json()

if result.get("data", {}).get("status") == "succeeded":
print("早报生成成功:")
print(result["data"]["outputs"])
else:
print("早报生成失败:", result)

if __name__ == "__main__":
run_brief_workflow()

Linux cron 配置

1
2
3
crontab -e

0 9 * * * /usr/bin/python3 /path/to/daily_brief.py >> /path/to/brief.log 2>&1

注意时区问题:Linux 服务器默认用系统时区,Dify Cloud 默认是 UTC。如果你的服务器是北京时间(UTC+8),而 Dify 显示的执行时间是 UTC,记得换算。

更省事的方案:dify-schedule

社区有个开源项目 dify-schedule,它直接用 GitHub Actions 当定时器,到点调用 Dify 工作流,还内置了企业微信、钉钉、飞书、邮件等多种通知渠道。

用法很简单:

  1. Fork 这个仓库。
  2. 在仓库的 Settings -> Secrets 里配置:
    • DIFY_TOKENS:你的工作流 API Key(多个用 ; 分隔)。
    • DIFY_BASE_URL:Dify API 地址,默认 https://api.dify.ai/v1
    • DIFY_INPUTS:工作流输入变量,JSON 格式。
  3. 到 Actions 页面启用 workflow。
  4. (可选)配置通知渠道的 Secret,比如 WEIXIN_WEBHOOK 推送到企业微信。

这个方案零运维、免费(GitHub Actions 公开仓库免费),适合个人或小团队。缺点是执行时间受 GitHub Actions 调度影响,可能延迟几十秒到几分钟,不适合对时间精度要求高的场景。


方案三:Webhook Trigger Webhook 触发器

前面两种方案都是”到点就跑”,但有些场景是”事情发生了才跑”:

  • 用户在企业微信群里 @机器人提问,机器人立刻回答
  • GitHub 仓库收到新的 Issue,自动分类并指派
  • 电商系统收到新订单,自动生成发货单

这些场景没有固定时间,事件来了才触发。Webhook 触发器就是干这个的。

配置步骤

配置流程比定时触发器复杂一些,但思路清晰:

第一步:添加节点

在工作流画布右键,选择 Add Node -> Start -> Webhook Trigger。添加后,Dify 会给你生成一个唯一的 Webhook URL,这就是外部系统”敲门”的地址。自部署环境下,这个 URL 的前缀可以通过环境变量 TRIGGER_URL 修改,必须保证外部系统能访问到,默认是http://localhost,自动拼成的Webhook URL示例:http://localhost/triggers/webhook/kJNn5412NCXYXC6nR5hgg5sl

第二步:配置 HTTP 方法

选择这个 URL 接受哪种 HTTP 方法(GET / POST / PUT 等)。必须和外部系统发请求时用的方法一致,否则请求会被拒绝。一般用 POST。

第三步:配置 Content-Type

选择请求体的格式(application/json 最常见)。同样必须和外部系统发的一致。

第四步:定义要提取的参数

这是关键。外部系统发来的请求里会带一堆数据,你要告诉 Dify “我要从里面拿哪几个字段”。每个提取的参数会变成一个输出变量,下游节点可以直接引用。

参数可以从三个地方提取:

  • Query Parameters(查询参数):URL 里 ? 后面的键值对。比如 ?userID=u-456&source=email,可以提取 userIDsource。适合放简单的过滤条件。
  • Header Parameters(请求头):请求头里的字段,比如 Authorization。注意:请求头里的连字符 - 会被自动转成下划线 _
  • Request Body Parameters(请求体):请求体里的核心数据,比如订单详情、消息内容。这是最常用的提取来源。

每个参数要设置:

  • 变量名:必须和请求里对应的 key 名一模一样。
  • 数据类型:String / Number / Boolean / Object / File 等(请求头参数只能是 String)。
  • 是否必填:勾选后,如果请求里没带这个参数,工作流不会触发。

第五步:配置响应(可选)

工作流被成功触发后,Dify 默认返回 200 OK。如果外部系统要求特定的响应格式(比如企业微信要求返回特定 JSON),可以自定义状态码和响应体。

调用示例

假设我们要做的是”用户在企业微信 @机器人时,触发工作流回答问题”。

Dify 端配置:

  • HTTP 方法:POST
  • Content-Type:application/json
  • 提取的请求体参数:
    • msg_type:String,必填
    • content:String,必填
    • user_id:String,必填

外部系统(模拟企业微信)发请求:

1
2
3
4
5
6
7
8
curl --request POST \
--url https://api.dify.ai/v1/workflows/webhook/你的webhook-id \
--header 'Content-Type: application/json' \
--data '{
"msg_type": "text",
"content": "今天有什么AI新闻?",
"user_id": "user-001"
}'

请求发出后,Dify 会立刻返回 200 OK,同时工作流开始执行。下游节点就可以用 {{content}} 引用用户的问题,用 LLM 生成回答,再用 HTTP Request 节点把回答推回企业微信。

测试方法

未发布的 Webhook 触发器,必须先点 “Run this step”(运行此步骤) 或整体试跑(测试运行),让它进入”监听状态”,才能收到外部请求。否则你从外部发再多请求,Dify 都不会响应。

测试流程:

  1. 在 Dify 里点 “Run this step”(运行此步骤),触发器开始监听。
  2. 用 curl 或 Postman 向测试用的 Webhook URL 发请求。
  3. 回到 Dify,在触发器的 Last Run 标签页查看收到的请求数据。
  4. 根据实际收到的数据,调整你要提取的参数。

官方建议测试时始终用 test webhook URL,把测试数据和生产数据隔离开。


方案四:Plugin Trigger 插件触发器

前面的 Webhook 触发器需要你手动配置外部系统的回调地址,而插件触发器更进一步——它通过官方或社区开发的触发器插件,帮你自动完成外部系统的事件订阅。

插件触发器就像是给你的工作流装了一套智能门禁系统。安装好插件后,门禁系统会自动连接到外部系统(比如 GitHub、飞书、企业微信),当外部系统发生特定事件时,门禁系统会自动开门,让工作流开始执行。

插件触发器和 Webhook 触发器的区别

用 GitHub 场景举例:

  • Webhook 触发器:你需要在 GitHub 仓库的 Settings -> Webhooks 里手动添加 Dify 的 Webhook URL,选择要监听的事件,然后在 Dify 里配置要提取的参数。
  • 插件触发器:你安装 GitHub 触发器插件后,在 Dify 里授权,插件会自动帮你在 GitHub 上创建 Webhook,你只需要选择要订阅的事件(如 Pull Request、Push、Issue),然后把对应的插件触发器拖到工作流画布上即可。

插件触发器是 Webhook 触发器的”封装版”,省去了你手动配置外部系统 Webhook 的步骤,同时还提供了标准化的事件参数提取。

配置步骤

第一步:添加节点

在工作流画布右键,选择 Add Node -> Start,然后从可用的插件触发器中选择,或者在 Dify Marketplace 搜索更多。

如果没有合适的触发器插件,你可以:

  • 向社区请求开发。
  • 自己开发一个触发器插件。
  • 改用 Webhook 触发器。

第二步:选择或创建订阅

每个插件触发器都需要关联一个订阅。订阅本质上是一个 Webhook,用于监听外部系统的事件。

一个工作流可以有多个插件触发器。如果这些触发器分支共享相同的下游节点,可以添加 Variable Aggregator 节点把它们汇合,避免重复画节点。

创建订阅有三种方式:

  • OAuth 自动创建:选择要订阅的事件,Dify 通过 OAuth 授权自动在外部系统创建 Webhook。很多热门插件都预置了默认的 OAuth 客户端,一键授权即可。
  • API Key 自动创建:输入 API Key 等认证信息,Dify 自动在外部系统创建 Webhook。
  • 手动创建:使用 Dify 提供的回调 URL,自己在外部系统创建 Webhook。

第三步:配置其他设置

根据插件的要求,配置必要的参数。插件触发器的输出变量由插件定义,不能修改。

示例:GitHub Pull Request 触发器

假设你想在 GitHub 仓库收到新的 Pull Request 时,自动触发工作流进行代码审查。

配置步骤:

  1. 在工作流画布添加 GitHub Pull Request 插件触发器。
  2. 选择 Create with OAuth,使用默认 OAuth 客户端。
  3. 在弹出的 GitHub 授权页面上,授予 Dify 访问权限。
  4. 选择订阅的仓库和事件(如 Pull Request -> opened)。
  5. 点击创建,插件会自动在 GitHub 上创建 Webhook。

配置完成后,当有人打开 Pull Request 时,工作流会自动触发,插件触发器会输出 Pull Request 的详细信息(标题、作者、分支、文件变更等),下游节点可以直接使用这些变量。

测试方法

未发布的插件触发器,必须先点 Run this step 或整体试跑,让它进入”监听状态”,才能捕获订阅的事件。否则即使外部系统发生了事件,工作流也不会触发。


四种方案怎么选?

回到我们的早报场景,给一个明确的选型建议:

首选方案一(Schedule Trigger),理由:

  • 需求就是”到点跑”,没有外部事件触发。
  • 不想维护外部服务器。
  • 配置最简单,5 分钟搞定。

什么时候用方案二(外部定时 + API)

  • Dify 是自部署的,且定时触发器功能受限或不可用。
  • 定时逻辑很复杂,比如”每月最后一个工作日 9 点”这种 Cron 不好表达的。
  • 需要和企业级调度系统(Airflow、DolphinScheduler)集成。
  • 需要在调用前后做额外处理(比如先从数据库取参数,调用后写日志到 ELK)。

什么时候用方案三(Webhook Trigger)

  • 触发时机不是”到点”,而是”事件发生”。
  • 外部系统支持 Webhook,但没有现成的 Dify 触发器插件。
  • 需要完全自定义请求参数的提取逻辑。
  • 比如早报场景升级:不再固定 9 点推,而是”每当有重要新闻入库,立刻生成快讯推送”——这时候就用 Webhook,让新闻系统入库时调你的 Webhook URL。

什么时候用方案四(Plugin Trigger)

  • Dify Marketplace 上有对应外部系统的触发器插件。
  • 想省去手动配置外部系统 Webhook 的步骤。
  • 需要标准化的事件参数提取,不想自己解析请求体。
  • 比如”GitHub 有新的 Pull Request 时自动触发代码审查”、”飞书收到新消息时自动回复”这类场景,用插件触发器比 Webhook 触发器更便捷。

四种方案能混着用吗?

能。一个工作流可以有多个触发器并行存在(但定时触发器最多一个)。比如同一个早报工作流,可以同时挂:

  • 一个 Schedule Trigger:每天 9 点定时推。
  • 一个 Webhook Trigger:管理员随时手动触发”立即推送”。
  • 一个 Plugin Trigger:通过飞书插件,管理员在飞书里发指令触发推送。

多个触发器共享同一套下游节点。如果不同触发器分支需要汇合,用 Variable Aggregator(变量聚合器)节点把各分支的变量收拢,避免重复画节点。

注意:Dify Cloud 上触发器执行次数有配额限制,不同套餐不一样。工作区所有者和管理员可以在 Settings -> Billing 里查看剩余配额。Sandbox 套餐每个工作流最多 2 个触发器。


常见问题与排查

定时触发器配好了但没执行

按这个顺序排查:

  1. 触发器是否已发布:在 Quick Settings 侧边栏能看到并启用,才算发布生效。没发布的触发器不会执行。
  2. 时区是否对得上:Dify Cloud 默认 UTC,你配的”9 点”可能是 UTC 9 点(北京时间 17 点)。自部署看服务器时区。
  3. 看 Logs:工作流应用的 Logs 里会显示每次执行的触发来源,确认是不是定时触发器触发的。
  4. 配额是否用完:Dify Cloud 上触发器执行有配额,用完了就不会触发。

Webhook 触发器收不到请求

  1. 是否处于监听状态:未发布的触发器,必须先 Run this step 才能收请求。
  2. HTTP 方法是否匹配:你配的是 POST,外部发的 GET,会被拒绝。
  3. Content-Type 是否匹配:你配的是 application/json,外部发的 form-data,会被拒绝。
  4. URL 是否可达:自部署环境下,TRIGGER_URL 必须是外部系统能访问到的公网地址。本地开发可以用 ngrok 做内网穿透。
  5. 必填参数是否齐全:少一个必填参数,工作流不会触发。

API 调用返回 404 或 401

  • 401 Unauthorized:API Key 错了,或者没加 Bearer 前缀。注意是 Authorization: Bearer app-xxxx,不是直接 app-xxxx
  • 404 Not Found:工作流没发布,或者 URL 写错了。确认工作流已发布,且 URL 是 https://api.dify.ai/v1/workflows/run(自部署换成你的域名)。
  • 400 Bad Request:请求体格式不对,或者 inputs 里的变量名和工作流定义的对不上。

插件触发器收不到事件

  1. 是否已创建订阅:插件触发器必须关联一个有效的订阅,订阅本质上是一个 Webhook。没有订阅或订阅已过期,就收不到事件。
  2. 订阅是否包含该事件:创建订阅时需要选择要监听的事件类型。如果当前事件不在订阅列表中,工作流不会触发。建议创建订阅时勾选所有可用事件。
  3. OAuth 授权是否有效:如果使用 OAuth 方式创建订阅,授权可能已过期或被撤销。可以在插件详情页重新授权。
  4. 是否处于监听状态:未发布的触发器,必须先点 Run this step 才能捕获事件。
  5. 检查请求日志:在订阅的手动设置页面,可以查看请求日志,确认外部系统是否发送了请求,以及 Dify 是否正确响应。

总结

最后用我们的早报场景把四种方案串一遍:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
场景:每天 9 点生成行业早报推送到企业微信

方案一:Schedule Trigger(推荐)
画布上拖一个定时触发器 → 配 Cron "0 9 * * *" → 工作流自动跑
优点:零代码,Dify 内部搞定
缺点:定时逻辑受限,配额受限

方案二:外部定时 + Workflow Run API
Linux cron 到点 → curl 调 POST /workflows/run → 工作流执行
优点:定时逻辑完全自主,可集成企业调度
缺点:要自己维护外部服务

方案三:Webhook Trigger(本场景不适用,举例升级版)
升级场景:有重要新闻入库时立刻推送
新闻系统入库 → POST 到 Webhook URL → 工作流执行
优点:事件驱动,实时性高
缺点:需要外部系统主动调用,配置较复杂

方案四:Plugin Trigger(本场景不适用,举例其他场景)
适用场景:GitHub 有新 PR 时自动触发代码审查
安装 GitHub 插件 → OAuth 授权 → 订阅 PR 事件 → 工作流执行
优点:配置简单,标准化事件参数
缺点:依赖插件生态,没有插件的系统无法使用

记住一个核心区别:

  • 定时触发器 = 闹钟:到点响。
  • Webhook 触发器 = 门铃:有人按才响。
  • 插件触发器 = 智能门禁:外部系统通过插件自动触发。
  • 外部定时 + API = 你自己定闹钟去按别人的门铃

选哪种,看你的”响铃条件”是时间还是事件,以及外部系统是否有现成的触发器插件。


参考文档