flow-designer について
ServiceNow 開発者向けに、Flow Designer のトリガー、分岐、サブフロー、エラー処理、スクリプトアクションを扱うスキルです。ツールを使ってフローをプログラムから作成・管理する方法も説明します。
主な機能
- 01レコード、スケジュール、カタログのトリガー設定
- 02分岐とサブフローによるロジックの再利用
- 03TRY/CATCH によるエラー処理
- 04スクリプトアクションと REST アクションの作成
- 05実行履歴の確認とフローのデバッグ
活用シーン
- 01SLA エスカレーションや承認ルートの構築
- 02外部システムとの定期的な同期
- 03新規開発向けの再利用可能な自動化設計
MCP 対応
tool_search で Flow Designer ツールを見つけて使用し、フローのライフサイクルを管理する方法を推奨しています。必要な GraphQL 変更はこのツールが処理します。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ serac-labs/ serac --skill flow-designerインストール後、Claude Code で/flow-designerを入力して読み込まれたか確認します。
詳細
ServiceNow の Flow Designer パターン
Flow Designer は ServiceNow の最新の自動化エンジンであり、新規開発では従来の Workflow に取って代わります。
Flow Designer ツールの使用
プログラムからフローを作成および管理するには、まず tool_search({query: "flow designer"}) で Flow Designer ツールを検出します。検出されたツールが、フローのライフサイクル全体にわたるすべての GraphQL ミューテーションを処理します。
重要 — IF/ELSE/ELSEIF の配置ルール:
- IF ブランチ内のアクション:
parent_ui_id= IF のuiUniqueIdentifier - ELSE/ELSEIF ブロック:IF と同じ階層に配置し、IF の内側にはネストしないでください
parent_ui_id= IF ブロックに使用したものと同じ親connected_to= IF のlogicId(IF の作成時に返される sysId)
- これを誤ると、フローの保存時に「Unsupported flowLogic type」エラーが発生します
重要 — TRY/CATCH の配置ルール:
TRY ブロックを追加すると、CATCH の対となるブロックはツールによって自動作成されます。TRY と CATCH はコンテナーです。アクションはその内側に配置し、隣には配置しないでください。
- TRY 内のアクション(失敗する可能性があるステップ):
parent_ui_id= TRY のuiUniqueIdentifierorder:TRY 内で 1、2、3、... と指定
- CATCH 内のアクション(エラー処理):
parent_ui_id= CATCH のuiUniqueIdentifier(TRY の作成レスポンスでcatch_ui_idとして返されます)order:CATCH 内で 1、2、3、... と指定
- TRY/CATCH ペアの作成時に返される
next_orderは、ペアの後に続く兄弟要素用であり、その内側の子要素用ではありません。TRY/CATCH の後に配置するアクションにはこれを使用しますが、その内側に配置するアクションには使用しないでください。
sys_hub_* テーブルへのバックグラウンドスクリプト、GlideRecord、または REST 呼び出しを使ってフローを作成しないでください。必ず tool_search({query: "flow designer"}) で Flow Designer ツールを検出して使用してください。このツールは GraphQL ミューテーションを正しく処理します。バックグラウンドスクリプトを使う方法では、壊れたフローが気づかれないまま作成されます。
Flow Designer のコンポーネント
| コンポーネント | 目的 | 再利用可能 |
|---|---|---|
| Flow | メインの自動化プロセス | いいえ |
| Subflow | 再利用可能なフローロジック | はい |
| Action | 単一の操作(Script、REST など) | はい |
| Spoke | 関連するアクションの集合 | はい |
フローのトリガー
レコードベースのトリガー
Trigger: Created
Table: incident
Condition: Priority = 1
Trigger: Updated
Table: incident
Condition: State changes to Resolved
Trigger: Created or Updated
Table: change_request
Condition: Risk = High
スケジュールトリガー
Trigger: Daily
Time: 02:00 AM
Timezone: America/New_York
Trigger: Weekly
Day: Monday
Time: 08:00 AM
サービスカタログのトリガー
Trigger: Service Catalog
Catalog Item: Request New Laptop
Flow のベストプラクティス
1. 再利用性のために Subflow を使用する
Main Flow: Incident P1 Handler
├── Trigger: Incident Created (Priority = 1)
├── Action: Log Event
├── Subflow: Notify On-Call Team ← Reusable!
├── Subflow: Create Major Incident ← Reusable!
└── Action: Update Incident
2. エラー処理
Flow: Process Integration
├── Try
│ ├── Action: Call REST API
│ ├── Action: Parse Response
│ └── Action: Update Record
├── Catch (all errors)
│ ├── Action: Log Error Details
│ ├── Action: Create Error Task
│ └── Action: Send Alert
└── Always
└── Action: Cleanup Temp Data
3. フロー変数
// Input Variables (from trigger)
var incidentSysId = fd_data.trigger.current.sys_id
var priority = fd_data.trigger.current.priority
// Scratch Variables (within flow)
fd_data.scratch.approval_required = priority == "1"
fd_data.scratch.notification_sent = false
// Output Variables (to calling flow/subflow)
fd_data.output.success = true
fd_data.output.message = "Processed successfully"
4. 条件と分岐
If: Priority = Critical
Then:
- Notify VP
- Create Major Incident
- Page On-Call
Else If: Priority = High
- Notify Manager
- Escalate in 4 hours
Else:
- Standard Processing
カスタムアクション(スクリプト)
基本的なスクリプトアクション
;(function execute(inputs, outputs) {
// Inputs defined in Action Designer
var incidentId = inputs.incident_sys_id
var newState = inputs.target_state
// Process
var gr = new GlideRecord("incident")
if (gr.get(incidentId)) {
gr.setValue("state", newState)
gr.update()
// Set outputs
outputs.success = true
outputs.incident_number = gr.getValue("number")
} else {
outputs.success = false
outputs.error_message = "Incident not found"
}
})(inputs, outputs)
エラー処理を伴うスクリプトアクション
;(function execute(inputs, outputs) {
try {
var gr = new GlideRecord(inputs.table_name)
gr.addEncodedQuery(inputs.query)
gr.query()
var records = []
while (gr.next()) {
records.push({
sys_id: gr.getUniqueValue(),
display_value: gr.getDisplayValue(),
})
}
outputs.records = JSON.stringify(records)
outputs.count = records.length
outputs.success = true
} catch (e) {
outputs.success = false
outputs.error_message = e.message
// Flow Designer will catch this and route to error handler
throw new Error("Query failed: " + e.message)
}
})(inputs, outputs)
REST アクションの例
設定
Action: Call External API
Connection: My REST Connection Alias
HTTP Method: POST
Endpoint: /api/v1/tickets
Headers:
Content-Type: application/json
Authorization: Bearer ${connection.credential.token}
Request Body:
{
"title": "${inputs.short_description}",
"priority": "${inputs.priority}",
"reporter": "${inputs.caller_email}"
}
Parse Response: JSON
レスポンス処理
// In a Script step after REST call
var response = fd_data.action_outputs.rest_response
if (response.status_code == 201) {
outputs.external_id = response.body.id
outputs.success = true
} else {
outputs.success = false
outputs.error = response.body.error || "Unknown error"
}
Subflow のパターン
通知 Subflow
Subflow: Send Notification
Inputs:
- recipient_email (String)
- subject (String)
- body (String)
- priority (String, default: "normal")
Actions:
1. Look Up: User by email
2. If: User found
- Send Email notification
- Output: success = true
3. Else:
- Log Warning
- Output: success = false
承認 Subflow
Subflow: Request Approval
Inputs:
- record_sys_id (Reference)
- approver (Reference: sys_user)
- approval_message (String)
Actions:
1. Create: Approval record
2. Wait: For approval state change
3. If: Approved
- Output: approved = true
4. Else:
- Output: approved = false
- Output: rejection_reason = comments
Flow Designer と Workflow の比較
| 機能 | Flow Designer | Workflow |
|---|---|---|
| インターフェース | 最新のビジュアル形式 | 従来型 |
| 再利用性 | Subflow、Action | 限定的 |
| テスト | テスト機能を標準搭載 | 手動 |
| バージョン管理 | はい | 限定的 |
| Integration Hub | はい | いいえ |
| パフォーマンス | より高い | より遅い |
| 推奨 | 新規開発に使用 | 既存のもののみ保守 |
フローのデバッグ
フローコンテキストのログ
// In Script Action
fd_log.info("Processing incident: " + inputs.incident_number)
fd_log.debug("Input data: " + JSON.stringify(inputs))
fd_log.warn("Retry attempt: " + inputs.retry_count)
fd_log.error("Failed to process: " + error.message)
フロー実行履歴
Navigate: Flow Designer > Executions
Filter by: Flow name, Status, Date range
View: Step-by-step execution details
よくあるパターン
パターン 1:SLA エスカレーションフロー
Trigger: SLA breached (Task SLA)
Actions:
1. Get: Task details
2. Get: Assignment group manager
3. Send: Escalation email
4. Update: Task priority
5. Create: Escalation task
パターン 2:承認ルーティング
Trigger: Request Item created
Actions:
1. If: Amount < $1000
- Auto-approve
2. Else If: Amount < $10000
- Request: Manager approval
3. Else:
- Request: VP approval
- Wait: 3 business days
- If timeout: Escalate to CFO
パターン 3:インテグレーション同期
Trigger: Scheduled (every 15 minutes)
Actions:
1. Call: External API (get changes)
2. For Each: Changed record
a. Look Up: Matching local record
b. If exists: Update
c. Else: Create
3. Log: Sync summary
パフォーマンスのヒント
- 早い段階で条件を使用する - コストの高い処理の前にフィルタリングします
- ループを制限する - For Each に最大反復回数を設定します
- 可能な場合は非同期にする - 時間のかかる処理でブロックしないようにします
- 検索結果をキャッシュする - 繰り返し行うクエリをスクラッチ変数に保存します
- 処理をまとめる - 類似する更新をまとめて実行します