service-omni-routing-flow-deploy

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

service-omni-routing-flow-deploy

service-omni-routing-flow-deploy

Voice runtime proof depends on a provisioned Contact Center. Flow redeploys report
Changed
even when the deployed configuration is unchanged.
Deploy an Omni-Channel routing Flow via the Metadata API, confirm it lands Active, and prove it routes work — either by CLI invocation (the autolaunched dry-run) or by observing real routing side effects (the record-triggered variant).
service-omni-channel-setup-coordinate
wires it in after
service-omni-queue-deploy
has produced the target queue and its members are bound.
Voice运行时验证依赖已配置的Contact Center。即使部署的配置未发生变化,Flow重新部署仍会报告“Changed”。
通过Metadata API部署Omni-Channel路由流,确认其处于Active状态,并验证其路由功能——可通过CLI调用(自动启动的dry-run模式)或观察实际路由副作用(记录触发变体)来完成。
service-omni-channel-setup-coordinate
会在
service-omni-queue-deploy
生成目标队列并绑定成员后,完成路由流的配置。

Variants

变体

Four assets ship under
assets/force-app/main/default/flows/
— an autolaunched and a record-triggered variant for each of Case and VoiceCall. Selection is by
--target Case|VoiceCall
(default Case) and
--trigger
.
VariantShapeProvesRoutes real work?
Omni_Route_Cases
/
Omni_Route_VoiceCalls
(default)
Autolaunched,
dryRun
gate
CLI invocability via Actions REST, no side effectsNo
Omni_Route_Case_Trigger
/
Omni_Route_VoiceCall_Trigger
(
--trigger
)
Record-triggered on insert, calls
routeWork
Real routing — the insert creates
PendingServiceRouting
/
AgentWork
Yes
The autolaunched variant de-risks the headless CLI path cheaply; the record-triggered variant proves real records reach a queue. A full steel thread deploys the record-triggered variant.
With
--trigger --routing-type SkillsBased
, the record-triggered variant is drawn from a sibling
<FlowDN>.SkillsBased.flow-meta.xml
asset that emits
routingType=SkillsBased
plus a non-null
skillOption
. The base trigger flows hardcode
routingType=QueueBased
, so a skills-based-routing org config never takes effect at runtime — this variant is what makes it route by skill (W-24069467).
assets/force-app/main/default/flows/
下包含四个资源——分别对应Case和VoiceCall的自动启动变体与记录触发变体。可通过
--target Case|VoiceCall
(默认值为Case)和
--trigger
参数进行选择。
变体类型验证内容是否路由实际工作项?
Omni_Route_Cases
/
Omni_Route_VoiceCalls
(默认)
自动启动,
dryRun
gated
通过Actions REST实现CLI调用,无副作用
Omni_Route_Case_Trigger
/
Omni_Route_VoiceCall_Trigger
(使用
--trigger
参数)
插入记录时触发,调用
routeWork
实际路由——插入操作会生成
PendingServiceRouting
/
AgentWork
自动启动变体可低成本降低无头CLI路径的风险;记录触发变体可验证实际记录是否到达队列。完整核心流程会部署记录触发变体。
若使用
--trigger --routing-type SkillsBased
参数,记录触发变体将从同级
<FlowDN>.SkillsBased.flow-meta.xml
资源中获取,该资源会设置
routingType=SkillsBased
并指定非空
skillOption
。基础触发流硬编码为
routingType=QueueBased
,因此基于技能的路由组织配置在运行时永远不会生效——此变体是实现按技能路由的关键(W-24069467)。

Inputs

输入参数

bash
bash scripts/deploy-and-report.sh <org-alias> [flow_developer_name] [--target Case|VoiceCall] [--trigger] [--routing-type QueueBased|SkillsBased] [--skill-option RunSBRRules|DefineSkillRequirements|Both] [--runtime-proof] [--require-proof] [--skip-invoke]
bash
bash scripts/deploy-and-report.sh <org-alias> [flow_developer_name] [--target Case|VoiceCall] [--trigger] [--routing-type QueueBased|SkillsBased] [--skill-option RunSBRRules|DefineSkillRequirements|Both] [--runtime-proof] [--require-proof] [--skip-invoke]

autolaunched smoke test (Case):

自动启动冒烟测试(Case):

