フロー API - ServiceNow Fluent
フロー API は、再利用可能な複数ステップコンポーネントを使用してビジネスプロセスを自動化するフローとサブフロー [sys_hub_flow] を定義します。
フローオブジェクトを使用してフローを作成します。詳細については、「フローオブジェクト」を参照してください。
Subflow オブジェクトを使用してサブフローを作成します。詳細については、「サブフローオブジェクト」を参照してください。
フローに関する一般的な情報については、「 Exploring flows」を参照してください。サブフローに関する一般的な情報については、「 Exploring subflows」を参照してください。
フローオブジェクト
一連のトリガー条件が発生したときに一連のアクションとフローロジックを実行するフロー [sys_hub_flow] を作成します。
フローは、トリガー条件が満たされた場合にのみ実行されます。一貫性のある事前定義されたトリガーを必要とするイベント駆動型の自動化にはフローを使用します。
- フロー構成プロパティを定義する 1 つの構成オブジェクト。
- フローを実行するタイミングを定義する1つのwfa.trigger関数。
- 実行するアクションとフローロジックを定義する One Body 関数。
- 0個以上のwfa.action関数
- 0 個以上のwfa.flow_logic関数
| 名前 | タイプ | 説明 |
|---|---|---|
| 構成 | オブジェクト | 必須。Fluent オブジェクトまたは関数のメタデータ構成プロパティを含むオブジェクト。 |
| $id | 文字列または数値 | 必須。メタデータオブジェクトの一意の ID。アプリケーションをビルドすると、この ID は一意のsys_idにハッシュされます。詳細については、「ServiceNow Fluent 言語構成」を参照してください。 形式: |
| name | 文字列 | 必須。フローの表示名。フロー名は、目的を簡単に識別できるように、わかりやすくわかりやすいものにする必要があります。 |
| 説明 | 文字列 | フローの内容の説明。 |
| runAs | 文字列 |
フローアクションが実行されるユーザーコンテキストを決定します。システムユーザー設定は、ロールベースの ACL をバイパスする特権ユーザーとして実行されます。ユーザー設定は、フローを開始したユーザーの権限とロールで実行されます。 有効な値:system、user デフォルト:ユーザー |
| runWithRoles | 文字列 | フローの実行中に使用するロールを指定します。ロールを使用してフローを実行する方法の詳細については、「 Flow roles」を参照してください。 |
| flowPriority | 文字列 |
フローエンジンでフローの実行優先度を定義します。 有効な値:低、中、高 デフォルト:中 |
| 保護 | 文字列 |
フローが読み取り専用 (読み取り) か編集可能 (空の文字列) かを定義します。 有効な値:read、'' デフォルト値:'' |
| アクセス | 文字列 |
フローがパブリックかプライベートかを定義します。 有効な値:public、package_private デフォルト:public |
| flowVariables | オブジェクト | 列タイプを使用してフローで使用できるデータ変数を定義するオブジェクト。get_table_schema関数を使用して、フィールド定義をフェッチします。 |
| wfa.trigger | 関数 | フローを実行するタイミングを定義します。トリガー条件が満たされると、トリガーによって提供されたデータを使用してフローが実行されます。wfa.trigger関数の詳細については、「wfa.trigger 関数」を参照してください。 |
| フロー本文 | 関数 |
Flow body は、フロー内の実行ステップを表す TypeScript の Arrow function です。フロー本体は、wfa.trigger オブジェクトと flowVariables オブジェクトを含む params パラメーターを入力として受け取ります。Flow bodyのステップは、次の機能タイプで構成されます。
これらのパラメーター値は、フロー本文関数で使用できます。
|
この例では、起点フィールド値が空のインシデントが作成されたときに実行されるフローを作成します。フローは、インシデントの重大度に基づいてマネージャーとチームメンバーにアラートを送信します。
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 によって呼び出されたときに実行されます。複数のフローで呼び出すことができるオンデマンド自動化のためにサブフローを使用します。
- サブフロー構成プロパティを定義する 1 つの構成オブジェクト。
- サブフロー入力を定義する 0 個または 1 個の入力オブジェクト。
- サブフロー出力を定義するゼロまたは 1 つの出力オブジェクト。
- フロー変数を定義する 0 個または 1 個のフロー変数オブジェクト。
- 実行するアクション、フローロジック、およびサブフローを定義する 1 つの本文機能。
- 0個以上のwfa.action関数
- 0 個以上のwfa.flow_logic関数
| 名前 | タイプ | 説明 |
|---|---|---|
| 構成 | オブジェクト | 必須。Fluent オブジェクトまたは関数のメタデータ構成プロパティを含むオブジェクト。 |
| $id | 文字列または数値 | 必須。メタデータオブジェクトの一意の ID。アプリケーションをビルドすると、この ID は一意のsys_idにハッシュされます。詳細については、「ServiceNow Fluent 言語構成」を参照してください。 形式: |
| name | 文字列 | 必須。サブフローの表示名。サブフロー名は、その目的を簡単に識別できるように、意味のある説明的なものにする必要があります。このプロパティは、サブフロー構成オブジェクトの一部です。 |
| 説明 | 文字列 | フローの内容の説明。このプロパティは、サブフロー構成オブジェクトの一部です。 |
| runAs | 文字列 |
サブフローアクションが実行されるユーザーコンテキストを決定します。 有効な値:system、user デフォルト:ユーザー このプロパティは、サブフロー構成オブジェクトの一部です。 |
| runWithRoles | アレイ | サブフローが実行中に使用するロールを指定します。このプロパティは、サブフロー構成オブジェクトの一部です。 |
| flowPriority | 文字列 |
フローエンジンでのサブフローの実行優先度を定義します。 有効な値:低、中、高 デフォルト:中 このプロパティは、サブフロー構成オブジェクトの一部です。 |
| 保護 | 文字列 |
サブフローが読み取り専用 (読み取り) か編集可能 (空の文字列) かを定義します。 有効な値:read、' ' このプロパティは、サブフロー構成オブジェクトの一部です。 |
| アクセス | 文字列 |
他のサブフロー作成者に対するサブフローの可視化/アクセシビリティを定義します。 有効な値:public、package_private デフォルト:public このプロパティは、サブフロー構成オブジェクトの一部です。 |
| category | 文字列 | サブフローを整理するためのカテゴリ。このプロパティは、サブフロー構成オブジェクトの一部です。 |
| 入力 | オブジェクト | 列タイプを使用して入力パラメーターを定義するオブジェクト。このプロパティは、サブフロー構成オブジェクトの一部です。 |
| 出力 | オブジェクト | 列タイプを使用して出力パラメーターを定義するオブジェクト。このプロパティは、サブフロー構成オブジェクトの一部です。 |
| flowVariables | オブジェクト | 列タイプを使用してサブフローで使用できるデータ変数を定義するオブジェクト。このプロパティは、サブフロー構成オブジェクトの一部です。 |
| フロー本文 | 関数 |
Flow body は、フロー内の実行ステップを表す TypeScript の Arrow function です。フロー本体は、inputs オブジェクトと flowVariables オブジェクトを含む _params パラメーターを入力として受け取ります。Flow bodyのステップは、次の機能タイプで構成されます。
これらのパラメーター値は、フロー本文関数で使用できます。
|
この例では、新しいユーザーの名前とオフィスの場所を使用して、ユーザーレコードを検索し、ようこそ通知を送信し、未アサインのハードウェア資産と利用可能なオフィスの場所を検索します。利用可能なラップトップ資産とオフィスの場所がある場合は、それぞれが新しいユーザーに割り当てられます。
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 関数
特定のトリガータイプの開始条件が満たされたときにフローを実行します。トリガーは、フローがいつ実行されるか、およびフロー開始条件からどのデータが利用可能かを決定します。
フローオブジェクトのFlow Body関数にwfa.trigger関数を追加します。
- 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
使用可能なアクションの詳細については、「 Workflow Studio flow trigger types」を参照してください。
| 名前 | タイプ | 説明 |
|---|---|---|
| トリガー | 文字列 | 実行する特定のトリガーの名前。すべてのアクション名には、 trigger で始まるドット表記が使用されます。たとえば、 trigger.record.created、 trigger.scheduled.daily、 trigger.application.serviceCatalog などです。 |
| 構成 | オブジェクト | 必須。Fluent オブジェクトまたは関数のメタデータ構成プロパティを含むオブジェクト。 |
| $id | 文字列または数値 | 必須。メタデータオブジェクトの一意の ID。アプリケーションをビルドすると、この ID は一意のsys_idにハッシュされます。詳細については、「ServiceNow Fluent 言語構成」を参照してください。 形式: |
| 入力 | オブジェクト | テーブルや条件など、トリガーに必要な入力パラメーターを含むオブジェクト。 |
この例では、優先度の高いインシデントレコードが作成されたときにフローを実行します。
// 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 Body関数にwfa.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」を参照してください。
| 名前 | タイプ | 説明 |
|---|---|---|
| アクション | 文字列 | 実行する特定のアクションの名前。すべてのアクション名には、 action.core で始まるドット表記が使用されます。たとえば、 action.core.lookUpRecord、 action.core.lookUpRecords、 action.core.createRecord、 action.core.updateRecord などです。 |
| 構成 | オブジェクト | 必須。Fluent オブジェクトまたは関数のメタデータ構成プロパティを含むオブジェクト。 |
| $id | 文字列または数値 | 必須。メタデータオブジェクトの一意の ID。アプリケーションをビルドすると、この ID は一意のsys_idにハッシュされます。詳細については、「ServiceNow Fluent 言語構成」を参照してください。 形式: |
| 入力 | オブジェクト | 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 関数
フローまたはサブフローから特定のフローロジックインスタンスを実行します。フローロジックは、データを使用するタイミングと方法を決定します。
フローまたはサブフローオブジェクトのFlow Body関数にwfa.flow_logic関数を追加します。
- if
- elseIf
- else
- forEach
- waitForADuration
- exitLoop、 endFlow、 skipIteration、 setFlowVariables、 assignSubflowOutputs
使用可能なフローロジックの詳細については、「 Workflow Studio flow logic」を参照してください。
| 名前 | タイプ | 説明 |
|---|---|---|
| 構成 | オブジェクト | 必須。Fluent オブジェクトまたは関数のメタデータ構成プロパティを含むオブジェクト。 |
| $id | 文字列または数値 | 必須。メタデータオブジェクトの一意の ID。アプリケーションをビルドすると、この ID は一意のsys_idにハッシュされます。詳細については、「ServiceNow Fluent 言語構成」を参照してください。 形式: |
| 注釈 | 文字列 | このフローロジックのインスタンスが何を実行するかを説明します。たとえば、「 Priority is critical」という注釈などです。 |
| ステータス | 文字列 | wfa.flow_logic.if 関数および wfa.flow_logic.elseIf 関数で必須です。このフローロジックを実行するために true である必要があるデータ値。たとえば、 condition: '\${_params.trigger.current.priority}=1',. |
| item | アレイ | wfa.flow_logic.forEach 関数で必須です。反復処理するレコードのアレイまたはコレクション。通常、このレコードリストは、アクション.core.lookUpRecordsアクションへのwfa.action関数呼び出しから動的に生成されます。たとえば、 問題などです。レコード アレイは、 action.core.lookUpRecords アクションから生成できます。 |
| ラベル | 文字列 | フローロジックのこのインスタンスを説明する値を表示します。たとえば、 label: 'If Priority is critical',。 |
| variables | スキーマ | wfa.flow_logic.assignSubflowOutputs 関数および wfa.flow_logic.setFlowVariables 関数で必須です。フロー変数のデータ構造を定義する FlowVariables API によって生成されるスキーマ。たとえば、 flowVars スキーマは FlowVariables から生成できます。重要: このプロパティの引数としては常に _params.flowVariables を使用します。間違ったスキーマを渡すと、検証エラーが発生します。 |
| フローロジック本体 | 関数 | Flow logic body は、フローロジックの実行ステップを表す TypeScript の Arrow function です。フロー本体は、wfa.trigger オブジェクトと flowVariables オブジェクトを含む _params パラメーターを入力として受け取ります。Flow logic bodyのステップは、次の関数呼び出しで構成されます。
|
この例は、トリガーレコードの条件をチェックしている様子を示しています。現在のレコードの優先度が 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 関数
アクションまたはフローロジック入力から特定のランタイムデータピル値を参照します。
wfa.dataPill関数をアクションまたはflow_logic関数の入力パラメータに追加します。使用するデータピルごとに定数を定義します。通常、この定数はwfa.actionまたはwfa.flow_logic関数の出力を格納します。
| 名前 | タイプ | 説明 |
|---|---|---|
| 式 | 文字列 | 必須。入力値として使用するランタイムデータへのドット表記の参照。一般的に使用されるランタイム値には、トリガーデータ、アクション出力、サブフロー出力などがあります。
|
| タイプ | 文字列 | 必須。文字列、ブーリアン、整数、参照などのデータのデータ型。使用可能なフィールドデータタイプのリストについては、「 Field types reference」を参照してください。 |
この例では、バインドされていないメールレコードを使用して、受信メールの値に基づいてインシデントまたはタスクを作成します。この例では、params オブジェクトを使用してトリガー内のデータを参照します。この例では、定数sender、senderManager、p3Incident、およびattachmentsも定義して、後の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'),
}
)
})
}
)