Skip to main content
Version: 4.7.0

Subflow

API reference for the Subflow() constructor, the wfa.subflow() invocation helper, and the wfa.flowLogic.assignSubflowOutputs() output helper.

Subflows are reusable units of automation with typed inputs and outputs. They are invoked from inside a Flow or another Subflow via wfa.subflow() -- they have no trigger of their own.


Subflow()

Defines a reusable callable subflow with typed inputs, typed outputs, and an optional body.

Signature

Subflow<TInputs, TOutputs, TFlowVariables, TStages>(
config: SubflowConfig<TInputs, TOutputs, TFlowVariables, TStages>,
body?: (params: {
inputs: TInputs,
outputs: TOutputs,
flowVariables: TFlowVariables,
stages: TStages
}) => void
): Subflow<TInputs, TOutputs>

Config Parameters

ParameterTypeDefaultRequiredDescription
$idstring / Now.ID[...]-YesUnique identifier
namestring-YesDisplay name shown in Flow Designer
descriptionstring-NoWhat the subflow does
annotationstring-NoAnnotation text visible on the designer canvas
runAs'system' | 'user'-NoExecution context. 'system' bypasses ACLs
runWithRoles(string | Role)[][]NoRole sys_ids or Role objects granting temporary elevated permissions
flowPriority'LOW' | 'MEDIUM' | 'HIGH'-NoExecution queue priority
protectionPolicy'read' | ''''NoIf 'read', subflow body is read-protected in the runtime
access'public' | 'package_private''public'NoVisibility scope
categorystring-NoGrouping category in Flow Designer
inputsRecord<string, Column>{}NoInput schema; passed by the caller via wfa.subflow()
outputsRecord<string, Column>{}NoOutput schema; set inside body via assignSubflowOutputs
flowVariablesRecord<string, Column>{}NoInternal variables scoped to this subflow execution
stagesRecord<string, FlowStageConfig>{}NoNamed stage declarations for tracking subflow execution progress. Each key must match the value field inside the corresponding FlowStage() call

Body Function

The body is optional. When supplied, it receives a params object exposing the typed schemas:

params keyTypeDescription
inputsTInputsTyped input pills (use wfa.dataPill(params.inputs.field, 'type'))
outputsTOutputsOutput schema reference. Pass this to assignSubflowOutputs
flowVariablesTFlowVariablesInternal mutable variables (read via data pill, write via setFlowVariables)
stagesTStagesNamed stages declared in the config. Activate via wfa.stage(params.stages.x)

The body may contain wfa.action(), wfa.flowLogic.*, and nested wfa.subflow() calls.

Subflow(config) with no body is valid -- useful for stub definitions or cross-file references.


wfa.subflow()

Invokes a subflow from inside a Flow body or another Subflow body.

Signature (typed)

wfa.subflow<TInputs, TOutputs>(
subflow: Subflow<TInputs, TOutputs>,
instanceConfig: {
$id: string,
annotation?: string,
uuid?: string,
showSubflowStage?: boolean
},
inputs: TInputs & { waitForCompletion?: boolean }
): TOutputs & { type: 'subflow' }

Signature (sys_id fallback)

When the subflow's typed definition cannot be imported (cross-application or unresolvable), pass the subflow's sys_id string directly. The return type allows arbitrary property access for downstream data pill references.

wfa.subflow(
subflowSysId: string,
instanceConfig: { $id: string, annotation?: string, ... },
inputs: Record<string, any> & { waitForCompletion?: boolean }
)

Parameters

ParameterTypeDefaultRequiredDescription
subflowSubflow | string (sys_id)-YesExported subflow constant or a string sys_id when the definition is not importable
instanceConfig.$idstring-YesUnique identifier for this invocation instance
annotationstring-NoDescription of this specific invocation
uuidstring-NoStable UUID for this instance (rarely set by hand; usually generated)
showSubflowStageboolean-NoIf true, a dedicated sys_hub_flow_stage of type: 'subflow' is created for this instance
inputsTInputs-YesInput values matching the subflow's input schema
waitForCompletionbooleanfalseNoIf true, the caller waits for the subflow to complete before continuing. Belongs inside the inputs object, not instanceConfig

Return Value

Returns a typed output object. Access output fields as data pills:

const result = wfa.subflow(mySubflow, { $id: Now.ID["instance"] }, { ... });
wfa.dataPill(result.outputField, "string"); // use output in downstream actions
wfa.dataPill(result.recordOutput, "reference");

wfa.flowLogic.assignSubflowOutputs()

Sets the subflow's output values. Must be called inside the subflow body for outputs to be visible to the caller.

Signature

wfa.flowLogic.assignSubflowOutputs(
definition: { $id: string, annotation?: string },
outputSchema: 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
outputSchemaTOutputsYesAlways 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. The actual runtime assignment happens in the underlying flow stage.


Column Types

Import from @servicenow/sdk/core for inputs, outputs, and flowVariables schemas:

TypeDescription
StringColumnText values
IntegerColumnWhole numbers
BooleanColumnTrue/false values
DecimalColumnDecimal numbers (fixed precision)
FloatColumnFloating-point numbers
DateTimeColumnDate and time values
ReferenceColumnReference to a ServiceNow table record
GenericColumnFlexible type via columnType property
JsonColumnJSON string values

Import from @servicenow/sdk/automation for complex types:

TypeDescription
FlowObjectNested object with typed fields
FlowArrayArray of typed elements (use with elementType)

FlowObject example

import { FlowObject } from "@servicenow/sdk/automation";
import { StringColumn, IntegerColumn } from "@servicenow/sdk/core";

inputs: {
requestData: FlowObject({
label: "Request Data",
mandatory: false,
fields: {
title: StringColumn({ label: "Title" }),
priority: IntegerColumn({ label: "Priority" })
}
})
}

// Access a nested field inside the body:
// wfa.dataPill(params.inputs.requestData.title, "string")

For complete examples, usage patterns, best practices, and anti-patterns, see the Subflow Guide.