bash scripts/deploy-and-report.sh myorg
bash scripts/deploy-and-report.sh myorg

record-triggered Voice routing with runtime proof:

带运行时验证的记录触发式Voice路由:

bash scripts/deploy-and-report.sh myorg --target VoiceCall --trigger --runtime-proof
bash scripts/deploy-and-report.sh myorg --target VoiceCall --trigger --runtime-proof

skills-based Case routing (platform evaluates WorkSkillRouting rules):

基于技能的Case路由(平台评估WorkSkillRouting规则):

bash scripts/deploy-and-report.sh myorg --target Case --trigger --routing-type SkillsBased --runtime-proof

- `--target Case|VoiceCall` (default Case) — selects the flow pair.
- `--trigger` — deploy the record-triggered variant with dynamic token resolution.
- `--routing-type QueueBased|SkillsBased` (default QueueBased; env `OMNI_ROUTING_TYPE`) — `SkillsBased` deploys the `<FlowDN>.SkillsBased` variant that calls `routeWork` with `routingType=SkillsBased`, so the org's skills-based routing config takes effect at runtime instead of being inert. It deploys under the same DeveloperName, replacing the QueueBased trigger (never two triggers on one object).
- `--skill-option RunSBRRules|DefineSkillRequirements|Both` (default `RunSBRRules`; env `OMNI_SKILL_OPTION`; SkillsBased only) — `RunSBRRules`/`Both` make the platform evaluate the org's `WorkSkillRouting` rules server-side and attach matching `SkillRequirement` rows to the PSR; `DefineSkillRequirements` uses only skills the flow itself passes. A SkillsBased deploy with an empty/invalid skillOption is **refused** (exit 2): a null skillOption NPEs the platform `routeWork` action and rolls back the triggering insert (W-24069761), so the asset always carries a non-null value.
- `--runtime-proof` (implies `--trigger`) — after deploy, insert a target record. QueueBased accepts a `PendingServiceRouting` or `AgentWork` row. SkillsBased requires a `PendingServiceRouting` with at least one `SkillRequirement`, proving that `RunSBRRules` evaluated the active `WorkSkillRouting` rule. Proof is fail-soft unless required. The record is always deleted afterward.
- `--require-proof` (implies `--runtime-proof`; also `OMNI_RUNTIME_PROOF_REQUIRED=1`) — makes that proof blocking; the release gate for the Voice steel thread.
- `--skip-invoke` (autolaunched only) — deploy + verify Active, no Actions REST call.
- Token overrides (`--trigger`): `QUEUE_DEVELOPER_NAME`, `ROUTING_CONFIG_DEVELOPER_NAME`, `SERVICE_CHANNEL_DEVELOPER_NAME`. The coordinator always supplies these three from the resources it established for the target, so the flow binds the same channel/queue/QRC rather than a guessed default.
bash scripts/deploy-and-report.sh myorg --target Case --trigger --routing-type SkillsBased --runtime-proof

- `--target Case|VoiceCall`(默认值为Case)——选择对应的流组。
- `--trigger`——部署带有动态令牌解析的记录触发变体。
- `--routing-type QueueBased|SkillsBased`(默认值为QueueBased;环境变量`OMNI_ROUTING_TYPE`)——`SkillsBased`会部署`<FlowDN>.SkillsBased`变体,该变体调用`routeWork`时设置`routingType=SkillsBased`,因此组织的基于技能的路由配置会在运行时生效,而非处于闲置状态。它会以相同的DeveloperName部署,替换QueueBased触发流(同一对象永远不会有两个触发流)。
- `--skill-option RunSBRRules|DefineSkillRequirements|Both`(默认值为`RunSBRRules`;环境变量`OMNI_SKILL_OPTION`;仅SkillsBased模式可用)——`RunSBRRules`/`Both`会让平台在服务器端评估组织的`WorkSkillRouting`规则,并将匹配的`SkillRequirement`行附加到PSR;`DefineSkillRequirements`仅使用流自身传递的技能。若基于技能的部署中skillOption为空或无效,将被拒绝(退出码2):空skillOption会导致平台`routeWork`操作出现NPE并回滚触发的插入操作(W-24069761),因此资源始终携带非空值。
- `--runtime-proof`(隐含`--trigger`)——部署完成后,插入目标记录。QueueBased模式会检查`PendingServiceRouting`或`AgentWork`行。SkillsBased模式需要带有至少一个`SkillRequirement`的`PendingServiceRouting`,以此证明`RunSBRRules`已评估了活跃的`WorkSkillRouting`规则。除非设置了强制验证,否则验证失败不会阻断流程。记录始终会在之后被删除。
- `--require-proof`(隐含`--runtime-proof`;也可通过`OMNI_RUNTIME_PROOF_REQUIRED=1`设置)——使验证成为阻断性检查;是Voice核心流程的发布门槛。
- `--skip-invoke`(仅自动启动模式可用)——部署并验证Active状态,不执行Actions REST调用。
- 令牌覆盖(`--trigger`模式):`QUEUE_DEVELOPER_NAME`、`ROUTING_CONFIG_DEVELOPER_NAME`、`SERVICE_CHANNEL_DEVELOPER_NAME`。协调器始终会从为目标建立的资源中提供这三个参数,因此流会绑定相同的渠道/队列/QRC,而非猜测的默认值。

