Flow API - ServiceNow Fluent

  • Rversion finale: Australia
  • Mis à jour 12 mars 2026
  • 24 minutes de lecture
  • The Flow API defines flows and subflows [sys_hub_flow], which automate business processes with reusable multiple-step components.

    Create a flow using the Flow object. For more information, see Flow object.

    Create a subflow using the Subflow object. For more information, see Subflow object.

    For general information about flows, see Exploring flows. For general information about subflows, see Exploring subflows.

    Flow object

    Create a flow [sys_hub_flow] to run a sequence of actions and flow logic when a set of trigger conditions occur.

    Flows only run when their trigger conditions are met. Use flows for event-driven automation that requires a consistent and predefined trigger.

    A Flow object consists of these components.
    • One configuration object that defines the flow configuration properties.
    • One wfa.trigger function that defines when to run the flow.
    • One Body function that defines what actions, flow logic, and subflows to run.
      • Zero or more wfa.action functions
      • Zero or more wfa.flow_logic functions
    Tableau 1. Properties
    Name Type Description
    configuration Object Required. An object containing the metadata configuration properties for the Fluent object or function.
    $id String or Number Required. A unique ID for the metadata object. When you build the application, this ID is hashed into a unique sys_id. For more information, see ServiceNow Fluent language constructs.

    Format: Now.ID['String' or Number]

    name String Required. Display name of the flow. The flow name should be meaningful and descriptive to easily identify its purpose.
    description String Description of what the flow does.
    runAs String

    Determines under which user context the flow actions are run.

    Valid values: system, user

    Default: user

    runWithRoles String Specify the roles that the flow uses while running.
    flowPriority String

    Defines the execution priority of the flow in the Flow Engine.

    Valid values: LOW, MEDIUM, HIGH

    Default: MEDIUM

    protection String

    Defines whether the flow is read-only (read) or editable (empty string).

    Valid values: read, ' '

    access String

    Defines whether a flow is public or private.

    Valid values: public, package_private

    Default: public

    flowVariables Object Object defining data variables available to the flow using Column types. Use the get_table_schema function to fetch field definitions.
    wfa.trigger Function Defines when to run the flow. When the trigger conditions are met, the system runs the flow using the data provided by the trigger. For more information about the wfa.trigger function, see wfa.trigger function.
    Flow body Function
    Flow body is an Arrow function in TypeScript that represents the execution steps in the flow. The Flow Body receives the _params parameter as its input, which contains the wfa.trigger and flowVariables objects.The steps in the Flow body consist of these function types:
    • wfa.action function: Execute specific tasks and operations within a flow, such as creating records, sending emails, requesting approvals, or integrating with external systems. For more information about the wfa.action function, see wfa.action function.
    • wfa.flow_logic function: Control how flows execute, providing conditional branching, iteration, and flow structuring capabilities. For more information about wfa.flow_logic function, see wfa.flow_logic function.

    You can use these parameter values in the Flow body function.

    _params.trigger.current
    Data type: Record. Parameter that stores the current record that started a create record, update record, or create or update record flow.
    _params.trigger.previous
    Data type: Record. Parameter that stores the previous record values that started an update record flow.
    _params.trigger.table_name
    Data type: String. Parameter that stores the table name of the current record that started the flow.
    _params.trigger.flowVariables
    Data type: Object. Parameter that stores the flow variables defined in this flow.

    This example creates a flow that runs when a high-priority incident is created. The flow assigns the incident to a team and sends a notification.

    import { Flow, wfa, trigger, action } from '@servicenow/sdk/automation'
    
    // ✅ CORRECT - Simple flow with record trigger
    Flow(
        {
            $id: Now.ID['priority_incident_handler'],
            name: 'Priority Incident Handler',
            description: 'Auto-assign high priority incidents'
        },
        wfa.trigger(
            trigger.record.created,
            { $id: Now.ID['incident_trigger'], annotation: 'When high priority incident created' },
            {
                table: 'incident',
                condition: 'priority=1^ORpriority=2'
            }
        ),
        (_params) => {
            // Assign to critical response team
            wfa.action(
                action.core.updateRecord,
                { $id: Now.ID['assign'], annotation: 'Assign to team' },
                {
                    record: _params.trigger.current,
                    table_name: 'incident',
                    values: 'assignment_group=critical_team_sys_id^state=2'
                }
            )
            
            // Send notification
            wfa.action(
                action.core.sendEmail,
                { $id: Now.ID['notify'], annotation: 'Notify team' },
                {
                    ah_to: 'critical-team@company.com',
                    ah_subject: `Priority Incident: \${_params.trigger.current.number}`,
                    ah_body: `New priority incident created`
                }
            )
        }
    )

    This example runs when a critical or high priority incident is created.

    import { Flow, wfa, trigger, action } from '@servicenow/sdk/automation'
    import { StringColumn, BooleanColumn } from '@servicenow/sdk/core'
    
    // Define flow directly - only export if it needs to be imported elsewhere
    Flow(
        {
            $id: Now.ID['priority_incident_handler'],
            name: 'Priority Incident Handler',
            description: 'Automatically handles high priority incidents',
            runAs: 'system',
            runWithRoles: [],
            flowPriority: 'HIGH',
            protection: '',
            access: 'public',
            category: 'Incident Management',
            flowVariables: {
                assignedTeam: StringColumn({ label: 'Assigned Team' }),
                notificationSent: BooleanColumn({ label: 'Notification Sent' })
            }
        },
        wfa.trigger(
            trigger.record.created,
            { $id: Now.ID['incident_trigger'], annotation: 'When high priority incident is created' },
            {
                table: 'incident',
                condition: 'priority=1^ORpriority=2',
            }
        ),
        (_params) => {
            // Check if incident is critical priority
            wfa.flow_logic.if(
                {
                    $id: Now.ID['check_critical'],
                    condition: `\${_params.trigger.current.priority}=1`,
                    annotation: 'Check if priority is critical',
                },
                () => {
                    // Assign to Critical Response Team
                    wfa.action(
                        action.core.updateRecord,
                        { $id: Now.ID['assign_critical'], annotation: 'Assign to Critical Response Team' },
                        {
                            record: _params.trigger.current,
                            table_name: 'incident',
                            values: 'assigned_to=senior.engineer^assignment_group=Critical Response Team^state=2'
                        }
                    )
                    
                    // Send notification
                    wfa.action(
                        action.core.sendNotification,
                        { $id: Now.ID['notify_team'], annotation: 'Notify Critical Response Team' },
                        {
                            notification: 'critical_incident_notification',
                            users: 'critical_team',
                            table_name: 'incident',
                            record: _params.trigger.current
                        }
                    )
                }
            )
            
            wfa.flow_logic.elseIf(
                {
                    $id: Now.ID['check_high'],
                    condition: `\${_params.trigger.current.priority}=2`,
                    annotation: 'Check if priority is high',
                },
                () => {
                    // Assign to Network Support team
                    wfa.action(
                        action.core.updateRecord,
                        { $id: Now.ID['assign_high'], annotation: 'Assign to Network Support team' },
                        {
                            record: _params.trigger.current,
                            table_name: 'incident',
                            values: 'assigned_to=agent.smith^assignment_group=Network Support^state=2'
                        }
                    )
                }
            )
        }
    )

    Subflow object

    Create a subflow [sys_hub_flow] to run a reusbale sequence of actions and flow logic when called by a flow or API.

    Subflows run when called by a flow or an API. Use subflows for on-demand automation that can be called by multiple flows.

    Subflows consist of these components.
    • One configuration object that defines the subflow configuration properties.
      • Zero or one inputs object that defines subflow inputs.
      • Zero or one outputs object that defines subflow outputs.
      • Zero or one flow variables object that defines flow variables.
    • One Body function that defines what actions, flow logic, and subflows to run.
      • Zero or more wfa.action functions
      • Zero or more wfa.flow_logic functions
    Tableau 2. Properties
    Name Type Description
    configuration Object Required. An object containing the metadata configuration properties for the Fluent object or function.
    $id String or Number Required. A unique ID for the metadata object. When you build the application, this ID is hashed into a unique sys_id. For more information, see ServiceNow Fluent language constructs.

    Format: Now.ID['String' or Number]

    name String Required. Display name of the subflow. The subflow name should be meaningful and descriptive to easily identify its purpose. This property is part of the Subflow configuration object.
    description String Description of what the flow does. This property is part of the Subflow configuration object.
    runAs String

    Determines under which user context the subflow actions are executed.

    Valid values: system, user

    Default: user

    This property is part of the Subflow configuration object.

    runWithRoles Array Specify the roles that the subflow uses while running. This property is part of the Subflow configuration object.
    flowPriority String

    Defines the execution priority of the subflow in the Flow Engine.

    Valid values: LOW, MEDIUM, HIGH

    Default: Medium

    This property is part of the Subflow configuration object.

    protection String

    Defines whether the subflow is read-only (read) or editable (empty string).

    Valid values: read, ' '

    This property is part of the Subflow configuration object.

    access String

    Defines the visibility/accessibility of the subflow to other subflow authors.

    Valid values: public, package_private

    Default: public

    This property is part of the Subflow configuration object.

    category String Category for organizing the subflow. This property is part of the Subflow configuration object.
    inputs Object Object defining input parameters using Column types. This property is part of the Subflow configuration object.
    outputs Object Object defining output parameters using Column types. This property is part of the Subflow configuration object.
    flowVariables Object Object defining data variables available to the subflow using Column types. This property is part of the Subflow configuration object.
    Flow body Function
    Flow body is an Arrow function in TypeScript that represents the execution steps in the flow. The Flow Body receives the _params parameter as its input, which contains the inputs and flowVariables objects.The steps in the Flow body consist of these function types:
    • wfa.action function: Execute specific tasks and operations within a flow, such as creating records, sending emails, requesting approvals, or integrating with external systems. For more information about the wfa.action function, see wfa.action function.
    • wfa.flow_logic function: Control how flows execute, providing conditional branching, iteration, and flow structuring capabilities. For more information about wfa.flow_logic function, see wfa.flow_logic function.

    You can use these parameter values in the Flow body function.

    _params.trigger.current
    Data type: Record. Parameter that stores the current record that started a create record, update record, or create or update record flow.
    _params.trigger.previous
    Data type: Record. Parameter that stores the previous record values that started an update record flow.
    _params.trigger.table_name
    Data type: String. Parameter that stores the table name of the current record that started the flow.
    _params.trigger.flowVariables
    Data type: Object. Parameter that stores the flow variables defined in this flow.

    This example creates a subflow that sends a customizable email to specified user. The subflow accepts inputs for a reference ID to a specific, a text string for the subject , and an string column for the HTML of the email body. The subflow returns a Boolean output value indicating whether the email was successfully sent.

    import { Subflow, wfa, action } from '@servicenow/sdk/automation'
    import { StringColumn, BooleanColumn, ReferenceColumn } from '@servicenow/sdk/core'
    
    /**
     * Reusable subflow for sending email notifications
     * Used by: Incident flow, Problem flow, Change flow
     */
    export const sendNotificationSubflow = Subflow(
        {
            // Unique identifier - string | guid, mandatory
            $id: Now.ID['send_notification_subflow'],
    
            // Display name - string, mandatory
            name: 'Send Email Notification',
    
            // Description - string, optional
            description: 'Sends email to specified user with customizable content',
    
            // Run as system user for guaranteed permissions - 'system' | 'user', optional, default: 'user'
            runAs: 'system',
    
            // Input schema - defines what data this subflow needs
            inputs: {
                // ReferenceColumn for sys_user reference
                // ALWAYS use runQuery tool to get EXACT sys_id from sys_user table
                recipientId: ReferenceColumn({
                    label: 'Recipient', // string, mandatory - field label
                    mandatory: true, // boolean, mandatory - if true, input must be provided when calling subflow
                    referenceTable: 'sys_user', // string, mandatory - table name for reference
                    hint: 'User to receive the email' // string, optional - helper text
                }),
                // StringColumn for text input
                subject: StringColumn({
                    label: 'Subject', // string, mandatory
                    mandatory: true, // boolean, mandatory
                    hint: 'Email subject line' // string, optional
                }),
                // StringColumn for HTML email body
                body: StringColumn({
                    label: 'Email Body', // string, mandatory
                    mandatory: true, // boolean, mandatory
                    hint: 'Email body content (supports HTML)' // string, optional
                })
            },
    
            // Output schema - defines what this subflow returns
            outputs: {
                // BooleanColumn for success indicator
                success: BooleanColumn({
                    label: 'Sent Successfully', // string, mandatory
                    mandatory: true, // boolean, mandatory - outputs should always be mandatory
                    hint: 'Indicates if email was sent' // string, optional
                })
            }
        },
        (params) => {
            // 1. ACCESS INPUTS via params.inputs.[fieldName]
            const recipient = params.inputs.recipientId // sys_id of user from inputs
            const subject = params.inputs.subject // string from inputs
            const body = params.inputs.body // string from inputs
    
            // 2. EXECUTE ACTION - Send email using sendEmail action
            wfa.action(
                action.core.sendEmail, // action definition
                {
                    $id: Now.ID['send_email_action'], // string | guid, mandatory
                    annotation: 'Send email notification to recipient' // string, optional - describes action purpose
                },
                {
                    // ALWAYS use get_table_schema tool to find valid field names for email actions
                    ah_to: recipient, // sys_id of recipient user
                    ah_subject: subject, // email subject line
                    ah_body: body, // email body content (HTML supported)
                    watermark_email: true // boolean - adds ServiceNow watermark
                }
            )
    
            // 3. RETURN OUTPUTS - ALWAYS use assignSubflowOutputs (NOT return statement)
            wfa.flow_logic.assignSubflowOutputs(
                {
                    $id: Now.ID['set_success_output'], // string | guid, mandatory
                    annotation: 'Mark notification as sent' // string, optional - describes what outputs are being set
                },
                params.outputs, // output schema from config - mandatory
                { success: true } // actual output values - must match output schema types
            )
        }
    )

    wfa.trigger function

    Run a flow when the start conditions of a specific trigger type are met. Triggers determine when a flow runs and what data is available from the flow start conditions.

    Add a wfa.trigger function to the Flow Body function of a Flow object.

    The following types of action instances are supported:
    • trigger.record.created
    • trigger.record.updated
    • trigger.record.createdOrUpdated
    • trigger.scheduled.daily
    • trigger.scheduled.weekly
    • trigger.scheduled.monthly
    • trigger.scheduled.repeat
    • trigger.scheduled.runOnce
    • trigger.application.inboundEmail
    • trigger.application.slaTask
    • trigger.application.knowledgeManagement
    • trigger.application.remoteTableQuery
    .

    For more information about available actions, see Workflow Studio flow trigger types.

    Tableau 3. Properties
    Name Type Description
    trigger String Name of the specific trigger to run. All action names use a dot notation that starts with trigger. For example, trigger.record.created, trigger.scheduled.daily, or trigger.application.serviceCatalog.
    configuration Object Required. An object containing the metadata configuration properties for the Fluent object or function.
    $id String or Number Required. A unique ID for the metadata object. When you build the application, this ID is hashed into a unique sys_id. For more information, see ServiceNow Fluent language constructs.

    Format: Now.ID['String' or Number]

    inputs Object An object containing any input parameters required by the trigger such as table or condition.

    This example runs a flow when a high priority incident record is created.

    // Trigger definition - defines when the flow starts
    wfa.trigger(
        trigger.record.created, // TriggerDefinition - record creation event
        { 
            $id: Now.ID['incident_trigger'], // string | guid, mandatory - unique identifier
            annotation: 'When high priority incident is created' // string, optional - describes trigger purpose
        },
        {
            table: 'incident', // string, mandatory - table name to monitor
            condition: 'priority=1^ORpriority=2', // string, optional - encoded query filter
            run_on_extended: 'false', // string, optional, default: 'false' - run on child tables
            run_flow_in: 'any', // string, optional, default: 'any' - 'any', 'background', or 'foreground'
            run_when_setting: 'both', // string, optional, default: 'both' - 'both', 'non_interactive', or 'interactive'
            run_when_user_list: [], // Array, optional, default: [] - need to use runQuery to get user sys_ids from sys_user table
            run_when_user_setting: 'any' // string, optional, default: 'any' - 'any', 'one_of', or 'not_one_of'
        }
    )

    This examples starts a flow daily at 9 AM.

    // ✅ CORRECT - Daily trigger at specific time
    wfa.trigger(
        trigger.scheduled.daily,
        { 
            $id: Now.ID['daily_report_trigger'],
            annotation: 'Runs daily at 9 AM'
        },
        {
            time: Time({ hours: 9, minutes: 0, seconds: 0 })
        }
    )

    This examples starts a flow when there is an email reply to an incident record.

    // Trigger when email arrives for incident table
    wfa.trigger(
        trigger.application.inboundEmail, // TriggerDefinition - inbound email event
        { 
            $id: Now.ID['incident_email_trigger'], // string | guid, mandatory
            annotation: 'Process emails for incident table' // string, optional
        },
        {
            target_table: 'incident', // string, optional - table for email replies/forwards
            email_conditions: '', // string, optional - filter which emails trigger the flow
            order: 100, // number, optional - execution order when multiple email triggers exist
            stop_condition_evaluation: true // boolean, optional - stop evaluating other triggers if this one matches
        }
    )
    
    // Access email data in flow body:
    (_params) => {
        const emailSubject = _params.trigger.email.subject // Email subject
        const emailBody = _params.trigger.email.body // Email body
        const emailFrom = _params.trigger.email.from // Sender email address
    }

    wfa.action function

    Run a specific action instance from a flow or subflow. Actions determine what data is generated, updated, or retrieved.

    Add wfa.action functions to the Flow Body function of a Flow or Subflow object.

    The following types of action instances are supported:
    • action.core.createRecord
    • action.core.createOrUpdateRecord
    • action.core.deleteRecord
    • action.core.lookUpRecord
    • action.core.lookUpRecords
    • action.core.updateRecord
    • action.core.updateMultipleRecords
    • action.core.sendNotification
    • action.core.sendEmail
    • action.core.sendSms
    • action.core.askForApproval
    • action.core.waitForApproval
    • action.core.createTask
    • action.core.log
    • action.core.waitForCondition
    • action.core.waitForMessage
    • action.core.slaPercentageTimer
    .

    For more information about available actions, see Workflow Studio actions.

    Tableau 4. Properties
    Name Type Description
    action String Name of the specific action to run. All action names use a dot notation that starts with action.core. For example, action.core.lookUpRecord, action.core.lookUpRecords, action.core.createRecord, or action.core.updateRecord.
    configuration Object Required. An object containing the metadata configuration properties for the Fluent object or function.
    $id String or Number Required. A unique ID for the metadata object. When you build the application, this ID is hashed into a unique sys_id. For more information, see ServiceNow Fluent language constructs.

    Format: Now.ID['String' or Number]

    inputs Object An object containing any input parameters required by the action such as table_name or values.

    This example creates an incident record, assigns it, adds work notes, and creates a related request record.

    // Step 1: Create an Incident for VPN access issue
    const incidentResult = wfa.action(
        action.core.createRecord,
        { $id: Now.ID['create_incident'], annotation: 'Create VPN access incident' },
        {
            table_name: 'incident',
            values: `short_description=User cannot access VPN^description=User reported VPN connectivity issues^impact=2^urgency=2^caller_id=\${params.flowVariables.user}`,
        }
    )
    
    // Step 2: Assign the incident to Network Support team
    wfa.action(
        action.core.updateRecord,
        { $id: Now.ID['assign_incident'], annotation: 'Assign incident to Network Support' },
        {
            table_name: 'incident',
            record: `\${incidentResult.record}`,
            values: 'assigned_to=agent_sys_id^assignment_group=network_support_sys_id^state=2',
        }
    )
    
    // Step 3: Add initial work notes to the incident
    wfa.action(
        action.core.updateRecord,
        { $id: Now.ID['add_notes'], annotation: 'Add initial work notes' },
        {
            table_name: 'incident',
            record: `\${incidentResult.record}`,
            values: 'work_notes=Assigned to agent for investigation.',
        }
    )
    
    // Step 4: Create a related Service Request for VPN access
    const serviceRequestResult = wfa.action(
        action.core.createRecord,
        { $id: Now.ID['create_request'], annotation: 'Create VPN access service request' },
        {
            table_name: 'sc_request',
            values: `requested_for=\${params.flowVariables.user}^short_description=VPN Access Request^description=Requesting access to the corporate VPN^state=1`,
        }
    )

    This example uses the Look Up Records action to looks up problem records created yesterday and checks to see if the assignment group field is empty. If unassigned, It uses the Update Record action to set the state and assignment group fields.

    // Find all newly created problem records from yesterday
    const problems = wfa.action(
        action.core.lookUpRecords,
        {
            $id: Now.ID['find_problems'],
            annotation: 'Find all newly created problem records for the past day',
        },
        {
            table: 'problem',
            conditions: 'sys_created_onONYesterday@javascript:gs.beginningOfYesterday()@javascript:gs.endOfYesterday()',
        }
    )
    
    // Check if problems exist before processing
    wfa.flow_logic.forEach(
        problems.Records,
        { $id: Now.ID['iterate_problems'], annotation: 'Iterate each problem' },
        (item) => {
            // Check if the problem is not assigned
            wfa.flow_logic.if(
                {
                    $id: Now.ID['check_assignment'],
                    condition: `{{problems.item.assignment_group}}ISEMPTY`,
                    annotation: 'Check if problem is not assigned',
                },
                () => {
                    // Update problem state
                    wfa.action(
                        action.core.updateRecord,
                        {
                            $id: Now.ID['update_problem'],
                            annotation: 'Update the problem record state',
                        },
                        {
                            table_name: 'problem',
                            record: item,
                            values: 'state=1^assignment_group=level1_triage',
                        }
                    )
                    
                    // Send notification to the group
                    wfa.action(
                        action.core.sendNotification,
                        {
                            $id: Now.ID['notify_team'],
                            annotation: 'Send notification to the group',
                        },
                        {
                            table_name: 'problem',
                            record: item,
                            notification: 'problem_assigned_notification',
                        }
                    )
                }
            )
        }
    )

    This example takes different Update Record actions based on the priority of an incident record.

    // Multi-level conditional logic for priority-based routing
    wfa.flow_logic.if(
        {
            $id: Now.ID['check_priority_critical'],
            condition: `\${params.trigger.current.priority}=1`,
            annotation: 'Check if priority is Critical',
        },
        () => {
            // Critical priority - expedite
            wfa.action(
                action.core.updateRecord,
                { $id: Now.ID['update_critical'], annotation: 'Update incident - Critical priority' },
                {
                    table_name: 'incident',
                    record: `\${params.trigger.current.sys_id}`,
                    values: 'work_notes=Critical priority - expediting request.^state=2^escalation=1',
                }
            )
            
            // Send SMS for critical
            wfa.action(
                action.core.sendSms,
                { $id: Now.ID['sms_critical'], annotation: 'Send SMS alert' },
                {
                    phone_number: '+1234567890',
                    message: `Critical incident \${params.trigger.current.number} requires immediate attention`,
                }
            )
        }
    )
    
    wfa.flow_logic.elseIf(
        {
            $id: Now.ID['check_priority_high'],
            condition: `\${params.trigger.current.priority}=2`,
            annotation: 'Check if priority is High',
        },
        () => {
            // High priority - normal processing
            wfa.action(
                action.core.updateRecord,
                { $id: Now.ID['update_high'], annotation: 'Update incident - High priority' },
                {
                    table_name: 'incident',
                    record: `\${params.trigger.current.sys_id}`,
                    values: 'work_notes=High priority - processing soon.^state=2',
                }
            )
            
            // Send email for high
            wfa.action(
                action.core.sendEmail,
                { $id: Now.ID['email_high'], annotation: 'Send email notification' },
                {
                    ah_to: 'support@company.com',
                    ah_subject: `High Priority Incident: \${params.trigger.current.number}`,
                    ah_body: 'High priority incident requires attention within 4 hours.',
                }
            )
        }
    )
    
    wfa.flow_logic.else(
        { $id: Now.ID['default_priority'], annotation: 'Default priority handling' },
        () => {
            // Standard priority - queue
            wfa.action(
                action.core.updateRecord,
                { $id: Now.ID['update_standard'], annotation: 'Update incident - Standard priority' },
                {
                    table_name: 'incident',
                    record: `\${params.trigger.current.sys_id}`,
                    values: 'work_notes=Standard priority - added to queue.^state=2',
                }
            )
        }
    )

    wfa.flow_logic function

    Run a specific flow logic instance from a flow or subflow. Flow logic determines how and when data is used.

    Add wfa.flow_logic functions to the Flow Body function of a Flow or Subflow object.

    The following types of flow logic instances are supported:
    • if
    • elseIf
    • else
    • forEach
    • waitForADuration
    • exitLoop, endFlow, skipIteration, setFlowVariables, and assignSubflowOutputs
    .

    For more information about available flow logic, see Workflow Studio flow logic.

    Tableau 5. Properties
    Name Type Description
    configuration Object Required. An object containing the metadata configuration properties for the Fluent object or function.
    $id String or Number Required. A unique ID for the metadata object. When you build the application, this ID is hashed into a unique sys_id. For more information, see ServiceNow Fluent language constructs.

    Format: Now.ID['String' or Number]

    annotation String Describe what this instance of flow logic does. For example, annotation: 'Priority is critical'.
    condition String Required in a wfa.flow_logic.if and wfa.flow_logic.elseIf function. Data values that must be true to run this flow logic. For example, condition: `\${_params.trigger.current.priority}=1`,.
    item Array Required in a wfa.flow_logic.forEach function. An array or a collection of records to iterate over. Typically, this list of records is dynamically generated from a wfa.action function call to the action.core.lookUpRecords action. For example, a problems.Records array can be generated from an action.core.lookUpRecords action.
    (_params) => {
        //Find all the newly created problem records for the past day
        const problems = wfa.action(
            action.core.lookUpRecords,
            {
                $id: Now.ID['daily_unassigned_new_problems_triage_flow_step1'],
                annotation: 'Find all the newly created problem records for the past day',
            },
            {
                table: 'problem',
                conditions:
                    'sys_created_onONYesterday@javascript:gs.beginningOfYesterday()@javascript:gs.endOfYesterday()',
            }
        )
    
        //Iterate over the problems
        wfa.flow_logic.forEach(
            problems.Records, { ... }
    label String Display value describing this instance of flow logic. For example, label: 'If Priority is critical',.
    variables Schema Required in a wfa.flow_logic.assignSubflowOutputs and wfa.flow_logic.setFlowVariables function. A schema produced by the FlowVariables API that defines the data structure of the flow variables. For example, the flowVars schema can be generated from FlowVariables.
    import { FlowVariables } from '@servicenow/sdk/automation'
    
    // Define flow variables
    const flowVars = FlowVariables({
        status: StringColumn({ label: 'Status' }),
        count: IntegerColumn({ label: 'Count' }),
        isActive: BooleanColumn({ label: 'Is Active' }),
    })
    
    // Flow body
    (_params) => {
        // Set flow variables with literal values
        wfa.flow_logic.setFlowVariables(
            {
                $id: Now.ID['initialize_variables'],
                annotation: 'Initialize flow variables with default values',
            },
            _params.flowVariables, { ... }
    Important :
    Always use _params.flowVariables as the argument for this property. Passing the wrong schema will cause validation errors.
    Flow logic body Function Flow logic body is an Arrow function in TypeScript that represents the execution steps in the flow logic. The Flow Body receives the _params parameter as its input, which contains the wfa.trigger and flowVariables objects. The steps in the Flow logic body consist of these functions calls:
    • wfa.action function: Run a specific action instance from a flow or subflow. Actions determine what data is generated, updated, or retrieved.. For more information about the wfa.action function, see wfa.action function.
    • wfa.flow_logic function: Run a specific flow logic instance from a flow or subflow. Flow logic determines how and when data is used. For more information about the wfa.flow_logic function, see wfa.flow_logic function.

    This example shows checking for conditions in the trigger record. If the current record has a priority of 1, it assigns the record to a critical priority team. Else If the current record has a priority value of 2, it assigns the record to a high priority team. If neither condition is met, the record is assigned to a general team.

    // Flow body showing if/elseIf/else usage
    (_params) => {
        wfa.flow_logic.if(
            {
                $id: Now.ID['check_critical_priority'],
                condition: `\${_params.trigger.current.priority}=1`,
                annotation: 'Priority is critical',
            },
            () => {
                wfa.action(
                    action.core.updateRecord,
                    { $id: Now.ID['assign_critical_team'], annotation: 'Assign to critical team' },
                    { record: _params.trigger.current, table_name: 'incident', values: 'assignment_group=critical_team' }
                )
            }
        )
        wfa.flow_logic.elseIf(
            { $id: Now.ID['check_high_priority'], condition: `\${_params.trigger.current.priority}=2`, annotation: 'Priority is high' },
            () => {
                wfa.action(
                    action.core.updateRecord,
                    { $id: Now.ID['assign_high_team'], annotation: 'Assign to high team' },
                    { record: _params.trigger.current, table_name: 'incident', values: 'assignment_group=high_team' }
                )
            }
        )
        wfa.flow_logic.else(
            { $id: Now.ID['assign_default'], annotation: 'Default assignment' },
            () => {
                wfa.action(
                    action.core.updateRecord,
                    { $id: Now.ID['assign_general_team'], annotation: 'Assign to general team' },
                    { record: _params.trigger.current, table_name: 'incident', values: 'assignment_group=general_team' }
                )
            }
        )
    }

    This example iterates through a list of problem records to find unassigned records, assign them to a problem triage group, and send an email to the group.

    // Flow body showing forEach usage with lookUpRecords
    (_params) => {
        //Find all the newly created problem records for the past day
        const problems = wfa.action(
            action.core.lookUpRecords,
            {
                $id: Now.ID['daily_unassigned_new_problems_triage_flow_step1'],
                annotation: 'Find all the newly created problem records for the past day',
            },
            {
                table: 'problem',
                conditions:
                    'sys_created_onONYesterday@javascript:gs.beginningOfYesterday()@javascript:gs.endOfYesterday()',
            }
        )
    
        //Iterate over the problems
        wfa.flow_logic.forEach(
            problems.Records,
            { $id: Now.ID['daily_unassigned_new_problems_triage_flow_step2'], annotation: 'Iterate each problem' },
            (item) => {
                //Check if the problem is not assigned
                wfa.flow_logic.if(
                    {
                        $id: Now.ID['daily_unassigned_new_problems_triage_flow_step3'],
                        condition: `\${item.assignment_group}ISEMPTY`,
                        annotation: 'Check if problem is not assigned',
                    },
                    () => {
                        wfa.action(
                            action.core.updateRecord,
                            {
                                $id: Now.ID['daily_unassigned_new_problems_triage_flow_step4'],
                                annotation: 'Update the problem record state',
                            },
                            { table_name: 'problem', record: item, values: 'state=1' }
                        )
    
                        //Send notification to the group
                        wfa.action(
                            action.core.sendNotification,
                            {
                                $id: Now.ID['daily_unassigned_new_problems_triage_flow_step5'],
                                annotation: 'Send notification to the group',
                            },
                            {
                                table_name: 'problem',
                                record: item,
                                notification: '',
                            }
                        )
                    }
                )
            }
        )
    }

    This example sets flow variables to dynamic values stored in data pills.

    import { FlowVariables } from '@servicenow/sdk/automation'
    
    const flowVars = FlowVariables({
        incidentPriority: IntegerColumn({ label: 'Incident Priority' }),
        assignedGroup: StringColumn({ label: 'Assigned Group' }),
        threshold: IntegerColumn({ label: 'Threshold' }),
        actionResult: StringColumn({ label: 'Action Result' }),
    })
    
    (_params) => {
        // Lookup action result
        const lookupResult = wfa.action(
            action.core.lookUpRecord,
            { $id: Now.ID['lookup_config'], annotation: 'Get configuration' },
            { table: 'sys_properties', conditions: 'name=incident.threshold' }
        )
    
        // Set flow variables using datapills from trigger, action outputs, and other flow variables
        wfa.flow_logic.setFlowVariables(
            {
                $id: Now.ID['set_variables_with_datapills'],
                annotation: 'Set variables from trigger and action outputs',
            },
            _params.flowVariables,
            {
                incidentPriority: _params.trigger.current.priority,        // Trigger datapill
                assignedGroup: _params.trigger.current.assignment_group,   // Trigger datapill
                threshold: lookupResult.Record.value,                      // Action output datapill
                actionResult: _params.flowVariables.status,                // Flow variable datapill
            }
        )
    }

    This exampe assign subflow Outputs using flow variables.

    // Flow body showing assignSubflowOutputs usage with flow variables
    import { FlowVariables } from '@servicenow/sdk/automation'
    
    const flowVars = FlowVariables({
        userEmail: StringColumn({ label: 'User Email' }),
        userName: StringColumn({ label: 'User Name' }),
        isApproved: BooleanColumn({ label: 'Is Approved' }),
    })
    
    (_params) => {
        // Call a subflow that returns user information
        const subflowResult = wfa.subflow(
            userInfoSubflow,
            { $id: Now.ID['get_user_info'], annotation: 'Get user information' },
            { userId: _params.trigger.current.caller_id }
        )
    
        // Assign subflow outputs to flow variables in one operation
        wfa.flow_logic.assignSubflowOutputs(
            { $id: Now.ID['assign_outputs'], annotation: 'Assign user info to flow variables' },
            flowVars,
            {
                userEmail: subflowResult.email,
                userName: subflowResult.name,
                isApproved: subflowResult.approved,
            }
        )
    
        // Now flow variables can be used throughout the flow
        // Access via _params.flowVariables.userEmail, etc.
    }

    wfa.dataPill function

    Reference a specific runtime data pill value from an action or flow logic input.

    Add wfa.dataPill functions to the input parameters of a action or flow_logic function.

    Tableau 6. Properties
    Name Type Description
    expression String Required. Dot notation reference to the runtime data that you want use as an input value. Commonly used runtime values include trigger data, action outputs, and subflow outputs.
    Trigger record data
    Field values from a trigger record. For example, _params.trigger.current.fieldName.
    Trigger record table
    Table name of the trigger record. For example, _params.trigger.table_name.
    Action output values
    Output values from previously run actions. For example, actionResult.fieldName
    Subflow output values
    Output values from previously run subflows. For example, subflowResult.fieldName
    Type String Required. Data type of the data such as string, boolean, integer, or reference. For a list of available field data types, see Field types reference.

    This example uses trigger record values to populate inputs in a send email action.

    import { Flow, wfa, trigger, action } from "@servicenow/sdk/automation";
    
    Flow(
      {
        $id: Now.ID["incident_escalation_flow"],
        name: "Incident Escalation with DataPills"
      },
      wfa.trigger(
        trigger.record.created,
        { $id: Now.ID["incident_created"] },
        { table: "incident", condition: "priority=1" }
      ),
      _params => {
        wfa.action(
          action.core.sendEmail,
          { $id: Now.ID["send_email"] },
          {
            ah_to: wfa.dataPill(
              _params.trigger.current.assigned_to.manager.email,
              "string"
            ),
            ah_subject: `Critical: ${wfa.dataPill(_params.trigger.current.number, "integer")}`,
            ah_body: `Incident ${wfa.dataPill(_params.trigger.current.number, "integer")} requires attention.
              Description: ${wfa.dataPill(_params.trigger.current.short_description, "string")}
              Caller: ${wfa.dataPill(_params.trigger.current.caller_id.name, "string")}`,
            record: wfa.dataPill(_params.trigger.current, "reference"),
            table_name: "incident"
          }
        );
      }
    );

    This example uses dot notation to reference field values from related tables.

    Flow(
      {
        $id: Now.ID["manager_notification_flow"],
        name: "Multi-Level Manager Notification"
      },
      wfa.trigger(
        trigger.record.created,
        { $id: Now.ID["trigger"] },
        { table: "incident" }
      ),
      _params => {
        // Single-level dot-walk
        wfa.action(
          action.core.sendEmail,
          { $id: Now.ID["notify_manager"] },
          {
            ah_to: wfa.dataPill(
              _params.trigger.current.assigned_to.manager.email,
              "string"
            ),
            ah_subject: "Team Assignment",
            ah_body: `Team member ${wfa.dataPill(_params.trigger.current.assigned_to.name, "string")} assigned`,
            record: wfa.dataPill(_params.trigger.current, "reference"),
            table_name: "incident"
          }
        );
    
        // Multi-level dot-walk (4 levels)
        wfa.action(
          action.core.log,
          { $id: Now.ID["log_skip_manager"] },
          {
            log_level: "info",
            log_message: `Skip manager: ${wfa.dataPill(_params.trigger.current.caller_id.manager.manager.manager.name, "string")}`
          }
        );
      }
    );

    This example references runtime values from a create record action.

    Flow(
      {
        $id: Now.ID["task_creation_flow"],
        name: "Task Creation with Output DataPills"
      },
      wfa.trigger(
        trigger.record.created,
        { $id: Now.ID["trigger"] },
        { table: "incident" }
      ),
      _params => {
        const newTask = wfa.action(
          action.core.createRecord,
          { $id: Now.ID["create_task"] },
          {
            table_name: "task",
            values: TemplateValue({
              short_description: "Follow-up task",
              parent: wfa.dataPill(_params.trigger.current, "reference")
            })
          }
        );
    
        wfa.action(
          action.core.updateRecord,
          { $id: Now.ID["assign_task"] },
          {
            table_name: "task",
            record: wfa.dataPill(newTask.Record, "reference"),
            values: TemplateValue({
              assigned_to: wfa.dataPill(
                _params.trigger.current.assigned_to.sys_id,
                "reference"
              )
            })
          }
        );
      }
    );

    This example references runtime values from a look up records action.

    Flow(
      {
        $id: Now.ID["ci_update_flow"],
        name: "Update Multiple CIs"
      },
      wfa.trigger(
        trigger.record.created,
        { $id: Now.ID["trigger"] },
        { table: "change_request" }
      ),
      _params => {
        const cis = wfa.action(
          action.core.lookUpRecords,
          { $id: Now.ID["get_cis"] },
          { table: "cmdb_ci", conditions: "install_status=1" }
        );
    
        wfa.flowLogic.forEach(
          wfa.dataPill(cis.Records, "records"),
          { $id: Now.ID["process_ci"] },
          ci => {
            wfa.action(
              action.core.createTask,
              { $id: Now.ID["create_task"] },
              {
                task_table: "task",
                field_values: TemplateValue({
                  short_description: `Verify: ${wfa.dataPill(ci.name, "string")}`,
                  cmdb_ci: wfa.dataPill(ci.sys_id, "reference")
                })
              }
            );
          }
        );
      }
    );