n8nのSub-workflowを理解する|Workflowを分割・再利用する設計の基本

「n8nのSub-workflowを理解する|Workflowを分割・再利用する設計の基本」の内容を表す技術イラスト

n8nで自動化を育てていくと、最初は小さかったWorkflowへ変換、検証、通知、保存などの処理が増えていきます。すべてを1本へ追加し続けると、どこを変更すればよいか分かりにくくなり、同じ処理を別のWorkflowへコピーする場面も増えます。

そこで役立つのがSub-workflowです。

親Workflow
→ 共通処理をSub-workflowとして呼び出す
→ 処理結果を受け取る
→ 親Workflow固有の処理を続ける

Sub-workflowは、単にcanvasを小さくする機能ではありません。処理の責務を分け、入力と出力を契約として定義し、複数のWorkflowから同じ機能を再利用するための仕組みです。

目次

今日の到達点

  • 親WorkflowとSub-workflowの役割を説明できる
  • Execute Sub-workflowとExecute Sub-workflow Triggerの接続を理解できる
  • input/output契約を明示して共通処理を切り出せる
  • 完了待ちとitem単位の実行モードを使い分けられる
  • 過剰分割や密結合を避ける判断基準を持てる

Sub-workflowとは何か

Sub-workflowは、別のWorkflowから呼び出されるWorkflowです。呼び出す側を親Workflow、呼び出される側をSub-workflowとして考えます。

n8nでは、親側にExecute Sub-workflow nodeを置き、子側の先頭にExecute Sub-workflow Trigger nodeを置きます。Trigger nodeはnode検索時に「When Executed by Another Workflow」と表示される場合があります。

親Workflow
Manual Trigger
→ Edit Fields
→ Execute Sub-workflow
→ 後続処理

Sub-workflow
Execute Sub-workflow Trigger
→ 共通変換
→ 最終node

親から渡したデータは、子のTriggerへ入力されます。子の最終nodeが出力したデータは、親のExecute Sub-workflow nodeへ戻ります。

この関係は関数に似ています。

入力を渡す
→ 決められた責務を実行する
→ 結果を返す

ただし、Sub-workflowは独立したWorkflowであり、設定、権限、executionも確認対象になります。「canvas上のnode群を折りたたむ」だけの機能ではありません。

Workflowを分割する目的

共通処理を再利用する

たとえばWebhook、Schedule Trigger、手動実行という異なる入口から、同じセンサーデータ正規化を使うとします。

Webhook Workflow ─┐
Schedule Workflow ├→ Normalize Sensor Data
Manual Workflow  ─┘

各Workflowへ同じ変換nodeをコピーすると、仕様変更のたびに複数箇所を直す必要があります。共通変換をSub-workflowへ集約すれば、呼び出し側は同じinput契約で利用できます。

責務を明確にする

長いWorkflowでは、取得、変換、判定、通知、保存が混ざりやすくなります。責務単位に分けると、「このWorkflowは何を保証するのか」を説明しやすくなります。

親:処理順序と業務判断を管理する
子:センサーデータを共通形式へ正規化する

変更とテストの範囲を小さくする

入出力が明確なSub-workflowは、特定の入力を与えて出力を確認できます。変更時も、その責務と呼び出し元への影響へ調査範囲を絞れます。

分割前に責務を1文で定義する

切り出す前に、Sub-workflowの役割を1文で書きます。

良い例:

機器名とMPa単位の圧力を受け取り、名称を正規化してkPa単位を追加する。

曖昧な例:

データをいろいろ処理する。

1文で説明できない場合、責務が広すぎるか、異なる処理が混ざっている可能性があります。反対に、1 fieldの名前変更だけをすべて別Workflowにすると、分割による管理コストの方が大きくなります。

切り出し候補になりやすいのは次のような処理です。

  • 複数Workflowで同じ規則を使うデータ正規化
  • 共通の検証や分類
  • 共通形式の通知本文作成
  • 複数nodeからなる外部サービス連携
  • 独立して入力と出力を検証できる業務処理

input契約を定義する

Sub-workflowの入口では、何を受け取るかを明示します。Execute Sub-workflow TriggerのInput data modeでは、現在の公式仕様として次の方法があります。

  • Define using fields below:field名と型を個別に定義する
  • Define using JSON example:JSON例から期待する構造を示す
  • Accept all data:入力を限定せず受け取る