Preconditions and safety

前置条件与安全

  • Target org authenticated via
    sf
    CLI, Service Cloud license,
    sf
    CLI ≥ 2.139.6,
    jq
    ≥ 1.6.
  • Omni-Channel base settings enabled (
    service-omni-base-settings-configure
    ) — the routing action resolves only when Omni is on; the flow deploys without it but fails at runtime.
  • Record-triggered runs need a deployed ServiceChannel (
    service-omni-service-channel-configure
    ), Queue (
    service-omni-queue-deploy
    ), and QueueRoutingConfig (
    service-omni-queue-routing-config-deploy
    ) to resolve their tokenized IDs; runtime proof additionally needs an agent online with a compatible presence status (
    service-omni-presence-status-deploy
    ).
  • The three-way
    safe_to_write
    production guard applies.
  • 目标组织已通过
    sf
    CLI认证,拥有Service Cloud许可证,
    sf
    CLI版本≥2.139.6,
    jq
    版本≥1.6。
  • Omni-Channel基础设置已启用(
    service-omni-base-settings-configure
    )——仅当Omni启用时,路由操作才能解析;流可在未启用的情况下部署,但运行时会失败。
  • 记录触发式运行需要已部署的ServiceChannel(
    service-omni-service-channel-configure
    )、Queue(
    service-omni-queue-deploy
    )和QueueRoutingConfig(
    service-omni-queue-routing-config-deploy
    )来解析其令牌化ID;运行时验证还需要在线且具有兼容状态的座席(
    service-omni-presence-status-deploy
    )。
  • 应用三方
    safe_to_write
    生产环境防护机制。

Run

运行流程

deploy-and-report.sh
deploys, verifies, and (per variant) proves routing:
  1. Resolve tokens (record-triggered only) — the committed asset carries
    __QUEUE_ID__
    ,
    __ROUTING_CONFIG_ID__
    ,
    __SERVICE_CHANNEL_ID__
    , and channel name/label tokens. The skill resolves each by DeveloperName into a materialized copy that is never committed (the asset stays tokenized for portability). A ServiceChannel that does not resolve fails closed rather than embedding an empty id.
  2. Deploy
    sf project deploy start --metadata "Flow:<FlowDN>"
    ; the
    files[].state
    maps to
    reused
    /
    updated
    /
    created
    .
  3. Verify Active — retrieve the Flow and confirm its resource IDs,
    routingType
    , and SkillsBased
    skillOption
    still match; otherwise redeploy. Confirm an active version exists.
  4. Prove routing — autolaunched: POST to
    /actions/custom/flow/<FlowDN>
    with
    {"dryRun":true}
    and assert
    isSuccess
    and
    dryRunOk
    . Record-triggered: insert a target record and observe routing. SkillsBased success additionally requires one or more
    SkillRequirement
    rows on the PSR.
