Skip to main content
Version: 4.11.0

Flow Logic

The wfa.flowLogic namespace provides control flow operators for branching, looping, and flow control within Flow and Subflow bodies.

Usage Pattern​

All flow logic constructs follow this invocation shape:

wfa.flowLogic.<construct>(
{ $id: Now.ID['logic_id'], ...params },
callback?
)

wfa.flowLogic.if​

Evaluates a condition and executes the callback if true.

Signature​

wfa.flowLogic.if(
params: {
$id: string,
condition: string,
label?: string,
annotation?: string
},
body: () => void
)

Parameters​

ParameterTypeRequiredDefaultDescription
$idstringYes-Unique identifier (Now.ID['value'])
conditionstringYes-Encoded query expression to evaluate
labelstringNo-Display label for this branch
annotationstringNo-Description/comment

wfa.flowLogic.elseIf​

Evaluates a condition if previous conditions were false. Must follow if or elseIf.

Signature​

wfa.flowLogic.elseIf(
params: {
$id: string,
condition: string,
label?: string,
annotation?: string
},
body: () => void
)

Parameters​

ParameterTypeRequiredDefaultDescription
$idstringYes-Unique identifier (Now.ID['value'])
conditionstringYes-Encoded query expression to evaluate
labelstringNo-Display label for this branch
annotationstringNo-Description/comment

wfa.flowLogic.else​

Executes callback if all previous conditions were false. Must follow if or elseIf.

Signature​

wfa.flowLogic.else(
params: {
$id: string,
annotation?: string
},
body: () => void
)

Parameters​

ParameterTypeRequiredDefaultDescription
$idstringYes-Unique identifier (Now.ID['value'])
annotationstringNo-Description/comment

wfa.flowLogic.forEach​

Iterates over an array, executing the callback for each item.

Signature​

wfa.flowLogic.forEach<TArray>(
items: TArray,
config: {
$id: string,
annotation?: string
},
body?: (item: ExtractArrayElement<TArray>) => void
)

Parameters​

ParameterTypeRequiredDefaultDescription
itemsTArrayYes-Array to iterate (use data pill with array type)
$idstringYes-Unique identifier (Now.ID['value'])
annotationstringNo-Description/comment
bodyfunctionNo-Callback receiving each item

Supported Data Pill Types​

  • 'array.object' — For lookUpRecords results and object arrays
  • 'array.string' — For string arrays (no item parameter)

wfa.flowLogic.exitLoop​

Immediately exits the enclosing loop (forEach or doTheFollowing).

Signature​

wfa.flowLogic.exitLoop(
params: {
$id: string,
annotation?: string
}
)

Parameters​

ParameterTypeRequiredDefaultDescription
$idstringYes-Unique identifier (Now.ID['value'])
annotationstringNo-Description/comment

wfa.flowLogic.skipIteration​

Skips the current iteration of the enclosing loop (forEach or doTheFollowing) and continues with the next iteration.

Signature​

wfa.flowLogic.skipIteration(
params: {
$id: string,
annotation?: string
}
)

Parameters​

ParameterTypeRequiredDefaultDescription
$idstringYes-Unique identifier (Now.ID['value'])
annotationstringNo-Description/comment

wfa.flowLogic.endFlow​

Immediately terminates flow execution.

Signature​

wfa.flowLogic.endFlow(
params: {
$id: string,
annotation?: string
}
)

Parameters​

ParameterTypeRequiredDefaultDescription
$idstringYes-Unique identifier (Now.ID['value'])
annotationstringNo-Description/comment

wfa.flowLogic.doInParallel​

Executes multiple code blocks in parallel within a flow.

Signature​

wfa.flowLogic.doInParallel(
params: {
$id: string,
annotation?: string
},
...blocks: (() => void)[]
)

Parameters​

ParameterTypeRequiredDefaultDescription
$idstringYes-Unique identifier (Now.ID['value'])
annotationstringNo-Description/comment
blocks() => voidYes-One or more arrow functions to execute in parallel

Important Constraints​

  • No nesting — doInParallel cannot be used inside another doInParallel block
  • Minimum 1 block — At least one parallel block is required
  • Each block is an arrow function: () => { ... }
  • Datapill scope limitation — Action output datapills captured inside a doInParallel block are not accessible outside it. To use an action output after the block, assign it to a flow variable inside the block using wfa.flowLogic.setFlowVariables, then reference the flow variable outside.

wfa.flowLogic.tryCatch​

Creates a try-catch block for error handling in flows.

Signature​

wfa.flowLogic.tryCatch(
params: {
$id: string,
annotation?: string
},
handlers: {
try: () => void,
catch: () => void
}
)

Parameters​

ParameterTypeRequiredDefaultDescription
$idstringYes-Unique identifier (Now.ID['value'])
annotationstringNo-Description/comment
handlersobjectYes-Object with try and catch arrow functions

Handlers Object​