学習では、fieldを明示する方式が理解しやすいでしょう。共通変換を次の契約にします。

{
  "machine_name": "Pump A",
  "pressure_mpa": 12
}

少なくとも次を決めます。

  • 必須field名
  • 値の型
  • 単位や形式
  • 欠損時の扱い
  • 1回に渡すitem数

pressure_mpaという名前なら単位を推測しやすくなります。単なるpressureでは、Pa、MPa、barのどれか分かりません。Sub-workflowを再利用するほど、暗黙の前提ではなくfield名と契約が重要になります。

Accept all dataは柔軟ですが、Sub-workflow側が欠損、型違い、予期しない構造を処理する責任を負います。再利用部品として使うなら、必要な入力を明示できないか先に検討します。

output契約を定義する

n8nでは、Sub-workflowの最終nodeの出力が親Workflowへ返ります。そのため、最後のnodeを「外へ公開する出力境界」として設計します。

今回の共通変換では、次の形を返すと決めます。

{
  "machine": "Pump A",
  "pressure_mpa": 12,
  "pressure_kpa": 12000,
  "normalized": true
}

output契約では次を確認します。

  • 返すfield名と型
  • 入力と出力のitem数
  • 元fieldを残すか
  • 成功状態をどう表すか
  • エラーを通常データとして返すのか、executionを失敗させるのか

内部nodeの途中結果をすべて返すと、呼び出し側がSub-workflowの内部構造へ依存します。親が必要とするfieldだけを安定した形で返すと、子の内部実装を変更しやすくなります。

最小の2Workflow構成

Sub-workflowを作る

新しいWorkflowを作り、Execute Sub-workflow Triggerを先頭へ置きます。Input data modeで次のfieldを定義します。

machine_name: String
pressure_mpa: Number

後続のEdit Fieldsで出力を整えます。

machine: {{ $json.machine_name }}
pressure_mpa: {{ $json.pressure_mpa }}
pressure_kpa: {{ $json.pressure_mpa * 1000 }}
normalized: true

この変換だけならCode nodeは不要です。標準nodeで入力と出力を画面から確認できます。

Sub-workflowを保存します。公式ドキュメントでは、Sub-workflow内にnode設定エラーがある場合、親Workflowから実行できないと説明されています。

親Workflowから呼び出す

親Workflowは次の最小構成にします。

Manual Trigger
→ Edit Fields - Sample Input
→ Execute Sub-workflow - Normalize Sensor Data
→ Edit Fields - Use Normalized Output

Execute Sub-workflow nodeのSourceをDatabase、選択方法をFrom listにすると、利用可能なWorkflowを選べます。子側で入力fieldを定義していれば、親側に入力欄が表示され、前nodeの値をmapできます。

{{ $json.machine_name }}
{{ $json.pressure_mpa }}

実行後は、親のExecute Sub-workflow nodeからView sub-executionを開けます。Sub-workflow側のexecutionからも親executionへ戻れるため、親子のどちらで期待と異なるデータになったかを追跡できます。

実行モードと完了待ち

Execute Sub-workflow nodeには、入力itemsを子へ渡す単位を決めるModeがあります。

Mode動作向く処理
Run once with all items全itemsを1回の子executionへ渡す全体集計、まとめて変換
Run once for each itemitemごとに子を実行する1件ごとに独立した処理

5 itemsをRun once for each itemで渡せば、Sub-workflowは5回呼ばれます。処理時間、executionの追跡、外部APIのrate limitへ影響するため、「個別にできる」ことと「個別にすべき」ことを分けて考えます。

Wait for Sub-Workflow Completionを有効にすると、親は子の完了を待ってから先へ進みます。子のoutputを次で使う場合は、完了待ちが必要です。

無効にすると親は子の完了を待たずに進むため、結果を使わない通知受付や非同期処理のような用途に向きます。ただし、親が成功しても子の処理完了まで保証したとは限りません。監視と失敗時の扱いを別途設計します。

呼び出し権限を狭める

Sub-workflowのWorkflow settingsには、どのWorkflowから呼び出せるかを制御する設定があります。公式ドキュメントでは「This workflow can be called by」として案内されています。