deploy-and-report.sh
脚本负责部署、验证,并根据变体类型验证路由功能:
  1. 解析令牌(仅记录触发模式)——提交的资源包含
    __QUEUE_ID__
    __ROUTING_CONFIG_ID__
    __SERVICE_CHANNEL_ID__
    以及渠道名称/标签令牌。脚本会根据DeveloperName将每个令牌解析为具体化的副本,且该副本不会被提交(资源保持令牌化以保证可移植性)。若ServiceChannel无法解析,会直接失败,而非嵌入空ID。
  2. 部署——执行
    sf project deploy start --metadata "Flow:<FlowDN>"
    files[].state
    会映射为
    reused
    /
    updated
    /
    created
  3. 验证Active状态——获取Flow并确认其资源ID、
    routingType
    以及SkillsBased模式下的
    skillOption
    仍与请求匹配;否则重新部署。确认存在活跃版本。
  4. 验证路由功能——自动启动模式:向
    /actions/custom/flow/<FlowDN>
    发送POST请求,参数为
    {"dryRun":true}
    ,并断言
    isSuccess
    dryRunOk
    为真。记录触发模式:插入目标记录并观察路由情况。SkillsBased模式成功还要求PSR上存在一个或多个
    SkillRequirement
    行。

Behavior

行为说明

Two shapes, two verification paths. "Can we invoke a routing flow headlessly?" and "do real records route to a queue?" are different questions. The autolaunched
dryRun
flow answers the first in one side-effect-free HTTP call — the flow must have a code path that succeeds without prerequisites, so
dryRun=true
takes an assignment step and returns
dryRunOk=true
. Record-triggered flows are not exposed as custom actions, so the only headless proof is inserting the source record and observing
PendingServiceRouting
/
AgentWork
. The PSR row alone proves the flow routed; agent assignment depends on Omni distribution, not the flow.
Active-version round trip. For the record-triggered variant, component deploy state proves only the transaction, not that an active version exists. The skill prefers
FlowDefinitionView.ActiveVersionId
and falls back to the active Tooling
Flow
row when that view is unavailable. It fails closed when neither source proves an active version, so
flow_active:true
is never reported without evidence.
Binding-drift redeploy.
reused
means an active version already exists and its embedded queue/QRC/ServiceChannel IDs, routing type, and SkillsBased skill option match the request. If a binding or routing mode drifted, the skill redeploys instead of reusing.
OMNI_FLOW_FORCE=1
forces a redeploy.
Idempotency quirk. Unlike most metadata types,
Flow
deploys are not byte-idempotent — Salesforce reports
Changed
on identical redeploys because every deploy is a potential version bump. Treat
updated
from this skill as "successfully redeployed," not "operator modified the flow."
Safety. Deploys use explicit
--metadata "Flow:<DN>"
(never
--source-dir
) so sibling flows are untouched, and the skill never overwrites a Flow it did not author — the coordinator supplies
flow_developer_name
deliberately.
flow_developer_name
is validated against
^[A-Za-z][A-Za-z0-9_]{0,79}$
because it is interpolated into the Actions REST URL path.
两种类型,两种验证路径。“能否无头调用路由流?”与“实际记录是否会路由到队列?”是两个不同的问题。自动启动的
dryRun
流通过一次无副作用的HTTP调用回答第一个问题——流必须有无需前置条件即可成功的代码路径,因此
dryRun=true
会执行赋值步骤并返回
dryRunOk=true
。记录触发流不会作为自定义操作暴露,因此唯一的无头验证方式是插入源记录并观察
PendingServiceRouting
/
AgentWork
。仅PSR行即可证明流已完成路由;座席分配取决于Omni分发机制,而非流本身。
活跃版本往返验证。对于记录触发变体,组件部署状态仅能证明事务完成,无法证明存在活跃版本。脚本优先使用
FlowDefinitionView.ActiveVersionId
,当该视图不可用时,回退到活跃的Tooling
Flow
行。若两个来源均无法证明存在活跃版本,会直接失败,因此只有在有证据的情况下才会报告
flow_active:true
绑定漂移重新部署
reused
表示已存在活跃版本,且其嵌入的队列/QRC/ServiceChannel ID、路由类型以及SkillsBased模式下的skill选项与请求匹配。若绑定或路由模式发生漂移,脚本会重新部署而非复用。设置
OMNI_FLOW_FORCE=1
可强制重新部署。
幂等性特性。与大多数元数据类型不同,
Flow
部署并非字节级幂等——Salesforce会在相同内容重新部署时报告“Changed”,因为每次部署都可能产生版本更新。在此脚本中,应将
updated
视为“重新部署成功”,而非“操作人员修改了流”。
安全性。部署使用显式的
--metadata "Flow:<DN>"
(从不使用
--source-dir
),因此不会影响同级流,且脚本永远不会覆盖非自身创建的Flow——协调器会特意提供
flow_developer_name
flow_developer_name
会验证是否符合
^[A-Za-z][A-Za-z0-9_]{0,79}$
规则,因为它会被插入到Actions REST URL路径中。

