Skip to main content
Create your own
Lesson illustration

Sub-workflows: Passing Data with Execute Workflow

Hello! Welcome to the first lesson in our module on "Modular and Reusable Workflows."

In the last module, we wrapped up by looking at how to interact with NoSQL databases like MongoDB. You saw a brief preview of how a complex AI workflow might delegate a task—like saving a user's preference to a database—to a separate, dedicated workflow. This concept of breaking down large processes into smaller, reusable components is central to building robust and maintainable automations, and it's what we'll be focusing on today.

Given your background in software development, you're already familiar with the principle of "Don't Repeat Yourself" (DRY) and the importance of creating functions or modules to encapsulate logic. Sub-workflows are n8n's equivalent of this fundamental concept.

By the end of this lesson, you will be able to create and call sub-workflows using the Execute Workflow node, passing data between them.

1. The "Why": Modularity in n8n

Before we dive into the mechanics, let's establish why sub-workflows are so important. As your workflows grow in complexity, managing everything in a single, monolithic flow becomes difficult. It's harder to read, harder to debug, and harder to maintain.

Sub-workflows allow you to:

  • Abstract Complexity: Hide a complex series of steps behind a single node.
  • Promote Reusability: Build a piece of logic once (e.g., enriching user data, sending a formatted notification) and call it from many different workflows.
  • Simplify Maintenance: If you need to update a process, you only have to change it in one place—the sub-workflow—and all the parent workflows that call it will automatically use the updated version.

This modular approach is the foundation for building sophisticated systems, including the multi-agent AI systems you're interested in. In that context, you can think of a main "orchestrator" workflow that decides which specialized "agent" (sub-workflow) to call to perform a specific task.

To get a formal introduction to the concept and its benefits, let's watch the beginning of a video from n8n's official advanced course.

n8n Advanced Course (4/8) - Subworkflows

This video, 'n8n Advanced Course (4/8) - Subworkflows', provides a concise definition of sub-workflows and their primary advantages.

Watch from the beginning (00:14) until 02:40. Focus on understanding the problem that sub-workflows solve and the benefits of reusability and easier maintenance.

2. The "How": The Mechanics of a Sub-workflow

At its core, the connection between two workflows is managed by a pair of nodes:

  1. The Execute Workflow node: This node lives in the parent workflow. You configure it to call a specific sub-workflow.
  2. The Execute Workflow Trigger node: This is the starting point for the sub-workflow. It listens for calls from an Execute Workflow node and receives the data passed by the parent.

The data flow follows a clear path:

  • The input data for the Execute Workflow node (from the node that precedes it) is sent to the sub-workflow.
  • The Execute Workflow Trigger receives this data.
  • The sub-workflow executes its nodes in sequence.
  • The output data from the very last node in the sub-workflow is sent back to the parent.
  • This data becomes the output of the Execute Workflow node.
Sub-workflow Execution in n8n
This diagram shows the execution path. The main workflow proceeds through its steps, calling the reusable sub-workflow logic whenever needed.

There are some important technical considerations to keep in mind, especially regarding how data is structured.

n8n Advanced Course (4/8) - Subworkflows

Let's continue with the 'n8n Advanced Course' video to understand the technical data flow and potential pitfalls.

Watch from 02:40 to 03:46. Pay close attention to the point about standardizing key names (e.g., 'email' vs 'Email') and how the output of the sub-workflow is determined.

This is a critical point: the parent and sub-workflow must agree on a "contract" for the data they exchange. If the parent sends a field named userEmail but the sub-workflow expects email, it will fail.

3. Hands-On: Building a Reusable Data Enrichment Workflow

Let's build a practical example. A common pattern is to have a workflow that gets a list of items (e.g., users) and then needs to perform a set of repetitive actions for each item (e.g., look up their details). This is a perfect use case for a sub-workflow.

We will build a system that:

  1. A parent workflow generates a list of user emails.
  2. It loops through each user.
  3. For each user, it calls a sub-workflow to "enrich" the data.
  4. The sub-workflow will take an email, pretend to look up details, and return a full user object.

This pattern is extremely common and is a great way to handle tasks that would otherwise require complex nested loops.

Step 1: Create the Sub-workflow

