Loop Node
Iteration node that processes arrays sequentially or in parallel with configurable execution modes
Loop Node
The Loop node enables iteration in your workflows. It can iterate over arrays of data (forEach) or repeat execution a specified number of times (forN). The node supports both sequential and parallel execution modes for optimal performance.
Configuration
Input Schema
The Loop node accepts one of two input modes:
forEach Mode
| Field | Type | Required | Description |
|---|---|---|---|
forEach | JsonValue[] | Yes | Array of items to iterate over |
forN | undefined | No | Must be undefined in forEach mode |
forN Mode
| Field | Type | Required | Description |
|---|---|---|---|
forN | number | Yes | Number of iterations (minimum 1) |
forEach | undefined | No | Must be undefined in forN mode |
Configuration Schema
| Field | Type | Required | Description |
|---|---|---|---|
mode | "sequential" | "parallel" | Yes | Execution mode for iterations |
Output Schema
| Field | Type | Description |
|---|---|---|
totalIterations | number | Total number of iterations executed |
iterations | JsonValue[] | Array of results from each iteration |
Basic Usage
Array Iteration (forEach)
# Process a list of users
- id: process_users
type: loop
input:
forEach: "{{ users }}"
configuration:
mode: "sequential"Count-based Iteration (forN)
# Retry an operation 3 times
- id: retry_operation
type: loop
input:
forN: 3
configuration:
mode: "sequential"Advanced Examples
# Process files in parallel for speed
- id: process_files_parallel
type: loop
input:
forEach: "{{ uploadedFiles }}"
configuration:
mode: "parallel"Use parallel mode when operations are independent and can benefit from concurrent execution. Perfect for file processing, image resizing, or API calls that don't depend on each other.
# Process orders one by one to maintain inventory state
- id: process_orders
type: loop
input:
forEach: "{{ orders }}"
configuration:
mode: "sequential"Use sequential mode when order matters or when operations depend on shared state. Essential for inventory management, account balance updates, or any workflow requiring consistency.
# Process data in batches
- id: create_batches
type: loop
input:
forN: "{{ Math.ceil(data.length / batchSize) }}"
configuration:
mode: "sequential"Use forN mode with calculated iterations for batch processing. Ideal for handling large datasets by processing them in manageable chunks.
Use Cases
Transform each item in an array:
# Resize multiple images
- id: resize_images
type: loop
input:
forEach: "{{ images }}"
configuration:
mode: "parallel"
# Child nodes would access {{ loop.current }} for each imagePerfect for applying the same operation to multiple items like image processing, data cleaning, or format conversion.
Fetch all pages of data:
# Fetch all pages from paginated API
- id: fetch_all_pages
type: loop
input:
forN: "{{ totalPages }}"
configuration:
mode: "sequential"
# Child nodes would use {{ loop.index }} for page numberIdeal for systematically fetching all data from paginated APIs where you need to iterate through page numbers.
Process large datasets in chunks:
# Process users in batches of 100
- id: batch_process_users
type: loop
input:
forN: "{{ Math.ceil(users.length / 100) }}"
configuration:
mode: "sequential"Essential for handling large datasets by breaking them into manageable chunks to avoid memory issues or API rate limits.
Implement retry mechanisms:
# Retry failed operations
- id: retry_with_backoff
type: loop
input:
forN: 5
configuration:
mode: "sequential"
# Child nodes implement exponential backoffBuild robust workflows by automatically retrying failed operations with configurable attempts and backoff strategies.
Execute independent operations concurrently:
# Send notifications to multiple channels
- id: send_notifications
type: loop
input:
forEach: "{{ notificationChannels }}"
configuration:
mode: "parallel"Maximize throughput by executing independent operations simultaneously, perfect for notifications, file uploads, or API calls.
Loop Context Variables
Available when iterating over arrays:
{{ loop.current }}- Current item being processed{{ loop.index }}- Zero-based index of current iteration{{ loop.isFirst }}- True if this is the first iteration{{ loop.isLast }}- True if this is the last iteration{{ loop.total }}- Total number of items
Perfect for array processing where you need access to both the item and its position.
Available when using count-based iteration:
{{ loop.index }}- Zero-based index of current iteration (0 to N-1){{ loop.iteration }}- One-based iteration number (1 to N){{ loop.isFirst }}- True if this is the first iteration{{ loop.isLast }}- True if this is the last iteration{{ loop.total }}- Total number of iterations
Ideal for retry logic, pagination, or any scenario requiring a specific number of iterations.
Best Practices
Use Sequential Mode When:
- Order of execution matters
- Operations modify shared state
- Each iteration depends on previous results
- Memory usage needs to be controlled
# Sequential for state-dependent operations
- id: process_transactions
type: loop
input:
forEach: "{{ transactions }}"
configuration:
mode: "sequential" # Maintain account balance consistencyUse Parallel Mode When:
- Operations are independent
- Performance is critical
- No shared state modifications
- I/O bound operations
# Parallel for independent operations
- id: validate_emails
type: loop
input:
forEach: "{{ emailList }}"
configuration:
mode: "parallel" # Each validation is independentKey optimization strategies:
- Batch size: For large arrays, consider chunking data
- Resource limits: Be mindful of memory and CPU usage
- Timeouts: Implement timeouts for long-running operations
- Error handling: Plan for partial failures in parallel mode
# Good: Controlled batch processing
- id: controlled_processing
type: loop
input:
forEach: "{{ data.slice(0, 1000) }}" # Limit batch size
configuration:
mode: "parallel"Implement robust error resilience:
# Implement error resilience
- id: resilient_loop
type: loop
input:
forEach: "{{ items }}"
configuration:
mode: "sequential"
# Child nodes should include error handling- Always plan for partial failures in parallel mode
- Use try-catch patterns in child nodes
- Consider circuit breaker patterns for external API calls
- Implement proper logging for debugging failed iterations
Integration Patterns
# Fetch data from multiple endpoints
- id: multi_endpoint_fetch
type: loop
input:
forEach: "{{ endpoints }}"
configuration:
mode: "parallel"
# Child HTTP node
- id: fetch_endpoint
type: http
input:
url: "{{ loop.current.url }}"
method: "GET"Perfect for parallel API calls, batch data fetching, and distributed service communication.
# Process multiple prompts
- id: ai_batch_processing
type: loop
input:
forEach: "{{ prompts }}"
configuration:
mode: "sequential" # Respect rate limits
# Child AI node
- id: process_prompt
type: ai
input:
prompt: "{{ loop.current }}"Ideal for bulk content processing, batch analysis, and respecting AI provider rate limits.
# Send Slack messages to multiple channels
- id: broadcast_message
type: loop
input:
forEach: "{{ channels }}"
configuration:
mode: "parallel"
# Child Slack node
- id: send_slack_message
type: slack
input:
channel: "{{ loop.current }}"
message: "{{ broadcastMessage }}"Essential for multi-channel notifications, bulk email sending, and broadcast communications.
Nested Loops
# Outer loop: Process each user
- id: process_users
type: loop
input:
forEach: "{{ users }}"
configuration:
mode: "sequential"
# Inner loop: Process each user's orders
- id: process_user_orders
type: loop
input:
forEach: "{{ loop.current.orders }}"
configuration:
mode: "parallel"Troubleshooting
Debugging Tips
# Add logging to track loop progress
- id: debug_loop
type: loop
input:
forEach: "{{ items }}"
configuration:
mode: "sequential"
# Debug child node
- id: log_iteration
type: script
input:
script: |
console.log(`Processing item ${loop.index}: ${JSON.stringify(loop.current)}`);
return loop.current;The Loop node is essential for processing collections and implementing retry logic, making it a cornerstone of data processing workflows.
Last updated on