Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.twine.se/llms.txt

Use this file to discover all available pages before exploring further.

A Flow Engine run starts at the graph’s root node and follows the connections between nodes until the graph has no more work to do. Along the way, nodes can branch execution, iterate over lists, bail out of a path, or abort the run entirely. Understanding the traversal rules and the error-handling policies is essential for building flows that behave predictably when things go wrong.

Traversal

Execution begins at the root node. For each node reached, the engine runs the node’s operation, then picks the next node by following its outgoing connections. A node is never run twice in a single run. When there are no more reachable nodes to visit, the run finishes. Unlike the Data Engine’s graph model - where reaching an end node terminates evaluation and returns a value - a flow has no single “output” in the same sense. A flow finishes when its graph is exhausted. The run’s result is captured in the token’s persisted assigns and in the logs.

Branching with FlowSwitch

The FlowSwitch node directs execution down one of several alternative paths based on a value computed by an inner graph. Each branch out of the switch is labelled; when the switch runs, the inner graph emits a branch name, and only the matching branch is followed. The other branches are pruned from the traversal and their nodes do not run. This is how a flow reacts to conditions - “if the employee is new, create them in the target system, otherwise update the existing record” becomes a switch with two branches.

Looping with FlowEach

The FlowEach node iterates a list, running a subgraph once per element. The subgraph is attached to the node’s loop ports and has its own root. Inside the subgraph, assigns written by one iteration are visible to later nodes in that iteration, but each iteration starts from the same token state as the previous one - iterations do not accumulate through the loop body unless the body explicitly writes to an accumulator assign. When the loop has visited every element, execution returns to the parent graph and continues from the FlowEach node.

Error handling

When a step run by a FlowAction fails, what happens next is controlled by the action’s on error policy:
  • halt_flow (default): the whole run aborts. No further nodes are executed and the FlowRun is finalised with status aborted. This is the safest default - a broken step does not cascade into partial writes downstream.
  • halt_branch: the current path stops, but other paths in the graph continue. Useful when a flow does several independent things and one of them failing should not stop the others.
  • continue: the error is cleared and downstream nodes run as if nothing happened. Use this sparingly and only for truly optional steps.
The FlowGuard node offers a related mechanism for deliberate bailouts. A guard checks whether a named assign is nil or present and then halts the flow, skips the branch, or continues. Unlike a FlowAction failure, a guard fires by design - it is the flow author explicitly saying “if this precondition is not met, do not run the rest of this path.”

Aborting a flow

A flow can also abort itself through a non-recoverable signal on the token. When that signal is set, the run unwinds regardless of which on_error policy is configured on surrounding nodes - no outer action can swallow it. This is distinct from cancellation (which is user-initiated from the editor) and from the halt_flow policy (which is one action’s response to a specific error). In practice, most flows rely on halt_flow as the default failure mode and use halt_branch or continue only where the flow’s design explicitly calls for them.