NarraLeaf

Flow

Execution routing — branches, loops, sequencing, and the latent wait that suspends a graph.

Flow nodes decide where execution goes next. Every other node computes or changes something; these only steer the exec line through them. You reach for one the moment a graph has to ask a question, repeat itself, wait, or stop early.

Conventions

  • Pin names. in is the exec entry. next, true, false, then, else, then0…, case0…, default, loop, and completed are exec exits. Everything else on the card is a data pin.
  • On-card literals are granted per pin, not per type. Where a table row below says a pin accepts one, you can type the value onto the card instead of wiring it. No condition pin does: If, If Else, and While always want a wired boolean.
  • Loops advance on one cursor. For Loop, For Each, and While take one step per entry. Wire the end of the loop body back into the same node's in pin; the node then hands you the next iteration through loop and eventually leaves through completed. A body that never returns to in runs exactly once.
  • Max iterations defaults to 1000 when left empty. It is a brake, not a target: hitting it leaves through completed as if the work were finished. There is no unbounded mode.
  • Blueprint Value accepts Flow, minus the timers. Delay and Skip Delay are excluded there — a provider that suspends would leave its property unresolved.

If

if

Routes execution by a boolean. Exactly one exit fires, every time.

PinDirectionTypeNotes
inin · exec—
trueout · exec—
falseout · exec—
conditionin · databooleanMust be wired.

If Else

blueprint.flow.ifElse

An if / else-if / else ladder on one card. Conditions are tested in order and the first true one wins; else fires when none does.

PinDirectionTypeNotes
inin · exec—
thenout · exec—Taken when condition is true.
elseout · exec—Taken when no condition is true.
conditionin · databooleanMust be wired.

Add If condition on the card appends a further branch: one boolean input if_N_condition and its matching exec output if_N_then, inserted above the fixed else. Added conditions are tested after condition, in the order they were added.

Switch String

blueprint.flow.switchString

Compares one string against each case value and fires the first match; default fires when nothing matches. A case whose value was never set never matches, so an empty card is not a wildcard — it is a case that can never be reached.

PinDirectionTypeNotes
inin · exec—
case0out · exec—
case1out · exec—
defaultout · exec—Taken when no case matches.
valuein · datastringThe string to match. Accepts an on-card literal.
case0Valuein · datastringMatch value for case0. Accepts an on-card literal.
case1Valuein · datastringMatch value for case1. Accepts an on-card literal.

Add Case appends a string input case_N_value and its exec output case_N_output, inserted above the fixed default. Added cases are matched after case0 and case1.

Sequence

blueprint.flow.sequence

Queues its outputs and runs them in order, each branch to completion before the next one starts. Unconnected outputs are skipped. A Return reached inside one branch drops everything still queued behind it.

PinDirectionTypeNotes
inin · exec—
then0out · exec—Labelled Then 1 on the card.
then1out · exec—Then 2.
then2out · exec—Then 3.
then3out · exec—Then 4.

For Loop

blueprint.flow.forLoop

Counts from start towards end by step, firing loop once per value and reporting it on index. The sign of step decides the direction: it runs while the index has not passed end.

PinDirectionTypeNotes
inin · exec—
loopout · exec—One iteration. Wire the body's tail back to in.
completedout · exec—The range is exhausted.
startin · dataintegerAccepts an on-card literal.
endin · dataintegerInclusive. Accepts an on-card literal.
stepin · dataintegerA step of 0 is treated as 1. Accepts an on-card literal.
maxIterationsin · dataintegerDefaults to 1000. Accepts an on-card literal.
indexout · dataintegerThe current value.

For Each

blueprint.flow.forEach

Walks a JSON array, firing loop once per entry with item and index set. An items value that is not an array leaves through completed immediately rather than failing.

PinDirectionTypeNotes
inin · exec—
loopout · exec—One entry. Wire the body's tail back to in.
completedout · exec—The array is exhausted.
itemsin · datajsonThe array to walk.
maxIterationsin · dataintegerDefaults to 1000. Accepts an on-card literal.
itemout · datajsonThe current entry. One item of items, typed like them: looping over endings, item is an Ending.
indexout · dataintegerThe current position.

While

blueprint.flow.while

Fires loop for as long as condition holds. The condition is re-read on every entry, so it has to be something the loop body can actually change — a variable, a runtime read — not a value computed once before the loop.

PinDirectionTypeNotes
inin · exec—
loopout · exec—One iteration. Wire the body's tail back to in.
completedout · exec—The condition is false, or the brake tripped.
conditionin · databooleanMust be wired.
maxIterationsin · dataintegerDefaults to 1000. Accepts an on-card literal.

Delay

blueprint.flow.delay · Latent

Waits, then continues through completed. It is the only latent Flow node: it suspends the chain that entered it, which is why a Blueprint Value, an inline story value and a branch condition do not offer it. Each of those hands back a value without waiting, and has nowhere to park a pending wait.

token is published before the wait begins, so another chain can read it while this one is suspended and cut the wait short with Skip Delay. A duration of 0 or less does not suspend at all. If the graph run is cancelled while the wait is pending, the wait ends as a cancellation and completed never fires.

PinDirectionTypeNotes
inin · exec—
completedout · exec—Fires after the wait, or as soon as the wait is skipped.
durationin · datafloatSeconds; 0.25 is 250 ms. Accepts an on-card literal.
tokenout · dataTimerFeed to Skip Delay.

A Timer identifies the Delay node within its runtime scope, not one particular wait. If two execution chains are parked on the same Delay at once, one Skip Delay releases both.

Skip Delay

blueprint.flow.skipDelay

Completes a pending Delay early. The target leaves through its own completed; Skip Delay itself continues through next without waiting for it. Hand it something that is not a Delay token, or a Delay that is not currently waiting, and it is a silent no-op — execution still continues through next.

PinDirectionTypeNotes
inin · exec—
nextout · exec—Continues as soon as the skip is submitted.
timerin · dataTimerThe token from the Delay you want to cut short.

Return

blueprint.flow.return

Ends the current execution chain. It has no exec output, and it also drops any branches Sequence still had queued.

PinDirectionTypeNotes
inin · exec—

Return Value

blueprint.data.returnValue

Hands a value back to whatever asked for it, and ends the chain. This is the terminal of a Blueprint Value graph — the node that decides what the bound property is. It belongs only on owners that produce a value; validation says so if you place it elsewhere. If a value graph finishes without reaching it, the previously resolved value stands.

PinDirectionTypeNotes
inin · exec—
valuein · dataanyThe value the property takes.

To return from a fn instead, use Fn Return — see Functions.

Noop

blueprint.flow.noop

Passes execution straight through, changing nothing. Useful as a junction where several branches merge into one continuation, and as a placeholder while a chain is half-rewired.

PinDirectionTypeNotes
inin · exec—
nextout · exec—

On this page