Sea12Docs
Automation

Flow Control

Conditionals, branching, loops, parallel execution, subprocess invocation, and error boundaries.


Flow control nodes let you branch, loop, and pause execution within a process.


Conditional Node

The conditional node evaluates expressions and routes data to different output handles based on the result. It supports two modes: Conditions and Switch.

Type: conditionalNode


Conditions Mode

Evaluates one or more boolean conditions, combines them with AND/OR logic, and routes to a "true" or "false" output handle.

Config

FieldTypeRequiredDefaultDescription
modestringYes--"conditions"
operatorstringNo"and""and" or "or" to combine conditions
conditionsarrayYes--Array of condition objects
passthroughFilesboolNofalseForward files to output

Condition Object

FieldTypeDescription
idintCondition identifier
fieldstringLeft-hand value (node reference or literal)
operatorstringComparison operator
valuestringRight-hand value (node reference or literal)

Comparison Operators

OperatorTypeDescription
==EqualityEqual (with type coercion for numbers)
!=EqualityNot equal
>NumericGreater than
>=NumericGreater than or equal
<NumericLess than
<=NumericLess than or equal
containsStringField contains value as substring
startsWithStringField starts with value
endsWithStringField ends with value
matchesStringField matches regex pattern
isEmptyUnaryField is empty, nil, or zero-length (no value needed)
isNotEmptyUnaryField is not empty (no value needed)

Logical Combination

OperatorBehavior
andAll conditions must be true
orAt least one condition must be true

Reference Syntax

Within condition field and value strings, you can use:

Dot notation:

ExtractOrder.Order Request.weight_lbs

Bracket notation:

input["Extract Order"]["Order Request"]["weight_lbs"]

Quoted literals:

"5000"
"rush"

Interpolated strings (single curly braces):

"Hello {ExtractOrder.customer_name}"

Example: Route by Weight

JSON
{
  "mode": "conditions",
  "operator": "and",
  "conditions": [
    {
      "id": 1,
      "field": "input[\"Extract Order\"][\"Order Request\"][\"weight_lbs\"]",
      "operator": ">",
      "value": "10000"
    }
  ]
}

Graph:

[Extract Order] → [Conditional] ──true──→ [Large Order Handler]
                                 ──false──→ [Standard Handler]

If weight > 10000, data flows to Large Order Handler. Otherwise, to Standard Handler.

Example: Multiple Conditions with OR

JSON
{
  "mode": "conditions",
  "operator": "or",
  "conditions": [
    {
      "id": 1,
      "field": "input[\"Extract Order\"][\"Order Request\"][\"urgency\"]",
      "operator": "==",
      "value": "\"rush\""
    },
    {
      "id": 2,
      "field": "input[\"Extract Order\"][\"Order Request\"][\"urgency\"]",
      "operator": "==",
      "value": "\"emergency\""
    }
  ]
}

Routes to true if urgency is either "rush" or "emergency".

Output Handles

  • "true" -- condition(s) evaluated to true
  • "false" -- condition(s) evaluated to false

Nodes connected to the inactive handle are skipped. Their descendants are also skipped unless they have another active path.


Switch Mode

Evaluates a single field and routes to one of several named output handles based on the value.

Config

FieldTypeRequiredDefaultDescription
modestringYes--"switch"
switchFieldstringYes--Field reference to evaluate
casesarrayYes--Array of case objects
defaultCasestringNo--Default handle label if no case matches
passthroughFilesboolNofalseForward files

Case Object

FieldTypeDescription
idintCase identifier
valuestringValue to match against (node reference or literal)
labelstringOutput handle label

Example: Route by Steel Type

JSON
{
  "mode": "switch",
  "switchField": "input[\"Extract Order\"][\"Order Request\"][\"steel_type\"]",
  "cases": [
    { "id": 1, "value": "\"carbon\"", "label": "carbon_handler" },
    { "id": 2, "value": "\"stainless\"", "label": "stainless_handler" },
    { "id": 3, "value": "\"alloy\"", "label": "alloy_handler" }
  ],
  "defaultCase": "other_handler"
}

Graph:

                       ──carbon_handler──→ [Carbon Pricing]
[Conditional] ──stainless_handler──→ [Stainless Pricing]
                       ──alloy_handler──→ [Alloy Pricing]
                       ──other_handler──→ [Default Pricing]

Only the matching handle's branch executes. All other branches are skipped.

Output Handles

One handle per case label, plus the default. The handle name is the sanitized version of the case label (spaces and hyphens replaced with underscores).


Conditional Data Flow

The conditional node passes all its input data through to the active output handle. Downstream nodes receive the same data that the conditional received, so they can reference upstream nodes normally:

{{input["Extract Order"]["Order Request"]["weight_lbs"]}}

This works in nodes downstream of the conditional because ancestor data is forwarded through.


Loop Node

The loop node iterates a subgraph (a set of connected nodes) over an array of items or a set of files.

Type: loopNode


Loop Structure

A loop node has two special output handles:

  • start -- connects to the first node(s) in the loop body
  • output -- carries the aggregated results after all iterations complete

The loop body is a subgraph of nodes between the loop's start handle and nodes that connect back to the loop's end handle.

                    ┌─── start ──→ [Process Item] ──→ [Validate] ───┐
[Loop Node] ───────│                                                 │──→ end
                    └── output ──→ [Aggregate Results]

Config

FieldTypeRequiredDefaultDescription
labelstringYes--Display name
modestringNo"sequential""sequential" or "parallel"
loopSourcestringNo"data""data" or "files"
arrayFieldPathstringNoauto-detectDot-separated path to the array field
maxConcurrencyintNo10Max parallel iterations (parallel mode only)
continueOnErrorboolNofalseContinue if an iteration fails
includeParentboolNofalseInclude parent data in each iteration
passthroughFilesboolNofalseForward files