再利用可能だからといって、すべてのWorkflowから無条件に呼び出せる必要はありません。内部更新や外部送信を含むSub-workflowでは、とくに呼び出し元を必要な範囲へ限定します。

環境、n8nバージョン、project構成によって表示される選択肢が異なる場合があります。実環境のWorkflow settingsで確認してください。

既存Workflowから切り出す方法

現在のn8n公式ドキュメントでは、既存canvas上で選択したnodesをSub-workflowへ変換する機能も案内されています。また、Execute Sub-workflow nodeのWorkflow選択から新しいSub-workflowを作成できます。

自動変換は接続の作成を助けますが、責務や契約まで自動で正しく決めるわけではありません。変換後に必ず次を確認します。

  • 子へ渡すinputが必要十分か
  • 子の最終outputが親の期待と一致するか
  • 子が親の特定node名や内部fieldへ依存していないか
  • Credentialsや呼び出し権限が適切か
  • 親子executionを追跡できるか

よくある失敗

canvasを短くするだけで分割する

見た目のnode数だけで切ると、責務の途中で境界ができ、親子間を往復するデータが増えます。「何を入力し、何を保証して返すか」で境界を決めます。

親の内部構造へ依存する

Sub-workflowが特定の親node名や、親だけに存在する一時fieldを前提にすると、ほかのWorkflowから再利用できません。子が必要とする値はinput契約として渡します。

Accept all dataのまま契約を決めない

最初の試作には便利ですが、呼び出し元ごとに異なるJSONを受けると、子側の条件分岐が増えます。安定後は入力fieldやJSON例で境界を明示できないか見直します。

outputに内部データを出しすぎる

内部fieldを親が使い始めると、子の実装変更が呼び出し元を壊します。公開するoutputを絞り、意味の安定したfield名を使います。

小さく分けすぎる

1〜2個の単純nodeまで別Workflowにすると、移動、権限、execution調査の負担が増える場合があります。再利用性、独立した責務、変更頻度、テスト価値があるかで判断します。

呼び出しが深くなる

親が子を呼び、子がさらに別の子を呼ぶ構成を重ねると、全体の処理順序と失敗箇所を追いにくくなります。階層を増やす前に、責務の境界と親子executionの追跡方法を決めます。

実務での設計チェック

Sub-workflowを小さな内部APIとして扱うと、設計項目を整理しやすくなります。

responsibility: Normalize sensor data
input:
  machine_name: string
  pressure_mpa: number
output:
  machine: string
  pressure_mpa: number
  pressure_kpa: number
  normalized: boolean
execution:
  mode: all_items
  wait_for_completion: true
ownership:
  callers: approved_workflows

変更するときは、内部nodeだけでなく契約への影響を確認します。field名や型を変える場合は、呼び出し元を同時に調査します。互換性を保てない変更では、新しいfieldを追加して移行期間を設ける方法もあります。

今日の実習で確認すること

  • 既存Workflowから共通変換処理を1つ選ぶ
  • 切り出す責務を1文で定義する
  • Execute Sub-workflow Triggerでinput fieldを明示する
  • Sub-workflowの最終nodeでoutput fieldを明示する
  • 親WorkflowのExecute Sub-workflowから呼び出す
  • 親子executionのリンクと実際の入出力を確認する
  • 再利用できる責務か、過剰分割になっていないかを記録する

まとめ

Sub-workflowは、Workflowを責務単位へ分け、明示したinput/outputを通じて再利用する仕組みです。

切り出す責務を決める
→ input契約を定義する
→ Sub-workflowで処理する
→ 最終nodeでoutput契約を作る
→ 親から呼び出す
→ 親子executionで結果を追う

重要なのは、Workflowを何本に分けたかではありません。Sub-workflowが何を受け取り、何を保証して返すのかを説明できることです。

共通処理を切り出すときは、再利用性だけでなく、責務、testability、権限、executionの追跡、変更時の影響まで考えます。適切な境界を作れば、巨大Workflowとコピーされた処理を減らし、変更しやすい自動化へ育てられます。

参考資料

参考になったらシェアしてください
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

機械設計・油圧・CAD・Python・AIなど、ものづくりに関わる技術を扱っています。工学知識を整理・構造化し、設計や自動化に再利用できる形へ変えていくことを目指しています。

目次