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 item | itemごとに子を実行する | 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とコピーされた処理を減らし、変更しやすい自動化へ育てられます。

