2025.05.19

dify-workflow-schedule-function-node-cron-remix

DifyのワークフローをNode Cronで定期実行

Shuji

Shuji

  • Dify
  • AI
  • Remix

はじめに

Difyは現状ノーコードだけではワークフローのスケジュール実行がないようで、

公式のスケジュール機能の導入法があるものの、やや複雑に感じ、よりシンプルにできないかと思い、node.jsからタスクスケジューラをローカル環境で実行してみました。

本記事の対象としましては、すでにDifyでワークフローを組んでいるがスケジュール実行する方法を検討している方向けです。

Node Cronの導入

node-cron モジュールは、node.js 用の純粋な JavaScript で書かれたタスクスケジューラです。
このモジュールを使うことで、簡単にnode.js 内で crontab の構文を使ってタスクをスケジュールすることができます。

またnode.js実行環境であれば他でも良いのですが、本記事ではRemixでサーバーアクションを実行しています。

npm i node-cron

インストール後、以下のコードで 30分ごとに処理を実行するジョブを定義しました。

import * as cron from 'node-cron';

let job: cron.ScheduledTask;

export function startCronJob() {
  try {
    // 30分毎に実行するcron job
    job = cron.schedule('*/30 * * * *', () => {
      try {
        console.log(`[${new Date().toISOString()}] Cron job executed: 30 minute interval`);
      } catch (error) {
        console.error('Error in cron job execution:', error);
      }
    }, {
      timezone: "Asia/Tokyo"
    });

    console.log('Cron job started successfully');
  } catch (error) {
    console.error('Error starting cron job:', error);
  }
}

export function stopCronJob() {
  try {
    if (job) {
      job.stop();
      console.log('Cron job stopped successfully');
    }
  } catch (error) {
    console.error('Error stopping cron job:', error);
  }
} 

Cron構文

node-cron の構文は6フィールド構文(秒付き)をサポートしています。

# ┌────────────── 秒 (0 - 59) (オプショナル)
# │ ┌──────────── 分 (0 - 59)
# │ │ ┌────────── 時 (0 - 23)
# │ │ │ ┌──────── 日 (1 - 31)
# │ │ │ │ ┌────── 月 (1 - 12)
# │ │ │ │ │ ┌──── 曜日 (0 - 7)(日曜 = 0 または 7)
# │ │ │ │ │ │
# * * * * * *

例えば次のような指定ができます。

  • */30 * * * * → 30分毎に実行(00分, 30分)
  • 0 9 * * * → 毎日朝9時に実行
  • 0 0 12 * * 1 → 毎日朝9時に実行

    以下で、サーバー起動時にcron jobを開始すると、ジョブが定期実行されるのが確認できるかと思います。

import { startCronJob } from './utils/cron.server';

startCronJob();

Dify側の設定

今回は、定期実行を主としているので、ワークフローはコード実行するだけの単純な内容にしています。

認証情報の取得

workflow idとAPIキーを取得し、node.jsアプリの方にセットします。workflow idは公開URLではなく、ワークフローアプリのhttps://cloud.dify.ai/app/{workflow_id}/workflow となるURLから確認できます。

APIキーはバックエンドサービスAPIから作成して取得します。

APIキーを発行後にはワークフローアプリを再度公開しておきます。

ワークフローを実行する処理

DifyのAPIエンドポイントに対して、ワークフローのIDと必要なパラメータを渡してPOSTリクエストを送り、ワークフローを実行します。

        const workflowId = "xxx";
        if (!workflowId) {
          throw new Error('DIFY_WORKFLOW_ID is not set');
        }

        const response = await fetch(`https://api.dify.ai/v1/workflows/run`, {
          method: 'POST',
          headers: {
            'Authorization': `Bearer app-xxx`,
            'Content-Type': 'application/json'
          },
          body: JSON.stringify({
            workflow_id: workflowId,
            inputs: {},
            response_mode: "blocking",
            user: "abc-123"
          })
        });

        if (!response.ok) {
          const errorText = await response.text();
          console.error(`Dify API request failed: ${response.status} - ${errorText}`);
          throw new Error(`Dify API request failed: ${response.statusText}`);
        }

        const result = await response.json();
        console.log('Workflow execution result:', result);
  • エンドポイント: https://api.dify.ai/v1/workflows/run
  • Authorizationヘッダ: Difyで発行されたAPIキー(app-xxx)を使い、Bearer認証。
  • Content-Type: JSON。
  • body(リクエストボディ)には以下を含む:
    • workflow_id: 実行するワークフローID
    • inputs: ワークフローに渡す入力パラメータ(今回は空)
    • response_mode: "blocking"(完了まで待機する同期実行)
    • user: ユーザーID(トラッキング用識別子)

成功すると以下のようなレスポンスボディが返ってきます。

[0] Workflow execution result: {
[0]   task_id: 'xxx',
[0]   workflow_run_id: 'xxx',
[0]   data: {
[0]     id: 'xxx',
[0]     workflow_id: 'xxx',
[0]     status: 'succeeded',
[0]     outputs: null,
[0]     error: null,
[0]     elapsed_time: 0.1323442067950964,
[0]     total_tokens: 0,
[0]     total_steps: 3,
[0]     created_at: 1747629120,
[0]     finished_at: 1747629120
[0]   }
[0] }

Dify側のログでも成功したことを確認できました。

最後に

今回はDifyのワークフローをnode.jsで定期実行することに焦点を当てて説明しました。Difyはノーコードだけでも様々なタスクを自動化できますが、外部のアプリケーションと連携することでより可能性が広がると感じています!
これからも実際の業務を想定したパターンを試してみたいと思いますので、もし感じたことがありましたらメッセージいただけますと幸いです!