플로우 API - ServiceNow Fluent

  • 릴리스 버전: Australia
  • 업데이트 날짜 2026년 03월 12일
  • 소요 시간: 62분
  • 플로우 API는 재사용 가능한 다단계 구성요소로 비즈니스 프로세스를 자동화하는 플로우 및 하위 플로우[sys_hub_flow]를 정의합니다.

    주:
    최신 ServiceNow Fluent API 설명서 및 예제는 ServiceNow Fluent API 참조ServiceNow SDK 예제 리포지토리 는 의 위치에 있습니다 GitHub.

    Flow 객체를 사용하여 흐름을 생성합니다. 자세한 내용은 플로우 객체 문서를 참조하십시오.

    하위 플로우 객체를 사용하여 하위 플로우를 생성합니다. 자세한 내용은 하위 플로우 객체 문서를 참조하십시오.

    플로우에 대한 일반 정보는 다음 문서를 참조하십시오 Exploring flows. 하위 플로우에 대한 일반적인 정보는 다음 문서를 참조하십시오 Exploring subflows.

    플로우 객체

    트리거 조건 세트가 발생할 때 플로우 [sys_hub_flow]을 생성하여 일련의 작업과 플로우 논리를 실행합니다.

    트리거 조건이 충족될 때만 플로우가 실행됩니다. 일관되고 미리 정의된 트리거가 필요한 이벤트 기반 자동화에 플로우를 사용합니다.

    플로우 객체는 다음 구성요소로 구성됩니다.
    • 플로우 구성 속성을 정의하는 하나의 구성 객체입니다.
    • 플로우를 실행할 시기를 정의하는 하나의 wfa.trigger 함수입니다.
    • 실행할 작업과 플로우 논리를 정의하는 OneBody 함수입니다.
      • 0개 이상의 wfa.action 함수
      • 0개 이상의 wfa.flow_logic 함수
    표 1. 속성
    이름 유형 설명
    구성 객체 필수 Fluent 객체 또는 함수에 대한 메타데이터 구성 속성을 포함하는 객체입니다.
    $id 문자열 또는 숫자 필수 메타데이터 객체의 고유 ID입니다. 애플리케이션을 빌드할 때 이 ID는 고유한 sys_id으로 해시됩니다. 자세한 내용은 ServiceNow Fluent 언어 구성 문서를 참조하십시오.

    형식: Now.ID['문자열' 또는 숫자]

    이름 문자열 필수 플로우의 표시 이름입니다. 플로우 이름은 목적을 쉽게 식별할 수 있도록 의미 있고 설명적이어야 합니다.
    설명 문자열 플로우가 수행하는 작업에 대한 설명입니다.
    runAs 문자열

    플로우 작업이 실행되는 사용자 컨텍스트를 결정합니다. 시스템 사용자 설정은 역할 기반 ACL을 무시하는 권한 있는 사용자로 실행됩니다. 사용자 설정은 플로우를 시작한 사용자의 권한과 역할로 실행됩니다.

    유효한 값: 시스템, 사용자

    기본값: user

    runWithRoles 문자열 플로우가 실행되는 동안 사용하는 역할을 지정합니다. 역할을 사용하여 플로우를 실행하는 방법에 대한 자세한 내용은 다음 문서를 참조하십시오 Flow roles.
    flowPriority 문자열

    플로우 엔진에서 플로우의 실행 우선순위를 정의합니다.

    유효한 값: 낮음, 중간, 높음

    기본값: 중간

    보호 문자열

    플로우가 읽기 전용(읽기)인지 아니면 편집 가능(빈 문자열)인지 정의합니다.

    유효한 값: read, ''

    기본값: ''

    접근 문자열

    플로우가 공용인지 비공개인지 정의합니다.

    유효한 값: 공개, package_private

    기본값: 공개

    flowVariables 객체 열 유형을 사용하여 플로우에 사용할 수 있는 데이터 변수를 정의하는 객체입니다. get_table_schema 함수를 사용하여 필드 정의를 가져옵니다.
    wfa.트리거 함수 플로우를 실행할 시기를 정의합니다. 트리거 조건이 충족되면 시스템은 트리거에서 제공된 데이터를 사용하여 플로우를 실행합니다. 함수에 대한 자세한 내용은 wfa.trigger 문서를 참조하십시오 wfa.trigger 함수.
    플로우 본문 함수
    Flow bodyArrow function 플로우의 실행 단계를 나타내는 In TypeScript입니다. 플로우 본문은 및 flowVariables 객체를 포함하는 wfa.trigger 입력으로 매개변수를 수신 params 합니다. 의 단계는 다음 함수 유형으로 구성됩니다.Flow body
    • wfa.action 기능: 기록 생성, 이메일 전송, 승인 요청 또는 외부 시스템과의 통합과 같은 플로우 내에서 특정 작업 및 작업을 실행합니다. wfa.action 함수에 대한 자세한 내용은 다음 문서를 참조하십시오wfa.action 함수.
    • wfa.flow_logic function: 플로우 실행 방법을 제어하여 조건부 분기, 반복 및 플로우 구조화 기능을 제공합니다. wfa.flow_logic 함수에 대한 자세한 내용은 다음 문서를 참조하십시오wfa.flow_logic 기능.

    이러한 매개변수 값은 플로우 본문 기능에 사용할 수 있습니다.

    매개변수.트리거.현재
    데이터 유형: 기록. 기록 생성, 기록 업데이트 또는 기록 플로우 생성/업데이트를 시작한 현재 기록을 저장하는 매개변수입니다.
    매개변수.트리거.이전
    데이터 유형: 기록. 기록 업데이트 플로우를 시작한 이전 기록 값을 저장하는 매개변수입니다.
    params.trigger.table_name
    데이터 유형: 문자열. 플로우를 시작한 현재 기록의 테이블 이름을 저장하는 매개변수입니다.
    params.trigger.flowVariables
    데이터 유형: 객체. 이 플로우에 정의된 플로우 변수를 저장하는 매개변수입니다.

    이 예에서는 빈 원본 필드 값으로 인시던트가 생성될 때 실행되는 플로우를 만듭니다. 플로우는 인시던트 심각도에 따라 관리자와 팀 구성원에게 경보를 보냅니다.

    import { action, Flow, wfa, trigger } from '@servicenow/sdk/automation'
    
    export const incidentSeverityAlertFlow = Flow(
        {
            $id: Now.ID['incident_severity_alert_flow'],
            name: 'Incident Severity Alert Flow',
            description: 'Alerts managers and team members based on incident severity for incidents with empty origin',
        },
        wfa.trigger(
            trigger.record.created,
            { $id: Now.ID['empty_origin_incident_trigger'] },
            {
                table: 'incident',
                condition: 'origin=NULL',
                run_flow_in: 'background',
                run_on_extended: 'false',
                run_when_setting: 'both',
                run_when_user_setting: 'any',
                run_when_user_list: [],
            }
        ),
        (params) => {
            wfa.action(
                action.core.log,
                { $id: Now.ID['log_incident_short_description'] },
                {
                    log_level: 'info',
                    log_message: `Incident created: ${wfa.dataPill(params.trigger.current.short_description, 'string')}`,
                }
            )
    
            wfa.flowLogic.if(
                {
                    $id: Now.ID['check_severity_high'],
                    condition: `${wfa.dataPill(params.trigger.current.severity, 'string')}=1`,
                    annotation: 'High severity (1)',
                },
                () => {
                    const assignmentGroup = wfa.action(
                        action.core.lookUpRecord,
                        { $id: Now.ID['lookup_assignment_group'] },
                        {
                            table: 'sys_user_group',
                            conditions: `sys_id=${wfa.dataPill(params.trigger.current.assignment_group, 'reference')}`,
                            sort_type: 'sort_asc',
                            if_multiple_records_are_found_action: 'use_first_record',
                        }
                    )
    
                    const manager = wfa.action(
                        action.core.lookUpRecord,
                        { $id: Now.ID['lookup_manager_details'] },
                        {
                            table: 'sys_user',
                            conditions: `sys_id=${wfa.dataPill(assignmentGroup.Record.manager, 'reference')}`,
                            sort_type: 'sort_asc',
                            if_multiple_records_are_found_action: 'use_first_record',
                        }
                    )
    
                    wfa.action(
                        action.core.sendNotification,
                        { $id: Now.ID['send_urgent_email_to_manager'] },
                        {
                            table_name: 'incident',
                            record: wfa.dataPill(params.trigger.current.sys_id, 'reference'),
                            notification: 'high_severity_incident_manager_notification',
                        }
                    )
    
                    wfa.flowLogic.forEach(
                        wfa.dataPill(params.trigger.current.additional_assignee_list, 'array.string'),
                        { $id: Now.ID['foreach_additional_assignees_high'] },
                        () => {
                            const assignee = wfa.action(
                                action.core.lookUpRecord,
                                { $id: Now.ID['lookup_assignee_details_high'] },
                                {
                                    table: 'sys_user',
                                    conditions: `sys_id=${wfa.dataPill(params.trigger.current.additional_assignee_list, 'array.string')}`,
                                    sort_type: 'sort_asc',
                                    if_multiple_records_are_found_action: 'use_first_record',
                                }
                            )
    
                            wfa.action(
                                action.core.sendSms,
                                { $id: Now.ID['send_sms_to_assignee_high'] },
                                {
                                    recipients: `${wfa.dataPill(assignee.Record.phone, 'string')}`,
                                    message: `High severity incident: ${wfa.dataPill(params.trigger.current.short_description, 'string')}`,
                                }
                            )
                        }
                    )
    
                    wfa.action(
                        action.core.updateRecord,
                        { $id: Now.ID['update_work_notes_high'] },
                        {
                            table_name: 'incident',
                            record: wfa.dataPill(params.trigger.current.sys_id, 'reference'),
                            values: TemplateValue({
                                work_notes: `Manager ${wfa.dataPill(manager.Record.name, 'string')} notified via email and team notified via SMS.`,
                            }),
                        }
                    )
                }
            )
    
            wfa.flowLogic.elseIf(
                {
                    $id: Now.ID['check_severity_medium'],
                    condition: `${wfa.dataPill(params.trigger.current.severity, 'string')}=2`,
                    annotation: 'Medium severity (2)',
                },
                () => {
                    wfa.flowLogic.forEach(
                        wfa.dataPill(params.trigger.current.additional_assignee_list, 'array.string'),
                        { $id: Now.ID['foreach_additional_assignees_medium'] },
                        () => {
                            const assignee = wfa.action(
                                action.core.lookUpRecord,
                                { $id: Now.ID['lookup_assignee_details_medium'] },
                                {
                                    table: 'sys_user',
                                    conditions: `sys_id=${wfa.dataPill(params.trigger.current.additional_assignee_list, 'array.string')}`,
                                    sort_type: 'sort_asc',
                                    if_multiple_records_are_found_action: 'use_first_record',
                                }
                            )
    
                            wfa.action(
                                action.core.sendSms,
                                { $id: Now.ID['send_sms_to_assignee_medium'] },
                                {
                                    recipients: `${wfa.dataPill(assignee.Record.phone, 'string')}`,
                                    message: `Medium severity incident: ${wfa.dataPill(params.trigger.current.short_description, 'string')}`,
                                }
                            )
                        }
                    )
                }
            )
    
            wfa.action(
                action.core.updateRecord,
                { $id: Now.ID['update_incident_to_in_progress'] },
                {
                    table_name: 'incident',
                    record: wfa.dataPill(params.trigger.current.sys_id, 'reference'),
                    values: TemplateValue({ state: '2' }),
                }
            )
        }
    )

    이 예시는 변경 요청이 승인되고 요청자에게 알릴 때 실행됩니다.

    import { action, Flow, wfa, trigger } from '@servicenow/sdk/automation'
    
    export const changeRequestApprovalNotificationFlow = Flow(
        {
            $id: Now.ID['change_request_approval_notification_flow'],
            name: 'Change Request Approval Notification Flow',
            description: 'Sends formatted notification to requester when change request is approved',
        },
        wfa.trigger(
            trigger.record.updated,
            { $id: Now.ID['change_request_approved_trigger'] },
            {
                table: 'change_request',
                condition: 'approval=approved',
                run_flow_in: 'background',
                trigger_strategy: 'unique_changes',
                run_when_user_list: [],
                run_when_setting: 'both',
                run_on_extended: 'false',
                run_when_user_setting: 'any',
            }
        ),
        (params) => {
            const requester = wfa.action(
                action.core.lookUpRecord,
                { $id: Now.ID['lookup_requester_details'] },
                {
                    table: 'sys_user',
                    conditions: `sys_id=${wfa.dataPill(params.trigger.current.requested_by, 'reference')}`,
                    sort_type: 'sort_asc',
                    if_multiple_records_are_found_action: 'use_first_record',
                }
            )
    
            wfa.action(
                action.core.sendEmail,
                { $id: Now.ID['send_approval_notification_email'] },
                {
                    table_name: 'change_request',
                    watermark_email: true,
                    ah_subject: `Change Request ${wfa.dataPill(params.trigger.current.number, 'string')} - Approved`,
                    ah_body: `Your change request has been approved.`,
                    record: wfa.dataPill(params.trigger.current.sys_id, 'reference'),
                    ah_to: wfa.dataPill(requester.Record.email, 'string'),
                }
            )
    
            wfa.action(
                action.core.updateRecord,
                { $id: Now.ID['update_work_notes_notification_sent'] },
                {
                    table_name: 'change_request',
                    record: wfa.dataPill(params.trigger.current.sys_id, 'reference'),
                    values: TemplateValue({
                        work_notes: `Approval notification sent to ${wfa.dataPill(requester.Record.name, 'string')} (${wfa.dataPill(requester.Record.email, 'string')})`,
                    }),
                }
            )
        }
    )

    하위 플로우 객체

    하위 플로우 [sys_hub_flow]를 생성하여 플로우 또는 API에서 호출될 때 작업 및 플로우 논리의 재사용 시퀀스를 실행합니다.

    하위 플로우는 플로우 또는 API에서 호출할 때 실행됩니다. 여러 플로우에서 호출할 수 있는 요청 시 자동화를 위해 하위 플로우를 사용합니다.

    하위 플로우는 다음 구성요소로 구성됩니다.
    • 하위 플로우 구성 속성을 정의하는 하나의 구성 객체입니다.
      • 하위 플로우 입력을 정의하는 0개 또는 1개의 입력 객체입니다.
      • 하위 플로우 출력을 정의하는 0개 또는 1개의 출력 객체입니다.
      • 플로우 변수를 정의하는 0개 또는 1개의 플로우 변수 객체입니다.
    • 실행할 작업, 플로우 로직 및 하위 플로우를 정의하는 One Body 함수입니다.
      • 0개 이상의 wfa.action 함수
      • 0개 이상의 wfa.flow_logic 함수
    표 2. 속성
    이름 유형 설명
    구성 객체 필수 Fluent 객체 또는 함수에 대한 메타데이터 구성 속성을 포함하는 객체입니다.
    $id 문자열 또는 숫자 필수 메타데이터 객체의 고유 ID입니다. 애플리케이션을 빌드할 때 이 ID는 고유한 sys_id으로 해시됩니다. 자세한 내용은 ServiceNow Fluent 언어 구성 문서를 참조하십시오.

    형식: Now.ID['문자열' 또는 숫자]

    이름 문자열 필수 하위 플로우의 표시 이름입니다. 하위 플로우 이름은 목적을 쉽게 식별할 수 있도록 의미 있고 설명적이어야 합니다. 이 속성은 하위 플로우 구성 객체의 일부입니다.
    설명 문자열 플로우가 수행하는 작업에 대한 설명입니다. 이 속성은 하위 플로우 구성 객체의 일부입니다.
    runAs 문자열

    하위 플로우 작업이 실행되는 사용자 컨텍스트를 결정합니다.

    유효한 값: 시스템, 사용자

    기본값: user

    이 속성은 하위 플로우 구성 객체의 일부입니다.

    runWithRoles 배열 실행 중에 하위 흐름이 사용할 역할을 지정합니다. 이 속성은 하위 플로우 구성 객체의 일부입니다.
    flowPriority 문자열

    플로우 엔진에서 하위 플로우의 실행 우선순위를 정의합니다.

    유효한 값: 낮음, 중간, 높음

    기본값: 중간

    이 속성은 하위 플로우 구성 객체의 일부입니다.

    보호 문자열

    하위 플로우가 읽기 전용(읽기)인지 아니면 편집 가능(빈 문자열)인지 정의합니다.

    유효한 값: 읽기, " "

    이 속성은 하위 플로우 구성 객체의 일부입니다.

    접근 문자열

    다른 하위 플로우 작성자에 대한 하위 플로우의 가시성/접근성을 정의합니다.

    유효한 값: 공개, package_private

    기본값: 공개

    이 속성은 하위 플로우 구성 객체의 일부입니다.

    범주 문자열 하위 플로우를 구성하기 위한 범주입니다. 이 속성은 하위 플로우 구성 객체의 일부입니다.
    입력 객체 열 유형을 사용하여 입력 매개변수를 정의하는 객체입니다. 이 속성은 하위 플로우 구성 객체의 일부입니다.
    출력 객체 열 유형을 사용하여 출력 매개변수를 정의하는 객체입니다. 이 속성은 하위 플로우 구성 객체의 일부입니다.
    flowVariables 객체 열 유형을 사용하여 하위 플로우에 사용할 수 있는 데이터 변수를 정의하는 객체입니다. 이 속성은 하위 플로우 구성 객체의 일부입니다.
    플로우 본문 함수
    Flow bodyArrow function 플로우의 실행 단계를 나타내는 In TypeScript입니다. 플로우 본문은 및 flowVariables 객체를 포함하는 inputs 입력으로 매개변수를 수신 _params 합니다. 의 단계는 다음 함수 유형으로 구성됩니다.Flow body
    • wfa.action 기능: 기록 생성, 이메일 전송, 승인 요청 또는 외부 시스템과의 통합과 같은 플로우 내에서 특정 작업 및 작업을 실행합니다. wfa.action 함수에 대한 자세한 내용은 다음 문서를 참조하십시오wfa.action 함수.
    • wfa.flow_logic function: 플로우 실행 방법을 제어하여 조건부 분기, 반복 및 플로우 구조화 기능을 제공합니다. wfa.flow_logic 함수에 대한 자세한 내용은 다음 문서를 참조하십시오wfa.flow_logic 기능.

    이러한 매개변수 값은 플로우 본문 기능에 사용할 수 있습니다.

    _params.trigger.current
    데이터 유형: 기록. 기록 생성, 기록 업데이트 또는 기록 플로우 생성/업데이트를 시작한 현재 기록을 저장하는 매개변수입니다.
    _params.trigger.previous
    데이터 유형: 기록. 기록 업데이트 플로우를 시작한 이전 기록 값을 저장하는 매개변수입니다.
    _params.trigger.table_name
    데이터 유형: 문자열. 플로우를 시작한 현재 기록의 테이블 이름을 저장하는 매개변수입니다.
    _params.trigger.flowVariables
    데이터 유형: 객체. 이 플로우에 정의된 플로우 변수를 저장하는 매개변수입니다.

    이 예시에서는 새 사용자의 이름과 사무실 위치를 사용하여 사용자 기록을 조회하고, 환영 알림을 보내고, 할당되지 않은 하드웨어 자산과 사용 가능한 사무실 위치를 조회합니다. 사용 가능한 노트북 자산과 사무실 위치가 있는 경우 각각 새 사용자에게 할당됩니다.

    import { Subflow, action, wfa } from '@servicenow/sdk/automation'
    import { BooleanColumn, ReferenceColumn, StringColumn } from '@servicenow/sdk/core'
    
    export const newUserOnboardingSubflow = Subflow(
        {
            $id: Now.ID['new_user_onboarding_subflow'],
            name: 'New User Onboarding Subflow',
            description: 'Sends welcome notification, assigns laptop and desk, returns assignment results',
            inputs: {
                user_sys_id: ReferenceColumn({
                    label: 'User',
                    referenceTable: 'sys_user',
                    mandatory: true,
                }),
                office_location: ReferenceColumn({
                    label: 'Office Location',
                    referenceTable: 'cmn_location',
                    mandatory: true,
                }),
            },
            outputs: {
                laptop_assigned: BooleanColumn({ label: 'Laptop Assigned' }),
                desk_assigned: BooleanColumn({ label: 'Desk Assigned' }),
                laptop_number: StringColumn({ label: 'Laptop Asset Number', maxLength: 40 }),
                desk_number: StringColumn({ label: 'Desk Asset Number', maxLength: 40 }),
            },
            flowVariables: {
                laptop_found: BooleanColumn({ label: 'Laptop Found Flag', default: false }),
                desk_found: BooleanColumn({ label: 'Desk Found Flag', default: false }),
            },
        },
        (params) => {
            const user = wfa.action(
                action.core.lookUpRecord,
                { $id: Now.ID['lookup_user'] },
                {
                    table: 'sys_user',
                    conditions: `sys_id=${wfa.dataPill(params.inputs.user_sys_id, 'reference')}`,
                    sort_type: 'sort_asc',
                    if_multiple_records_are_found_action: 'use_first_record',
                }
            )
    
            wfa.action(
                action.core.sendNotification,
                { $id: Now.ID['send_welcome_notification'] },
                {
                    table_name: 'sys_user',
                    record: wfa.dataPill(params.inputs.user_sys_id, 'reference'),
                    notification: 'new_user_welcome_notification',
                }
            )
    
            const availableLaptop = wfa.action(
                action.core.lookUpRecord,
                { $id: Now.ID['lookup_available_laptop'] },
                {
                    table: 'alm_hardware',
                    conditions: 'assigned_to=NULL^install_status=1^substatus=available',
                    sort_type: 'sort_asc',
                    if_multiple_records_are_found_action: 'use_first_record',
                }
            )
    
            wfa.flowLogic.if(
                {
                    $id: Now.ID['check_laptop_available'],
                    condition: `${wfa.dataPill(availableLaptop.Record.sys_id, 'reference')}!=NULL`,
                    annotation: 'Available laptop found',
                },
                () => {
                    wfa.action(
                        action.core.updateRecord,
                        { $id: Now.ID['assign_laptop'] },
                        {
                            table_name: 'alm_hardware',
                            record: wfa.dataPill(availableLaptop.Record.sys_id, 'reference'),
                            values: TemplateValue({
                                assigned_to: wfa.dataPill(params.inputs.user_sys_id, 'reference'),
                                install_status: '2',
                                substatus: 'in_use',
                            }),
                        }
                    )
                }
            )
    
            wfa.flowLogic.else(
                { $id: Now.ID['no_laptop_available'] },
                () => {
                    wfa.action(
                        action.core.log,
                        { $id: Now.ID['log_no_laptop'] },
                        {
                            log_level: 'warn',
                            log_message: `No available laptop found for ${wfa.dataPill(user.Record.name, 'string')} — manual assignment required.`,
                        }
                    )
                }
            )
    
            const availableDesk = wfa.action(
                action.core.lookUpRecord,
                { $id: Now.ID['lookup_available_desk'] },
                {
                    table: 'alm_asset',
                    conditions: `assigned_to=NULL^location=${wfa.dataPill(params.inputs.office_location, 'reference')}^install_status=1^substatus=available`,
                    sort_type: 'sort_asc',
                    if_multiple_records_are_found_action: 'use_first_record',
                }
            )
    
            wfa.flowLogic.if(
                {
                    $id: Now.ID['check_desk_available'],
                    condition: `${wfa.dataPill(availableDesk.Record.sys_id, 'reference')}!=NULL`,
                    annotation: 'Available desk found at office location',
                },
                () => {
                    wfa.action(
                        action.core.updateRecord,
                        { $id: Now.ID['assign_desk'] },
                        {
                            table_name: 'alm_asset',
                            record: wfa.dataPill(availableDesk.Record.sys_id, 'reference'),
                            values: TemplateValue({
                                assigned_to: wfa.dataPill(params.inputs.user_sys_id, 'reference'),
                                install_status: '2',
                                substatus: 'in_use',
                            }),
                        }
                    )
                }
            )
    
            wfa.flowLogic.else(
                { $id: Now.ID['no_desk_available'] },
                () => {
                    wfa.action(
                        action.core.log,
                        { $id: Now.ID['log_no_desk'] },
                        {
                            log_level: 'warn',
                            log_message: `No available desk at office location for ${wfa.dataPill(user.Record.name, 'string')} — manual assignment required.`,
                        }
                    )
                }
            )
    
            wfa.action(
                action.core.sendNotification,
                { $id: Now.ID['send_onboarding_complete'] },
                {
                    table_name: 'sys_user',
                    record: wfa.dataPill(params.inputs.user_sys_id, 'reference'),
                    notification: 'user_onboarding_complete_notification',
                }
            )
    
            wfa.flowLogic.assignSubflowOutputs(
                {
                    $id: Now.ID['assign_outputs'],
                    annotation: 'Return laptop and desk assignment results',
                },
                params.outputs,
                {
                    laptop_assigned: true,
                    desk_assigned: true,
                    laptop_number: wfa.dataPill(availableLaptop.Record.asset_tag, 'string'),
                    desk_number: wfa.dataPill(availableDesk.Record.asset_tag, 'string'),
                }
            )
        }
    )

    wfa.trigger 함수

    특정 트리거 유형의 시작 조건이 충족되면 플로우를 실행합니다. 트리거는 플로우가 실행되는 시기와 플로우 시작 조건에서 사용할 수 있는 데이터를 결정합니다.

    wfa.trigger 함수를 Flow 객체의 함수에 Flow Body 추가합니다.

    다음과 같은 유형의 작업 인스턴스가 지원됩니다.
    • 트리거.기록.생성됨
    • 트리거.기록.업데이트됨
    • trigger.record.createdOrUpdated
    • trigger.scheduled.daily 트리거
    • trigger.scheduled.weekly
    • trigger.scheduled.monthly
    • 트리거.예약됨.반복
    • trigger.scheduled.runOnce
    • trigger.application.inboundEmail
    • trigger.application.slaTask
    • trigger.application.knowledgeManagement
    • trigger.application.remoteTableQuery
    .

    사용 가능한 작업에 대한 자세한 내용은 다음 문서를 참조하십시오 Workflow Studio flow trigger types.

    표 3. 속성
    이름 유형 설명
    트리거 문자열 실행할 특정 트리거의 이름입니다. 모든 작업 이름은 트리거로 시작하는 점 표기법을 사용합니다. 예를 들어 trigger.record.created, trigger.scheduled.daily 또는 trigger.application.serviceCatalog입니다.
    구성 객체 필수 Fluent 객체 또는 함수에 대한 메타데이터 구성 속성을 포함하는 객체입니다.
    $id 문자열 또는 숫자 필수 메타데이터 객체의 고유 ID입니다. 애플리케이션을 빌드할 때 이 ID는 고유한 sys_id으로 해시됩니다. 자세한 내용은 ServiceNow Fluent 언어 구성 문서를 참조하십시오.

    형식: Now.ID['문자열' 또는 숫자]

    입력 객체 트리거에 필요한 입력 매개변수( 예: 테이블 또는 조건)를 포함하는 객체입니다.

    이 예에서는 우선순위가 높은 인시던트 기록이 생성될 때 플로우를 실행합니다.

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

    이 예시에서는 매일 오전 9시에 플로우를 시작합니다.

    // ✅ 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 })
        }
    )

    다음 예에서는 인시던트 기록에 대한 이메일 회신이 있을 때 플로우를 시작합니다.

    // 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 함수

    플로우 또는 하위 플로우에서 특정 작업 인스턴스를 실행합니다. 작업은 생성, 업데이트 또는 검색할 데이터를 결정합니다.

    플로우 또는 하위 플로우 객체의 함수에 Flow Bodywfa.action 함수를 추가합니다.

    다음과 같은 유형의 작업 인스턴스가 지원됩니다.
    • 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
    .

    사용 가능한 작업에 대한 자세한 내용은 다음 문서를 참조하십시오 Workflow Studio actions.

    표 4. 속성
    이름 유형 설명
    작업 문자열 실행할 특정 작업의 이름입니다. 모든 작업 이름은 action.core로 시작하는 점 표기법을 사용합니다. 예를 들어 action.core.lookUpRecord, action.core.lookUpRecords, action.core.createRecord 또는 action.core.updateRecord 등이 있습니다.
    구성 객체 필수 Fluent 객체 또는 함수에 대한 메타데이터 구성 속성을 포함하는 객체입니다.
    $id 문자열 또는 숫자 필수 메타데이터 객체의 고유 ID입니다. 애플리케이션을 빌드할 때 이 ID는 고유한 sys_id으로 해시됩니다. 자세한 내용은 ServiceNow Fluent 언어 구성 문서를 참조하십시오.

    형식: Now.ID['문자열' 또는 숫자]

    입력 객체 작업에 필요한 입력 매개변수( 예: table_name또는 값)를 포함하는 객체입니다.

    이 예시는 변경 요청이 승인되고 요청자에게 알릴 때 실행됩니다. 플로우는 기록 조회, 이메일 전송 및 기록 업데이트 작업을 사용합니다.

    import { action, Flow, wfa, trigger } from '@servicenow/sdk/automation'
    
    export const changeRequestApprovalNotificationFlow = Flow(
        {
            $id: Now.ID['change_request_approval_notification_flow'],
            name: 'Change Request Approval Notification Flow',
            description: 'Sends formatted notification to requester when change request is approved',
        },
        wfa.trigger(
            trigger.record.updated,
            { $id: Now.ID['change_request_approved_trigger'] },
            {
                table: 'change_request',
                condition: 'approval=approved',
                run_flow_in: 'background',
                trigger_strategy: 'unique_changes',
                run_when_user_list: [],
                run_when_setting: 'both',
                run_on_extended: 'false',
                run_when_user_setting: 'any',
            }
        ),
        (params) => {
            const requester = wfa.action(
                action.core.lookUpRecord,
                { $id: Now.ID['lookup_requester_details'] },
                {
                    table: 'sys_user',
                    conditions: `sys_id=${wfa.dataPill(params.trigger.current.requested_by, 'reference')}`,
                    sort_type: 'sort_asc',
                    if_multiple_records_are_found_action: 'use_first_record',
                }
            )
    
            wfa.action(
                action.core.sendEmail,
                { $id: Now.ID['send_approval_notification_email'] },
                {
                    table_name: 'change_request',
                    watermark_email: true,
                    ah_subject: `Change Request ${wfa.dataPill(params.trigger.current.number, 'string')} - Approved`,
                    ah_body: `Your change request has been approved.`,
                    record: wfa.dataPill(params.trigger.current.sys_id, 'reference'),
                    ah_to: wfa.dataPill(requester.Record.email, 'string'),
                }
            )
    
            wfa.action(
                action.core.updateRecord,
                { $id: Now.ID['update_work_notes_notification_sent'] },
                {
                    table_name: 'change_request',
                    record: wfa.dataPill(params.trigger.current.sys_id, 'reference'),
                    values: TemplateValue({
                        work_notes: `Approval notification sent to ${wfa.dataPill(requester.Record.name, 'string')} (${wfa.dataPill(requester.Record.email, 'string')})`,
                    }),
                }
            )
        }
    )

    이 예에서는 변경 요청 기록이 높은 영향으로 생성되거나 업데이트될 때 플로우를 실행합니다. 플로우는 기록 업데이트를 실행하여 변경 요청을 높은 위험으로 표시하고, 기록 조회를 실행하여 이름이 CAB인 그룹을 찾고, 알림 보내기를 실행하여 CAB 그룹에 높은 위험 변경 알림을 보내고, 로그 작업을 실행하여 기록 업데이트와 전송된 알림을 모두 문서화합니다.

    import { action, Flow, wfa, trigger } from '@servicenow/sdk/automation'
    
    export const changeRiskTaggingFlow = Flow(
        {
            $id: Now.ID['change_risk_tagging_flow'],
            name: 'Change Risk Tagging Flow',
            description: 'Tags change requests with high-risk label when created or updated with high impact',
        },
        wfa.trigger(
            trigger.record.createdOrUpdated,
            { $id: Now.ID['change_risk_trigger'] },
            {
                table: 'change_request',
                condition: 'active=true^impact=1',
                run_flow_in: 'background',
                run_on_extended: 'false',
                run_when_setting: 'both',
                run_when_user_setting: 'any',
                run_when_user_list: [],
            }
        ),
        (params) => {
            wfa.action(
                action.core.updateRecord,
                { $id: Now.ID['tag_high_risk'] },
                {
                    table_name: 'change_request',
                    record: wfa.dataPill(params.trigger.current.sys_id, 'reference'),
                    values: TemplateValue({
                        risk: 'high',
                        work_notes: 'Automatically tagged as high-risk due to high impact.',
                    }),
                }
            )
    
            const cab = wfa.action(
                action.core.lookUpRecord,
                { $id: Now.ID['lookup_cab_group'] },
                {
                    table: 'sys_user_group',
                    conditions: 'name=CAB^active=true',
                    sort_type: 'sort_asc',
                    if_multiple_records_are_found_action: 'use_first_record',
                }
            )
    
            wfa.action(
                action.core.sendNotification,
                { $id: Now.ID['notify_cab_high_risk'] },
                {
                    table_name: 'change_request',
                    record: wfa.dataPill(params.trigger.current.sys_id, 'reference'),
                    notification: 'high_risk_change_cab_notification',
                }
            )
    
            wfa.action(
                action.core.log,
                { $id: Now.ID['log_risk_tagged'] },
                {
                    log_level: 'warn',
                    log_message: `Change ${wfa.dataPill(params.trigger.current.number, 'string')} tagged as high-risk. CAB group ${wfa.dataPill(cab.Record.name, 'string')} notified.`,
                }
            )
        }
    )

    wfa.flow_logic 기능

    플로우 또는 하위 플로우에서 특정 플로우 논리 인스턴스를 실행합니다. 플로우 로직은 데이터가 사용되는 방법과 시기를 결정합니다.

    플로우 또는 하위 플로우 객체의 기능에 wfa.flow_logic 함수 Flow Body 를 추가합니다.

    다음과 같은 유형의 플로우 논리 인스턴스가 지원됩니다.
    • if
    • elseIf
    • else
    • forEach
    • waitForADuration
    • exitLoop, endFlow, skipIteration, setFlowVariablesassignSubflowOutputs
    .

    사용 가능한 플로우 논리에 대한 자세한 내용은 다음 문서를 참조하십시오 Workflow Studio flow logic.

    표 5. 속성
    이름 유형 설명
    구성 객체 필수 Fluent 객체 또는 함수에 대한 메타데이터 구성 속성을 포함하는 객체입니다.
    $id 문자열 또는 숫자 필수 메타데이터 객체의 고유 ID입니다. 애플리케이션을 빌드할 때 이 ID는 고유한 sys_id으로 해시됩니다. 자세한 내용은 ServiceNow Fluent 언어 구성 문서를 참조하십시오.

    형식: Now.ID['문자열' 또는 숫자]

    주석 문자열 이 플로우 논리 인스턴스가 수행하는 작업을 설명하십시오. 예를 들어, 주석: '우선순위가 중요'입니다.
    조건 문자열 wfa.flow_logic.ifwfa.flow_logic.elseIf 함수에 필요합니다. 이 플로우 논리를 실행하기 위해 예여야 하는 데이터 값입니다. 예: condition: '\${_params.trigger.current.priority}=1',.
    항목 배열 wfa.flow_logic.forEach 함수에 필요합니다. 반복할 배열 또는 기록 컬렉션입니다. 일반적으로 이 기록 목록은 wfa.action 함수 호출에서 action.core.lookUpRecords 작업에 대한 동적으로 생성됩니다. 예를 들어, 문제가 있습니다 . 기록 배열은 action.core.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, { ... }
    레이블 문자열 이 플로우 논리 인스턴스를 설명하는 표시 값입니다. 예를 들어, label: '우선순위가 중요한 경우',.
    variables 스키마 wfa.flow_logic.assignSubflowOutputswfa.flow_logic.setFlowVariables 함수에 필요합니다. 흐름 변수의 데이터 구조를 정의하는 FlowVariables API에서 생성하는 스키마입니다. 예를 들어 flowVars 스키마는 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, { ... }
    중요사항:
    항상 _params.flowVariables를 이 속성의 인수로 사용하십시오. 잘못된 스키마를 전달하면 확인 오류가 발생합니다.
    플로우 논리 본문 함수 Flow logic bodyArrow function 플로우 논리의 실행 단계를 나타내는 TypeScript입니다. 플로우 본문은 및 flowVariables 객체를 포함하는 wfa.trigger 입력으로 매개변수를 수신 _params 합니다. 의 Flow logic body 단계는 다음 함수 호출로 구성됩니다.
    • wfa.action 기능: 플로우 또는 하위 플로우에서 특정 작업 인스턴스를 실행합니다. 작업은 생성, 업데이트 또는 검색할 데이터를 결정합니다.. wfa.action 함수에 대한 자세한 내용은 다음 문서를 참조하십시오wfa.action 함수.
    • wfa.flow_logic 함수: 플로우 또는 하위 플로우에서 특정 플로우 논리 인스턴스를 실행합니다. 플로우 로직은 데이터가 사용되는 방법과 시기를 결정합니다. wfa.flow_logic 함수에 대한 자세한 내용은 다음 문서를 참조하십시오 wfa.flow_logic 기능.

    이 예는 트리거 기록의 조건을 확인하는 방법을 보여줍니다. 현재 기록의 우선순위가 1이면 중요 우선순위 팀에 기록을 할당합니다. 그렇지 않으면 현재 기록의 우선순위 값이 2이면 우선순위가 높은 팀에 기록을 할당합니다. 두 조건 모두 충족되지 않으면 기록이 일반 팀에 할당됩니다.

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

    이 예시에서는 문제 기록 목록을 반복하여 할당되지 않은 기록을 찾고 문제 분류 그룹에 할당하고 그룹에 이메일을 보냅니다.

    // 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: '',
                            }
                        )
                    }
                )
            }
        )
    }

    이 예에서는 플로우 변수를 데이터 알약에 저장된 동적 값으로 설정합니다.

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

    이 시험에서는 플로우 변수를 사용하여 하위 플로우 출력을 할당합니다.

    // 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 함수

    작업 또는 플로우 논리 입력에서 특정 런타임 데이터 알약 값을 참조합니다.

    작업 또는 flow_logic 함수의 입력 매개변수에 wfa.dataPill 함수를 추가합니다. 사용하려는 각 데이터 알약에 대해 상수를 정의합니다. 일반적으로 이 상수는 wfa.action 또는 wfa.flow_logic 함수의 출력을 저장합니다.

    표 6. 속성
    이름 유형 설명
    표현식 문자열 필수 입력 값으로 사용할 런타임 데이터에 대한 점 표기법 참조입니다. 일반적으로 사용되는 런타임 값에는 트리거 데이터, 작업 출력 및 하위 플로우 출력이 포함됩니다.
    트리거 기록 데이터
    트리거 기록의 필드 값입니다. 예: _params.trigger.current.fieldName.
    트리거 기록 테이블
    트리거 기록의 테이블 이름입니다. 예: _params.trigger.table_name.
    작업 출력 값
    이전에 실행된 작업의 출력 값입니다. 예: actionResult.fieldName
    하위 플로우 출력 값
    이전에 실행된 하위 플로우의 출력 값입니다. 예: subflowResult.fieldName
    유형 문자열 필수 문자열, 부울, 정수 또는 참조와 같은 데이터의 데이터 형식입니다. 사용 가능한 필드 데이터 형식의 목록은 다음 문서를 참조하십시오 Field types reference.

    이 예시에서는 언바운딩된 이메일 기록을 사용하여 인바운드 이메일의 값을 기반으로 인시던트 또는 작업을 생성합니다. 이 예시에서는 params 객체를 사용하여 트리거의 데이터를 참조합니다. 또한 이 예에서는 상수 sender, senderManager, p3Incident 및 첨부 파일을 정의하여 나중에 wfa.dataPill 함수에 사용할 작업 및 플로우 논리의 출력을 저장합니다.

    import { action, Flow, wfa, trigger } from '@servicenow/sdk/automation'
    
    export const emailIncidentTaskFlow = Flow(
        {
            $id: Now.ID['email_incident_task_flow'],
            name: 'Email Incident/Task Creation Flow',
            description: 'Creates incidents or tasks based on email content with "raise incident or task" in subject',
        },
        wfa.trigger(
            trigger.application.inboundEmail,
            { $id: Now.ID['inbound_email_trigger'] },
            {
                email_conditions: 'subjectLIKEraise incident or task',
                target_table: 'incident',
            }
        ),
        (params) => {
            wfa.action(
                action.core.log,
                { $id: Now.ID['log_email_received'] },
                {
                    log_level: 'info',
                    log_message: `Email received from: ${wfa.dataPill(params.trigger.from_address, 'string')}, Subject: ${wfa.dataPill(params.trigger.subject, 'string')}`,
                }
            )
    
            const sender = wfa.action(
                action.core.lookUpRecord,
                { $id: Now.ID['lookup_sender'] },
                {
                    table: 'sys_user',
                    conditions: `email=${wfa.dataPill(params.trigger.from_address, 'string')}`,
                    sort_type: 'sort_asc',
                    if_multiple_records_are_found_action: 'use_first_record',
                }
            )
    
            // Internal P1 path — two tasks
            wfa.flowLogic.if(
                {
                    $id: Now.ID['check_internal_p1'],
                    condition: `${wfa.dataPill(sender.Record.email, 'string')}LIKEservicenow^${wfa.dataPill(params.trigger.subject, 'string')}LIKEP1`,
                    annotation: 'Internal sender with P1 subject',
                },
                () => {
                    const senderManager = wfa.action(
                        action.core.lookUpRecord,
                        { $id: Now.ID['lookup_sender_manager'] },
                        {
                            table: 'sys_user',
                            conditions: `sys_id=${wfa.dataPill(sender.Record.manager, 'reference')}`,
                            sort_type: 'sort_asc',
                            if_multiple_records_are_found_action: 'use_first_record',
                        }
                    )
    
                    wfa.action(
                        action.core.createTask,
                        { $id: Now.ID['task_for_manager'] },
                        {
                            task_table: 'incident',
                            field_values: TemplateValue({
                                priority: 1,
                                assigned_to: wfa.dataPill(senderManager.Record.sys_id, 'reference'),
                                short_description: wfa.dataPill(params.trigger.inbound_email.body, 'reference'),
                                urgency: 1,
                                impact: 1,
                            }),
                        }
                    )
    
                    wfa.action(
                        action.core.createTask,
                        { $id: Now.ID['task_for_sender'] },
                        {
                            task_table: 'incident',
                            field_values: TemplateValue({
                                priority: 1,
                                assigned_to: wfa.dataPill(sender.Record.sys_id, 'reference'),
                                short_description: wfa.dataPill(params.trigger.subject, 'string'),
                                urgency: 1,
                                impact: 1,
                            }),
                        }
                    )
                }
            )
    
            // External / non-P1 path — P3 incident + copy attachments
            wfa.flowLogic.else({ $id: Now.ID['create_p3_incident_branch'] }, () => {
                const p3Incident = wfa.action(
                    action.core.createRecord,
                    { $id: Now.ID['create_p3_incident'] },
                    {
                        table_name: 'incident',
                        values: TemplateValue({
                            priority: 4,
                            short_description: wfa.dataPill(params.trigger.subject, 'string'),
                            description: `From: ${wfa.dataPill(params.trigger.from_address, 'string')}\n\n${wfa.dataPill(params.trigger.inbound_email.body, 'reference')}`,
                            contact_type: 'email',
                            caller_id: wfa.dataPill(sender.Record.sys_id, 'reference'),
                        }),
                    }
                )
    
                const attachments = wfa.action(
                    action.core.getAttachmentsOnRecord,
                    { $id: Now.ID['get_email_attachments'] },
                    { source_record: wfa.dataPill(params.trigger.inbound_email.sys_id, 'reference') }
                )
    
                wfa.flowLogic.forEach(
                    wfa.dataPill(attachments.parameter, 'records'),
                    { $id: Now.ID['copy_attachments_loop'] },
                    () => {
                        wfa.action(
                            action.core.copyAttachment,
                            { $id: Now.ID['copy_attachment'] },
                            {
                                target_record: wfa.dataPill(p3Incident.record, 'reference'),
                                attachment_record: wfa.dataPill(attachments.parameter, 'records'),
                                table: 'incident',
                            }
                        )
                    }
                )
    
                wfa.action(
                    action.core.sendEmail,
                    { $id: Now.ID['confirm_p3_email'] },
                    {
                        table_name: 'incident',
                        ah_to: wfa.dataPill(params.trigger.from_address, 'string'),
                        ah_subject: `Incident Created: ${wfa.dataPill(params.trigger.subject, 'string')}`,
                        ah_body: `Your request has been received and a P3 incident has been created. Our team will be in touch shortly.`,
                        record: wfa.dataPill(p3Incident.record, 'reference'),
                    }
                )
            })
        }
    )