Skip to main content
Version: 4.8.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 forEach loop.

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 and continues with the next item.

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 nestingdoInParallel 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.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. This is a type-only helper — it is erased at runtime and only influences the TypeScript type-checker.

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' }

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
CONTAINSContainsshort_descriptionCONTAINSfailed

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.