PropertyTypeRequiredDescription
try() => voidYesArrow function containing code to attempt
catch() => voidYesArrow function to execute if try block fails

Important Notes​

  • Both try and catch must be arrow functions
  • tryCatch blocks can be nested
  • The catch block executes only if an error occurs in the try block
  • Datapill scope limitation — Action output datapills captured inside a tryCatch block are not accessible outside it. To use an action output after the block, assign it to a flow variable inside the block using wfa.flowLogic.setFlowVariables, then reference the flow variable outside.

wfa.flowLogic.doTheFollowing​

Executes the body repeatedly until an exit condition is met (do-while semantics — the body always runs at least once, and the exit condition is checked only after each run).

Signature​

wfa.flowLogic.doTheFollowing(
params: {
$id: string,
label?: string,
annotation?: string
},
body: () => {
wfa.action(action.core.<coreAction>, { $id: string }, { ... }) // one or more actions
wfa.flowLogic.until(condition: string) // required — must be the last statement
}
)

Parameters​

ParameterTypeRequiredDefaultDescription
$idstringYes-Unique identifier (Now.ID['value'])
labelstringNo-Display label for this loop
annotationstringNo-Description/comment
body() => voidYes-Loop body; must call wfa.flowLogic.until(...) as its last statement

The wfa.flowLogic.until() function​

wfa.flowLogic.until() sets the loop's exit condition. It is a member of the same wfa.flowLogic namespace as doTheFollowing — no separate import is needed. See Important Notes below for the last-statement requirement.

wfa.flowLogic.until(value: string): string
ParameterTypeRequiredDescription
valuestringYesEncoded query expression checked after each iteration; may reference wfa.dataPill(...) values, including outputs from actions declared earlier in the same body

Example​

wfa.flowLogic.doTheFollowing(
{ $id: Now.ID['do_until_1'], label: 'Retry until resolved' },
() => {
const result = wfa.action(
action.core.lookUpRecord,
{ $id: Now.ID['check_status'] },
{ table_name: 'incident', conditions: `sys_id=${wfa.dataPill(params.trigger.current.sys_id, 'string')}` }
);
wfa.flowLogic.until(`${wfa.dataPill(result.Record.state, 'string')}=6`);
}
);

Important Notes​

  • Do-While Semantics — The body always executes at least once; the exit condition is checked only after the body runs.
  • wfa.flowLogic.until(...) Required — A body without a wfa.flowLogic.until(...) call fails validation at build time.
  • wfa.flowLogic.until(...), Not return — Using return instead of calling wfa.flowLogic.until(...) does not satisfy the loop and still fails validation.
  • Must Be the Last Statement — wfa.flowLogic.until(...) must be the final statement in body; any statement after it fails validation at build time.
  • Cross-Statement Datapill Access — Because wfa.flowLogic.until(...) runs after the body, it can reference data pills from actions declared earlier in the same body.

wfa.flowLogic.appendToFlowVariables​

Appends element(s) to array-typed flow variables.

Signature​

wfa.flowLogic.appendToFlowVariables<V>(
params: {
$id: string,
annotation?: string
},
variables: V,
values: Partial<{
[K in keyof V]: V[K] extends Array<infer E>
? E | E[] | unknown[] | string
: never
}>
)

Parameters​

ParameterTypeRequiredDefaultDescription
$idstringYes-Unique identifier (Now.ID['value'])
annotationstringNo-Description/comment
variablesVYes-Flow variables schema (pass params.flowVariables)
valuesobjectYes-Key/value pairs where keys are array variable names

Value Types​

For each array variable, you can append:

  • Single element — { arrayVar: singleElement }
  • Array of elements — { arrayVar: [elem1, elem2, elem3] }
  • Data pill — { arrayVar: wfa.dataPill(...) }
  • Template string — { arrayVar: 'template expression' }

Important Constraints​

  • Array.Object only — Only supports FlowArray({ elementType: FlowObject(...) }) variables
  • Array elements must be objects or datapill expressions — When appending an array literal, each element must be an object or a datapill expression
  • Compile-time safety — TypeScript enforces that target variables are arrays

wfa.flowLogic.waitForADuration​

Pauses flow execution for a specified duration. Supports explicit durations, relative durations, and percentage-based durations.

Signature​

wfa.flowLogic.waitForADuration(
params: WaitForADurationParams
): WaitForADurationOutputs

WaitForADurationParams is $id plus one of three discriminated variants determined by durationType:

Explicit Duration (durationType: 'explicit_duration')​

ParameterTypeRequiredDefaultDescription
$idstringYes-Unique identifier (Now.ID['value'])
durationType'explicit_duration'Yes-Duration variant selector
durationDurationNo-The duration to wait. When omitted, platform uses zero duration
scheduleRecord<'cmn_schedule'> | stringNo-Optional schedule for business-hours calculation
annotationstringNo-Description/comment
uuidstringNo-UUID for referencing this instance's outputs as datapills

