flow-designer

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Flow Designer Patterns for ServiceNow

ServiceNow Flow Designer 设计模式

Flow Designer is the modern automation engine in ServiceNow, replacing legacy Workflows for new development.
Flow Designer是ServiceNow中的现代化自动化引擎,在新开发场景下替代了传统的Workflows。

Using the Flow Designer Tool

使用Flow Designer工具

To create and manage flows programmatically, first discover the Flow Designer tool via
tool_search({query: "flow designer"})
. The discovered tool handles all GraphQL mutations for the full flow lifecycle.
CRITICAL — IF/ELSE/ELSEIF placement rules:
  • Actions inside an IF branch:
    parent_ui_id
    = IF's
    uiUniqueIdentifier
  • ELSE/ELSEIF blocks: must be at the same level as IF, NOT nested inside it
    • parent_ui_id
      = the same parent you used for the IF block
    • connected_to
      = IF's
      logicId
      (the sysId returned when creating the IF)
  • Getting this wrong causes "Unsupported flowLogic type" errors when saving the flow
要以编程方式创建和管理流程,首先通过
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”错误

Flow Designer Components

Flow Designer 组件

ComponentPurposeReusable
FlowMain automation processNo
SubflowReusable flow logicYes
ActionSingle operation (Script, REST, etc.)Yes
SpokeCollection of related actionsYes
组件用途可复用性
Flow(流程)主自动化流程
Subflow(子流程)可复用的流程逻辑
Action(动作)单个操作(脚本、REST等)
Spoke(集成套件)相关动作的集合

Flow Triggers

流程触发器

Record-Based Triggers

基于记录的触发器

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: 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

Schedule Triggers

定时触发器

Trigger: Daily
Time: 02:00 AM
Timezone: America/New_York

Trigger: Weekly
Day: Monday
Time: 08:00 AM
Trigger: Daily
Time: 02:00 AM
Timezone: America/New_York

Trigger: Weekly
Day: Monday
Time: 08:00 AM

Service Catalog Triggers

服务目录触发器

Trigger: Service Catalog
Catalog Item: Request New Laptop
Trigger: Service Catalog
Catalog Item: Request New Laptop

Flow Best Practices

Flow 最佳实践

1. Use Subflows for Reusability

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
Main Flow: Incident P1 Handler
├── Trigger: Incident Created (Priority = 1)
├── Action: Log Event
├── Subflow: Notify On-Call Team     ← 可复用!
├── Subflow: Create Major Incident   ← 可复用!
└── Action: Update Incident

2. Error Handling

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
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. Flow Variables

3. 流程变量

javascript
// 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';
javascript
// Input Variables (来自触发器)
var incidentSysId = fd_data.trigger.current.sys_id;
var priority = fd_data.trigger.current.priority;

// Scratch Variables (流程内临时变量)
fd_data.scratch.approval_required = priority == '1';
fd_data.scratch.notification_sent = false;

// Output Variables (返回给调用流程/子流程)
fd_data.output.success = true;
fd_data.output.message = 'Processed successfully';

4. Conditions and Branches

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

Custom Actions (Scripts)

自定义动作(脚本)

Basic Script Action

基础脚本动作

javascript
(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);
javascript
(function execute(inputs, outputs) {
  // Inputs 在Action Designer中定义
  var incidentId = inputs.incident_sys_id;
  var newState = inputs.target_state;

  // 处理逻辑
  var gr = new GlideRecord('incident');
  if (gr.get(incidentId)) {
    gr.setValue('state', newState);
    gr.update();

    // 设置输出
    outputs.success = true;
    outputs.incident_number = gr.getValue('number');
  } else {
    outputs.success = false;
    outputs.error_message = 'Incident not found';
  }
})(inputs, outputs);

Script Action with Error Handling

带错误处理的脚本动作

javascript
(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);
javascript
(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会捕获此错误并路由到错误处理程序
    throw new Error('Query failed: ' + e.message);
  }
})(inputs, outputs);

REST Action Example

REST 动作示例

Configuration

配置

yaml
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
yaml
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

Response Handling

响应处理

javascript
// 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';
}
javascript
// 在REST调用后的脚本步骤中
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 Patterns

Subflow 模式

Notification 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: 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

Approval 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
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 vs Workflow

Flow Designer vs Workflow

FeatureFlow DesignerWorkflow
InterfaceModern, visualLegacy
ReusabilitySubflows, ActionsLimited
TestingBuilt-in testingManual
Version ControlYesLimited
Integration HubYesNo
PerformanceBetterSlower
RecommendationUse for new developmentMaintain existing only
特性Flow DesignerWorkflow
界面现代化、可视化传统样式
复用性支持Subflow、Action有限
测试内置测试功能手动测试
版本控制支持有限
Integration Hub支持不支持
性能更优较慢
推荐方案新开发首选仅维护现有流程

Debugging Flows

流程调试

Flow Context Logs

流程上下文日志

javascript
// 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);
javascript
// 在脚本动作中
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);

Flow Execution History

流程执行历史

Navigate: Flow Designer > Executions
Filter by: Flow name, Status, Date range
View: Step-by-step execution details
导航路径: Flow Designer > Executions
筛选条件: 流程名称、状态、日期范围
查看内容: 分步执行详情

Common Patterns

常见模式

Pattern 1: SLA Escalation Flow

模式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
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

Pattern 2: Approval Routing

模式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
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

Pattern 3: Integration Sync

模式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
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

Performance Tips

性能优化技巧

  1. Use conditions early - Filter before expensive operations
  2. Limit loops - Set max iterations on For Each
  3. Async where possible - Don't block on slow operations
  4. Cache lookups - Store repeated queries in scratch variables
  5. Batch operations - Group similar updates together
  1. 提前使用条件过滤 - 在执行高开销操作前先过滤数据
  2. 限制循环次数 - 为For Each设置最大迭代次数
  3. 尽可能异步执行 - 不要阻塞在慢速操作上
  4. 缓存查询结果 - 将重复查询的结果存储在临时变量中
  5. 批量操作 - 将相似的更新操作分组执行