First, we'll create the reusable "enrichment" logic.

  1. Create a new, blank workflow.
  2. As its trigger, add the Execute Workflow Trigger node. This workflow will now wait to be called by another.
  3. Add a Set node and connect it to the trigger. We'll use this to simulate looking up user data. Configure it as follows:
    • Set Mode to Keep Only Set. This ensures we only return the data we explicitly define.
    • Add a value:
      • Name: fullName
      • Value: Let's create a name from the email. Use an expression: {{ $json.email.split('@')[0].replace('.', ' ').replace(/\b\w/g, c => c.toUpperCase()) }}. This bit of JavaScript will take the part of the email before the "@", replace dots with spaces, and capitalize it.
    • Add another value:
      • Name: email
      • Value: Use an expression to get the email passed from the parent: {{ $json.email }}
    • Add a final value:
      • Name: enrichedAt
      • Value: Use an expression to add a timestamp: {{ new Date().toISOString() }}
  4. Save the workflow and give it a memorable name, like Sub-Enrich User Data.
  5. Look at the URL in your browser. The string of characters at the end is the Workflow ID. Copy it; you'll need it in the next step. (e.g., https://<your-n8n-instance>/workflow/SAaCiC3kH5rK1a2b -> ID is SAaCiC3kH5rK1a2b).

Your completed sub-workflow should look like this. Simple, yet powerful and reusable.

Step 2: Create the Parent Workflow

Now let's create the main workflow that will use our new module.

  1. Create another new, blank workflow.
  2. Start with a Manual trigger.
  3. Add a Set node to create our initial list of users.
    • Mode: Append.
    • Add three values, making sure to set their type to JSON:
      • Name: user1, Value (JSON): {"email": "jane.doe@example.com"}
      • Name: user2, Value (JSON): {"email": "john.smith@example.com"}
      • Name: user3, Value (JSON): {"email": "alex.jones@example.com"}
  4. Add a Split In Batches node. This node is designed to process items one by one, which is perfect for calling a sub-workflow for each item.
    • Set Batch Size to 1. This ensures our loop processes one user at a time.
  5. Add the Execute Workflow node and connect it to the Split In Batches node.
    • Workflow ID: Paste the ID of the sub-workflow you copied earlier.
  6. Activate and Execute the parent workflow.

Step 3: Inspect the Results

After the execution finishes, click on the Execute Workflow node to see its output. You will see three separate runs, one for each user. Each run's output contains the fully enriched user object (fullName, email, enrichedAt) that was constructed and returned by your sub-workflow.

You've successfully created a modular system! The parent workflow doesn't need to know how the user is enriched; it just delegates the task to the sub-workflow.

Test your understanding!

You have a sub-workflow that expects an input field named productID. Your parent workflow has a node that outputs a field named item_id. When you connect the Execute Workflow node, the sub-workflow fails. What is the most likely reason?

A) The Execute Workflow node can't handle number fields.
B) The data field names do not match (item_id vs productID).
C) The sub-workflow needs to be in the same parent workflow.

Show answer

B) The data field names do not match. This is the most common error when working with sub-workflows. The sub-workflow expected a field named productID, but it received item_id. To fix this, you would add a Set node before the Execute Workflow node to rename item_id to productID.

For a more in-depth walkthrough of building with sub-workflows, especially for complex cases like nested loops, the following community tutorial is an excellent resource.

N8n Nested Loop Tutorial - Complete End-to-End Guide

This community post, 'N8n Nested Loop Tutorial', provides a fantastic step-by-step guide on using a sub-workflow to handle nested loops, which is a more advanced version of the pattern we just built.

Skim through 'Solution 1: Using Sub-Workflow'. Notice how it breaks the problem down into a 'MAIN WORKFLOW' and a 'SUB-WORKFLOW'. This reinforces the pattern of separating concerns. You don't need to build it now, but it's a great reference for a future project.

Conclusion

In this lesson, you've learned one of the most important architectural concepts in n8n. By mastering sub-workflows, you can move from building simple, linear automations to creating complex, robust, and maintainable systems.

Key Takeaways:

  • Modularity is Key: Sub-workflows are n8n's way of creating reusable functions or modules, just like in traditional programming.
  • The Core Pair: The process is managed by the Execute Workflow node (in the parent) and the Execute Workflow Trigger (in the sub-workflow).
  • Data Contract: Data is passed from the parent to the sub-workflow's trigger. The output from the sub-workflow's last node is returned to the parent. The structure and naming of this data must be consistent.
  • Common Use Cases: Sub-workflows are ideal for encapsulating any reusable logic, such as data enrichment, custom notifications, API interactions, or handling loops over complex items.

Preview of the Next Lesson:
We've made our workflow logic reusable, but what about our configuration? You might have API keys, base URLs, or other settings that you want to use in multiple workflows. Hardcoding them in each one is not ideal. In the next lesson, we'll learn how to use workflow static data for shareable configuration, providing a clean and central way to manage these values.

Can't find a good explanation? Sign up and we'll make it for you

Sign up