Relative Duration (durationType: 'relative_duration')​

ParameterTypeRequiredDefaultDescription
$idstringYes-Unique identifier (Now.ID['value'])
durationType'relative_duration'Yes-Duration variant selector
durationDurationYes-The duration to offset
relativeOperator'before' | 'after'Yes-Whether to wait before or after the reference datetime
relativeDatetimestringYes-Reference datetime for the relative calculation
scheduleRecord<'cmn_schedule'> | stringNo-Optional schedule for business-hours calculation
annotationstringNo-Description/comment
uuidstringNo-UUID for referencing this instance's outputs as datapills

Percentage Duration (durationType: 'percentage_duration')​

ParameterTypeRequiredDefaultDescription
$idstringYes-Unique identifier (Now.ID['value'])
durationType'percentage_duration'Yes-Duration variant selector
percentagenumberYes-Percentage value for percentage-based duration
percentageDatetimestringYes-Reference datetime for percentage-based calculation
scheduleRecord<'cmn_schedule'> | stringNo-Optional schedule for business-hours calculation
annotationstringNo-Description/comment
uuidstringNo-UUID for referencing this instance's outputs as datapills

Return Value​

FieldTypeDescription
total_durationDurationThe total duration that was waited
scheduled_end_date_timedatetimeThe scheduled end date/time when the wait completed

wfa.flowLogic.assignSubflowOutputs​

Assigns the subflow's output values from within the subflow body, mapping declared output names to values, datapill references, or template literals. This is the recommended way to set subflow outputs based on step results. Type-only helper — erased at runtime.

Signature​

wfa.flowLogic.assignSubflowOutputs(
definition: { $id: string, annotation?: string },
variables: TOutputs, // always pass params.outputs
values: Partial<TOutputs> // fields to assign; omitted fields are undefined
)

Parameters​

ParameterTypeRequiredDescription
$idstringYesUnique identifier for this assignment node
annotationstringNoDescription/comment
variablesTOutputsYesAlways pass params.outputs -- do not construct a custom object
valuesPartial<TOutputs>YesKey/value pairs to assign. Values may be literals or data pills

⚠️ Type-only helper. This call is erased at runtime; it exists for compile-time type safety.


wfa.flowLogic.setFlowVariables​

Assigns values to flow-scoped variables declared in the Flow or Subflow config flowVariables property. Each call produces a sys_hub_flow_logic_instance_v2 record whose values field contains the serialized assignment JSON.

Signature​

wfa.flowLogic.setFlowVariables(
definition: { $id: string, annotation?: string },
variables: FlowSchemaType<S>,
values: { [K in keyof FlowSchemaType<S>]?: FlowSchemaType<S>[K] | string }
)

Parameters​

ParameterTypeRequiredDescription
$idstringYesUnique identifier (Now.ID['value'])
annotationstringNoDescription/comment
variablesFlowSchemaType<S>YesFlow variables schema — always pass params.flowVariables
valuesPartial recordYesKey/value pairs of variables to set. Omitted keys are unchanged.

Value Types​

For each variable entry in values, you can supply:

  • Typed literal — { myVar: 'hello' }, { count: 42 }
  • Data pill — { myVar: wfa.dataPill(params.trigger.current.short_description, 'string') }
  • Template string — { myVar: 'template expression' }
  • Inline script — { myVar: wfa.inlineScript('return fd_data.trigger.current.number;') }

null and undefined are not valid — omit the key instead of setting it to null.

Important Notes​

  • Always pass params.flowVariables as the variables argument — never construct a custom object.
  • Only the keys listed in values are updated; other flow variables retain their current values.
  • Flow variables are scoped to the current flow or subflow execution — they are not visible to called subflows.

Condition Syntax Reference​

Flow logic conditions use ServiceNow encoded query format.

Comparison Operators​

OperatorDescriptionExample
=Equalspriority=1
!=Not equalsstate!=6
<Less thanpriority<3
<=Less or equalpriority<=2
>Greater thanpriority>3
>=Greater or equalpriority>=2

Empty/Not Empty Operators​

OperatorDescriptionExample
ISEMPTYField is emptyassigned_toISEMPTY
ISNOTEMPTYField has valueassignment_groupISNOTEMPTY

List Operators​

OperatorDescriptionExample
INIn liststateIN1,2,3
NOT INNot in liststateNOT IN6,7

String Operators​

OperatorDescriptionExample
STARTSWITHStarts withnumberSTARTSWITHINC
ENDSWITHEnds withemailENDSWITH@company.com
LIKEContainsshort_descriptionLIKEfailed

Logical Operators​

OperatorDescriptionExample
^ or ^ANDLogical ANDpriority=1^active=true
^ORLogical ORpriority=1^ORpriority=2
^NQNew query (OR group)priority=1^NQstate=2

For usage patterns, examples, best practices, and end-to-end flow logic examples, see the Flow Logic Guide.