Data Loop

Iterates over an array of data items.

Array Detection

The engine finds the array to iterate over:

  1. If arrayFieldPath is set (e.g., "items" or "data.orders"), extract that field.
  2. Otherwise, auto-detect: search input data for the first array value.
  3. If no array found, wrap the entire input as a single-item array (the loop runs once).

Iteration Data

Each iteration receives:

JSON
{
  "data": { ... },        // Current array item
  "parent": { ... }       // Parent data (if includeParent is true)
}

Template reference from within the loop body:

{{input["Loop Label"]["data"]["order_id"]}}
{{input["Loop Label"]["parent"]["customer_name"]}}

Example: Process Multiple Line Items

Input to the loop:

JSON
{
  "items": [
    { "product": "Carbon Steel", "qty": 5000 },
    { "product": "Stainless Steel", "qty": 2000 },
    { "product": "Alloy Steel", "qty": 1000 }
  ]
}

Config:

JSON
{
  "mode": "sequential",
  "loopSource": "data",
  "arrayFieldPath": "items"
}

The loop body runs 3 times. In each iteration:

Iteration 0: input["Loop"]["data"] = { "product": "Carbon Steel", "qty": 5000 }
Iteration 1: input["Loop"]["data"] = { "product": "Stainless Steel", "qty": 2000 }
Iteration 2: input["Loop"]["data"] = { "product": "Alloy Steel", "qty": 1000 }

File Loop

Iterates over files from upstream nodes. Each iteration processes one file.

Iteration Data

Each iteration receives file metadata:

JSON
{
  "__loop_file_name__": "invoice-001.pdf",
  "__loop_file_link__": "https://storage.example.com/files/invoice-001.pdf",
  "__loop_file_size__": 245760,
  "__loop_file_node_key__": "Email Input",
  "__loop_file_index__": 0
}

Template reference:

{{input["Loop Label"]["__loop_file_name__"]}}
{{input["Loop Label"]["__loop_file_link__"]}}

The current file is also available as a file reference for nodes that accept files (OCR, ML Model, etc.).


Sequential vs Parallel

Sequential

  • Iterations run one at a time, in order.
  • Each iteration completes before the next starts.
  • Prior iterations' results are available via Loop Label_iter_N:
{{input["Loop Label_iter_0"]["result"]}}
{{input["Loop Label_iter_1"]["result"]}}

Use sequential when:

  • Iterations depend on previous results
  • Order matters
  • External API rate limits require serialization

Parallel

  • Multiple iterations run concurrently.
  • Concurrency limited by maxConcurrency (default 10).
  • Iteration order is not guaranteed.
  • Prior iteration results are NOT available (each iteration is independent).

Use parallel when:

  • Iterations are independent
  • Throughput matters more than order
  • Processing large batches

Continue on Error

When continueOnError: true:

  • A failed iteration is recorded but does not stop the loop.
  • Remaining iterations continue processing.
  • The loop output includes both successful and failed results.

When continueOnError: false (default):

  • The first failed iteration cancels the entire loop.
  • The execution may fail (depending on error handling upstream).

Loop Output

After all iterations complete, the loop output contains:

JSON
{
  "items": [
    {
      "index": 0,
      "success": true,
      "data": { "result": "..." }
    },
    {
      "index": 1,
      "success": true,
      "data": { "result": "..." }
    },
    {
      "index": 2,
      "success": false,
      "error": "API rate limit exceeded"
    }
  ],
  "summary": {
    "total": 3,
    "successful": 2,
    "failed": 1
  }
}

Nodes connected to the loop's output handle receive this aggregated result.


Nested Loops

Loops can be nested. The inner loop body has access to both the inner and outer loop's data:

[Outer Loop] ──start──→ [Inner Loop] ──start──→ [Process] ──→ end
                                       ──output──→ end

Each level of nesting creates its own scoped data bucket, preventing iteration data from leaking between levels.


Wait Node

Pauses execution for a configurable duration.

Type: waitNode

Config

FieldTypeRequiredDefaultDescription
labelstringYes--Display name
durationintYes--Wait time in seconds

Behavior

  • The node starts, waits for duration seconds, then completes.
  • All input data is passed through unchanged.
  • The execution timeout is paused during the wait, so a 5-minute wait doesn't consume 5 minutes of the execution timeout.
  • Files are passed through if passthroughFiles is set.

Use Cases

  • Rate limiting: Add a wait between API calls to avoid rate limits.
  • Delayed notification: Wait before sending a follow-up email.
  • Polling pattern: Combined with a conditional and loop, create a poll-wait-check cycle.

Flow Control Patterns

If-Then-Else

[Input] → [Conditional] ──true──→ [Process A] ──→ [Output]
                          ──false──→ [Process B] ──↗

Multi-Way Branch (Switch)

                         ──case_a──→ [Handler A] ──→ [Merge] → [Output]
[Input] → [Conditional] ──case_b──→ [Handler B] ──↗
                         ──default──→ [Handler C] ──↗

Loop with Conditional

[Input] → [Loop] ──start──→ [Conditional] ──true──→ [Process] → end
                                            ──false──→ [Skip] → end
           ──output──→ [Aggregate]

Sequential Processing with Wait

[Input] → [API Call 1] → [Wait 5s] → [API Call 2] → [Wait 5s] → [API Call 3] → [Output]

Parallel Fan-Out

              ──→ [Process A] ──→
[Input] ──→  ──→ [Process B] ──→ [Output]
              ──→ [Process C] ──→

All three processing nodes run in parallel (no loop needed). The output node waits for all three to complete.