Output contract

输出约定

A single JSON object with
status
created
|
reused
|
updated
|
blocked
,
flow_developer_name
,
flow_state
,
flow_active
,
deploy_id
,
manual_actions
, and
blocking_issue
. The autolaunched variant adds
verification_path
and
invocation_smoke_test
(
attempted
,
success
,
endpoint
,
dry_run_ok
). The record-triggered variant adds
mode: "record_triggered"
,
target
,
flow_active_version_id
,
routing_type
,
skill_option
(the skillOption when SkillsBased, else null),
resolved
(queue/routing_config/service_channel), and
runtime_proof
(
attempted
,
required
,
success
,
record_id
,
pending_service_routing
,
agent_work
,
reason
). Under
--routing-type SkillsBased
,
runtime_proof
also carries
skill_requirement_count
and
skill_requirements
— the
SkillRequirement
rows the platform attached to the PSR (the skills-based acceptance signal).
  • blocked
    — deploy failed; the flow is not Active; the autolaunched invocation failed; a queue/QRC could not be resolved; the ServiceChannel did not resolve; or
    --require-proof
    was set and the mode-specific proof was not observed. For SkillsBased, a PSR with zero
    SkillRequirement
    rows is not a passing proof. A plain
    --runtime-proof
    failure remains fail-soft.
  • runtime_proof.attempted
    is
    false
    unless
    --runtime-proof
    /
    --require-proof
    was passed; the throwaway record is always cleaned up.
返回一个JSON对象,包含
status
created
|
reused
|
updated
|
blocked
flow_developer_name
flow_state
flow_active
deploy_id
manual_actions
blocking_issue
。自动启动变体还会添加
verification_path
invocation_smoke_test
(包含
attempted
success
endpoint
dry_run_ok
)。记录触发变体还会添加
mode: "record_triggered"
target
flow_active_version_id
routing_type
skill_option
(SkillsBased模式下为skillOption,否则为null)、
resolved
(包含queue/routing_config/service_channel)和
runtime_proof
(包含
attempted
required
success
record_id
pending_service_routing
agent_work
reason
)。在
--routing-type SkillsBased
模式下,
runtime_proof
还会包含
skill_requirement_count
skill_requirements
——平台附加到PSR的
SkillRequirement
行(基于技能的验证信号)。
  • blocked
    ——部署失败;流未处于Active状态;自动启动调用失败;队列/QRC无法解析;ServiceChannel无法解析;或设置了
    --require-proof
    但未观察到对应模式的验证结果。对于SkillsBased模式,没有
    SkillRequirement
    行的PSR不算验证通过。仅设置
    --runtime-proof
    时,验证失败不会阻断流程。
  • runtime_proof.attempted
    仅在传递
    --runtime-proof
    /
    --require-proof
    参数时为
    true
    ;临时记录始终会被清理。

Limitations

局限性

  • Case and VoiceCall only; extend by forking the closest asset and preserving the
    dryRun
    /
    dryRunOk
    contract (autolaunched) or the
    routeWork
    + tokenized-ID pattern (record-triggered).
  • Does not register the Flow on a queue's routing configuration — that binding belongs to
    service-omni-queue-routing-config-deploy
    .
  • Does not handle screen flows, platform-event-triggered flows, or Flow Tests.
  • 仅支持Case和VoiceCall;可通过复制最接近的资源并保留
    dryRun
    /
    dryRunOk
    约定(自动启动模式)或
    routeWork
    +令牌化ID模式(记录触发模式)进行扩展。
  • 不会在队列的路由配置上注册Flow——该绑定属于
    service-omni-queue-routing-config-deploy
    的功能。
  • 不支持屏幕流、平台事件触发流或Flow测试。

References

参考资料

FileWhen to read
references/api-notes.md
On unexpected deploy or verification behavior — variant comparison, the token-resolution table, Flow schema, the Actions REST response shape, and record-DML verification
文件阅读场景
references/api-notes.md
遇到意外的部署或验证行为时——变体对比、令牌解析表、Flow schema、Actions REST响应格式以及记录DML验证