service-de-channel-routing-configure

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Configuring Channel Routing

配置通道路由

What this skill does

本技能的作用

Ensures a
MessagingChannel
has valid routing configured before activation. The channel's
SessionHandler
field is a polymorphic foreign key (verified against
MessagingChannel.entity.xml
,
domain="Queue, FlowDefinition, User, BotDefinition, AgenticCtxtDecorDefinition"
) — it names who the channel routes incoming sessions to. Some targets additionally require a
FallbackQueue
(an Omni-Channel Queue that catches sessions the primary target can't take).
These skills create Enhanced channels (
PlatformType=Enhanced
, SCRT2). All five SessionHandler domains are writable on Enhanced channels. (A Standard/SCRT1 channel would only accept a Flow as SessionHandler — the server rejects any other domain with "Only flows of type Omni-Channel are supported". These skills never create Standard channels, so that path isn't handled here.)
Where this fits: the channel is inserted by
service-de-channel-create
(or a per-type leaf); this skill sets routing;
service-de-channel-consent-configure
sets consent; then
service-de-channel-activate
flips it live — activation requires both routing and consent. The
service-de-headless-channel-configure
orchestrator runs all four in sequence.
Supported routing types — all set
SessionHandlerId
, some also set
FallbackQueueId
:
TypeSessionHandler targetId prefixFallbackQueue
Omni-Channel Queue
Group
(Type=Queue)
00G
must be null
Omni-Flow
FlowDefinition
(ProcessType=RoutingFlow)
300
required
Agentforce Service Agent (ASA)
BotDefinition
(Type=ExternalCopilot)
0Xx
required
Digital Worker
AgenticCtxtDecorDefinition
1iE
required
User
User
(with a RoutingConfiguration)
005
must be null
Provisioning behavior:
  • Queue — pick an existing
    MessagingSession
    -capable Queue, or create a new Queue + QueueRoutingConfig via Metadata API.
  • Flow / ASA / Digital Worker / User — locate an existing eligible target and PATCH it. These skills do not create Flows, bots, digital workers, or users — if none eligible exist, the skill reports the precondition and points the user at Setup.
确保
MessagingChannel
在激活前已配置有效的路由。通道的
SessionHandler
字段是一个多态外键(已通过
MessagingChannel.entity.xml
验证,
domain="Queue, FlowDefinition, User, BotDefinition, AgenticCtxtDecorDefinition"
)——它指定了通道将传入会话路由到的目标对象。部分目标还需要设置
FallbackQueue
(一个Omni-Channel队列,用于接收主目标无法处理的会话)。
这些技能创建的是Enhanced通道(
PlatformType=Enhanced
,SCRT2)。所有五种SessionHandler域都可在Enhanced通道上写入。(Standard/SCRT1通道仅接受Flow作为SessionHandler——服务器会拒绝其他域,返回错误信息“Only flows of type Omni-Channel are supported”。本技能从不创建Standard通道,因此无需处理该场景。)
适用场景:通道由
service-de-channel-create
(或特定类型的分支技能)创建;本技能负责设置路由;
service-de-channel-consent-configure
负责设置授权;随后
service-de-channel-activate
将通道激活——激活操作需要同时配置路由和授权。
service-de-headless-channel-configure
编排器会按顺序执行这四个步骤。
支持的路由类型——所有类型都会设置
SessionHandlerId
,部分类型还会设置
FallbackQueueId
类型SessionHandler目标ID前缀FallbackQueue
Omni-Channel Queue
Group
(Type=Queue)
00G
必须为null
Omni-Flow
FlowDefinition
(ProcessType=RoutingFlow)
300
必填
Agentforce Service Agent (ASA)
BotDefinition
(Type=ExternalCopilot)
0Xx
必填
Digital Worker
AgenticCtxtDecorDefinition
1iE
必填
User
User
(带有RoutingConfiguration)
005
必须为null
配置行为:
  • Queue——选择现有的支持
    MessagingSession
    的队列,或通过Metadata API创建新的Queue + QueueRoutingConfig。
  • Flow / ASA / Digital Worker / User——定位现有的符合条件的目标并执行PATCH操作。本技能不会创建Flow、机器人、数字工作者或用户——如果没有符合条件的目标,技能会报告前置条件未满足,并指引用户前往Setup页面创建。

Reference File Index

参考文件索引

Reference fileLoad when
references/queue-creation.md
The user picked "create a new queue" on the Queue routing path — full Metadata API scaffold → deploy → ID lookup → optional member add.
references/target-locate.md
You need the per-domain SOQL to locate and validate an eligible target (Queue, Flow, ASA, Digital Worker, User) and the FallbackQueue requirement matrix.
references/asa-routing.md
The user picked ASA (Agentforce Service Agent) routing — precondition check, enumerating live ASAs, and selection.
references/gotchas.md
Troubleshooting an unexpected result, or before modifying this skill — the known gotchas.
references/worked-examples.md
You want a reference run of the reuse-existing-queue, create-new-queue, Flow, or ASA paths.
参考文件加载时机
references/queue-creation.md
用户在Queue路由路径中选择“创建新队列”时——完整的Metadata API脚手架→部署→ID查找→可选成员添加流程。
references/target-locate.md
需要按域执行SOQL来定位并验证符合条件的目标(Queue、Flow、ASA、Digital Worker、User),以及查看FallbackQueue要求矩阵时。
references/asa-routing.md
用户选择ASA(Agentforce Service Agent)路由时——前置条件检查、枚举可用ASA、选择ASA。
references/gotchas.md
排查意外结果,或修改本技能之前——查看已知的问题点。
references/worked-examples.md
需要参考复用现有队列、创建新队列、Flow或ASA路径的实际运行示例时。

When NOT to use this skill

不适用本技能的场景

  • The channel already has
    SessionHandlerId
    or
    FallbackQueueId
    set.
    This skill no-ops and tells you — nothing to do. Proceed to activation.
  • The channel doesn't exist yet. Run the insertion skill first; this skill expects a real
    MessagingChannel.Id
    .
  • You want to replace existing routing. Safer to clear
    SessionHandlerId
    manually in the UI, then re-run this skill. The no-op check is a guardrail, not a limitation worth bypassing automatically.
  • 通道已设置
    SessionHandlerId
    FallbackQueueId
    。本技能会直接返回不操作提示——无需执行任何操作。直接进入激活步骤即可。
  • 通道尚未创建。请先运行插入技能;本技能需要一个真实的
    MessagingChannel.Id
  • 需要替换现有路由。建议先在UI中手动清除
    SessionHandlerId
    ,然后重新运行本技能。不操作检查是一个防护机制,不建议自动绕过。

Inputs (from caller)

输入参数(来自调用方)

  • {CHANNEL_ID}
    — a 15- or 18-char
    MessagingChannel.Id
    (prefix
    0Mj
    ). The channel must already exist.
  • {ORG_ALIAS}
    — optional; the
    sf
    CLI target-org alias. Default: whatever
    sf config get target-org
    returns. All SOQL, PATCH, and Metadata deploys run against this org.
  • {CHANNEL_ID}
    ——15或18位的
    MessagingChannel.Id
    (前缀为
    0Mj
    )。通道必须已存在。
  • {ORG_ALIAS}
    ——可选;
    sf
    CLI的目标组织别名。默认值:
    sf config get target-org
    返回的结果。所有SOQL、PATCH和Metadata部署操作都针对该组织执行。

Output (to caller)

输出结果(返回给调用方)

One of:
Success — no change needed:
json
{"ok": true, "noop": true, "routingType": "queue|flow|asa|digital_worker|user", "sessionHandlerId": "00G...|300...|0Xx...|1iE...|005...", "fallbackQueueId": "00G...|null", "targetName": "...", "message": "Routing already configured"}
Success — Queue routing configured:
json
{"ok": true, "routingType": "queue", "sessionHandlerId": "00G...", "fallbackQueueId": null, "queueName": "...", "queueDeveloperName": "...", "created": true|false}
Success — Flow routing configured:
json
{"ok": true, "routingType": "flow", "sessionHandlerId": "300...", "fallbackQueueId": "00G...", "flowName": "...", "flowDeveloperName": "...", "created": false}
Success — ASA routing configured:
json
{"ok": true, "routingType": "asa", "sessionHandlerId": "0Xx...", "fallbackQueueId": "00G...", "asaName": "...", "asaDeveloperName": "...", "botUserId": "005...", "botVersionId": "0X9...", "created": false}
Success — Digital Worker routing configured:
json
{"ok": true, "routingType": "digital_worker", "sessionHandlerId": "1iE...", "fallbackQueueId": "00G...", "workerName": "...", "created": false}
Success — User routing configured:
json
{"ok": true, "routingType": "user", "sessionHandlerId": "005...", "fallbackQueueId": null, "userName": "...", "created": false}
Precondition not met:
json
{"ok": false, "kind": "no-eligible-target", "routingType": "flow|asa|digital_worker|user", "hint": "no eligible <target> found on this org — <how to create one in Setup>, then re-run this skill"}
{"ok": false, "kind": "no-fallback-queue", "hint": "Flow/ASA/Digital Worker routing requires a FallbackQueue but no MessagingSession-capable queue exists — create one (Queue routing path) first"}
{"ok": false, "kind": "asa-not-supported", "hint": "this org doesn't have BotDefinition (Agentforce not licensed); use Queue routing instead"}
{"ok": false, "kind": "standard-channel", "hint": "this is a Standard (SCRT1) channel — only Flow routing is supported; these skills only create Enhanced channels, so this is unexpected"}
Failure:
json
{"ok": false, "kind": "metadata-deploy-failed", "message": "..."}
{"ok": false, "kind": "patch-failed", "message": "..."}
{"ok": false, "kind": "verify-failed", "hint": "PATCH returned success but re-read shows SessionHandlerId still null — permission or trigger issue"}
The PATCH failure
message
often carries the server-side validation error verbatim (from
MessagingChannelFunctionsHelper.validateSessionHandler
). Surface it — it tells the user exactly which linking rule failed. Common ones:
MissingFallbackQueueForFlowRouting
/
...ForAsaRouting
/
...ForDigitalWorkerRouting
(FallbackQueue required but null),
UnsupportedFallbackQueue
(FallbackQueue set on a Queue/User path where it must be null),
InvalidSessionHandlerFlowType
(Flow isn't ProcessType=RoutingFlow, or the channel is Standard/SCRT1),
NoRoutingConfigDefined
(User has no RoutingConfiguration).

以下结果之一:
成功——无需修改:
json
{"ok": true, "noop": true, "routingType": "queue|flow|asa|digital_worker|user", "sessionHandlerId": "00G...|300...|0Xx...|1iE...|005...", "fallbackQueueId": "00G...|null", "targetName": "...", "message": "Routing already configured"}
成功——已配置Queue路由:
json
{"ok": true, "routingType": "queue", "sessionHandlerId": "00G...", "fallbackQueueId": null, "queueName": "...", "queueDeveloperName": "...", "created": true|false}
成功——已配置Flow路由:
json
{"ok": true, "routingType": "flow", "sessionHandlerId": "300...", "fallbackQueueId": "00G...", "flowName": "...", "flowDeveloperName": "...", "created": false}
成功——已配置ASA路由:
json
{"ok": true, "routingType": "asa", "sessionHandlerId": "0Xx...", "fallbackQueueId": "00G...", "asaName": "...", "asaDeveloperName": "...", "botUserId": "005...", "botVersionId": "0X9...", "created": false}
成功——已配置Digital Worker路由:
json
{"ok": true, "routingType": "digital_worker", "sessionHandlerId": "1iE...", "fallbackQueueId": "00G...", "workerName": "...", "created": false}
成功——已配置User路由:
json
{"ok": true, "routingType": "user", "sessionHandlerId": "005...", "fallbackQueueId": null, "userName": "...", "created": false}
前置条件未满足:
json
{"ok": false, "kind": "no-eligible-target", "routingType": "flow|asa|digital_worker|user", "hint": "no eligible <target> found on this org — <how to create one in Setup>, then re-run this skill"}
{"ok": false, "kind": "no-fallback-queue", "hint": "Flow/ASA/Digital Worker routing requires a FallbackQueue but no MessagingSession-capable queue exists — create one (Queue routing path) first"}
{"ok": false, "kind": "asa-not-supported", "hint": "this org doesn't have BotDefinition (Agentforce not licensed); use Queue routing instead"}
{"ok": false, "kind": "standard-channel", "hint": "this is a Standard (SCRT1) channel — only Flow routing is supported; these skills only create Enhanced channels, so this is unexpected"}
失败:
json
{"ok": false, "kind": "metadata-deploy-failed", "message": "..."}
{"ok": false, "kind": "patch-failed", "message": "..."}
{"ok": false, "kind": "verify-failed", "hint": "PATCH returned success but re-read shows SessionHandlerId still null — permission or trigger issue"}
PATCH失败的
message
通常会直接携带服务器端的验证错误信息(来自
MessagingChannelFunctionsHelper.validateSessionHandler
)。请直接展示该信息——它会准确告知用户哪条链接规则未通过。常见错误包括:
MissingFallbackQueueForFlowRouting
/
...ForAsaRouting
/
...ForDigitalWorkerRouting
(需要FallbackQueue但未设置)、
UnsupportedFallbackQueue
(在Queue/User路径中设置了FallbackQueue,而该路径要求必须为null)、
InvalidSessionHandlerFlowType
(Flow不是ProcessType=RoutingFlow,或者通道是Standard/SCRT1类型)、
NoRoutingConfigDefined
(User未配置RoutingConfiguration)。

Stage 1: Read current routing state

阶段1:读取当前路由状态

Query the channel. If it already has
SessionHandlerId
OR
FallbackQueueId
, no-op. Otherwise, continue.
bash
sf data query --target-org '{ORG_ALIAS}' \
  --query "SELECT Id, DeveloperName, SessionHandlerId, FallbackQueueId FROM MessagingChannel WHERE Id = '{CHANNEL_ID}'" \
  --json > /tmp/ccr-channel.json
Parse with
node -e
or
jq
. If the record is missing — halt with
Error: Channel {CHANNEL_ID} not found — check the id, or run the insertion skill first.
If
SessionHandlerId
is non-null, branch on the Id prefix to figure out what the existing routing target is, then no-op with the right envelope. The prefix maps 1:1 to the SessionHandler domain (verified against
MessagingChannel.entity.xml
):
PrefixDomain / TargetLookup queryroutingType
00G
Group
(Type=Queue)
SELECT Id, Name, DeveloperName FROM Group WHERE Id='<sh>' AND Type='Queue'
queue
300
FlowDefinition
SELECT DurableId, Label, ApiName FROM FlowDefinitionView WHERE DurableId='<sh>'
flow
0Xx
BotDefinition
(ASA)
SELECT Id, DeveloperName, MasterLabel, AgentType FROM BotDefinition WHERE Id='<sh>'
asa
1iE
AgenticCtxtDecorDefinition
(Digital Worker)
SELECT Id, DeveloperName, MasterLabel FROM AgenticCtxtDecorDefinition WHERE Id='<sh>'
digital_worker
005
User
SELECT Id, Name FROM User WHERE Id='<sh>'
user
bash
SESSION_HANDLER_ID="$(node -e 'console.log(JSON.parse(require("fs").readFileSync("/tmp/ccr-channel.json","utf8")).result.records[0].SessionHandlerId)')"
PREFIX="${SESSION_HANDLER_ID:0:3}"
case "$PREFIX" in
  00G) sf data query --target-org '{ORG_ALIAS}' --query "SELECT Id, Name, DeveloperName FROM Group WHERE Id = '$SESSION_HANDLER_ID' AND Type = 'Queue'" --json > /tmp/ccr-noop-target.json ;;
  300) sf data query --target-org '{ORG_ALIAS}' --query "SELECT DurableId, Label, ApiName FROM FlowDefinitionView WHERE DurableId = '$SESSION_HANDLER_ID'" --json > /tmp/ccr-noop-target.json ;;
  0Xx) sf data query --target-org '{ORG_ALIAS}' --query "SELECT Id, DeveloperName, MasterLabel, AgentType FROM BotDefinition WHERE Id = '$SESSION_HANDLER_ID'" --json > /tmp/ccr-noop-target.json ;;
  1iE) sf data query --target-org '{ORG_ALIAS}' --query "SELECT Id, DeveloperName, MasterLabel FROM AgenticCtxtDecorDefinition WHERE Id = '$SESSION_HANDLER_ID'" --json > /tmp/ccr-noop-target.json ;;
  005) sf data query --target-org '{ORG_ALIAS}' --query "SELECT Id, Name FROM User WHERE Id = '$SESSION_HANDLER_ID'" --json > /tmp/ccr-noop-target.json ;;
  *)   echo "{\"records\":[{\"Id\":\"$SESSION_HANDLER_ID\"}]}" > /tmp/ccr-noop-target.json ;;
esac
Report the success-noop envelope (include the existing
FallbackQueueId
from the Stage 1 read) and return.
If
FallbackQueueId
is non-null but
SessionHandlerId
is null — still no-op. That's a partially-configured Flow/ASA state; don't touch it, but flag it in the envelope
message
(
"FallbackQueue set but SessionHandler null — incomplete routing, review in Setup"
) since activation will still fail readiness without a SessionHandler.

查询通道信息。如果通道已设置
SessionHandlerId
FallbackQueueId
,则不执行任何操作。否则,继续后续步骤。
bash
sf data query --target-org '{ORG_ALIAS}' \
  --query "SELECT Id, DeveloperName, SessionHandlerId, FallbackQueueId FROM MessagingChannel WHERE Id = '{CHANNEL_ID}'" \
  --json > /tmp/ccr-channel.json
使用
node -e
jq
解析结果。如果未找到记录——终止并返回错误信息:
Error: Channel {CHANNEL_ID} not found — check the id, or run the insertion skill first.
如果
SessionHandlerId
不为空,根据ID前缀判断现有路由目标类型,然后返回对应的不操作信封。前缀与SessionHandler域一一对应(已通过
MessagingChannel.entity.xml
验证):
前缀域 / 目标查询语句routingType
00G
Group
(Type=Queue)
SELECT Id, Name, DeveloperName FROM Group WHERE Id='<sh>' AND Type='Queue'
queue
300
FlowDefinition
SELECT DurableId, Label, ApiName FROM FlowDefinitionView WHERE DurableId='<sh>'
flow
0Xx
BotDefinition
(ASA)
SELECT Id, DeveloperName, MasterLabel, AgentType FROM BotDefinition WHERE Id='<sh>'
asa
1iE
AgenticCtxtDecorDefinition
(Digital Worker)
SELECT Id, DeveloperName, MasterLabel FROM AgenticCtxtDecorDefinition WHERE Id='<sh>'
digital_worker
005
User
SELECT Id, Name FROM User WHERE Id='<sh>'
user
bash
SESSION_HANDLER_ID="$(node -e 'console.log(JSON.parse(require("fs").readFileSync("/tmp/ccr-channel.json","utf8")).result.records[0].SessionHandlerId)')"
PREFIX="${SESSION_HANDLER_ID:0:3}"
case "$PREFIX" in
  00G) sf data query --target-org '{ORG_ALIAS}' --query "SELECT Id, Name, DeveloperName FROM Group WHERE Id = '$SESSION_HANDLER_ID' AND Type = 'Queue'" --json > /tmp/ccr-noop-target.json ;;
  300) sf data query --target-org '{ORG_ALIAS}' --query "SELECT DurableId, Label, ApiName FROM FlowDefinitionView WHERE DurableId = '$SESSION_HANDLER_ID'" --json > /tmp/ccr-noop-target.json ;;
  0Xx) sf data query --target-org '{ORG_ALIAS}' --query "SELECT Id, DeveloperName, MasterLabel, AgentType FROM BotDefinition WHERE Id = '$SESSION_HANDLER_ID'" --json > /tmp/ccr-noop-target.json ;;
  1iE) sf data query --target-org '{ORG_ALIAS}' --query "SELECT Id, DeveloperName, MasterLabel FROM AgenticCtxtDecorDefinition WHERE Id = '$SESSION_HANDLER_ID'" --json > /tmp/ccr-noop-target.json ;;
  005) sf data query --target-org '{ORG_ALIAS}' --query "SELECT Id, Name FROM User WHERE Id = '$SESSION_HANDLER_ID'" --json > /tmp/ccr-noop-target.json ;;
  *)   echo "{\"records\":[{\"Id\":\"$SESSION_HANDLER_ID\"}]}" > /tmp/ccr-noop-target.json ;;
esac
返回成功-不操作信封(包含阶段1读取到的现有
FallbackQueueId
)并结束。
如果
FallbackQueueId
不为空但
SessionHandlerId
为空——仍执行不操作。这是一种Flow/ASA的部分配置状态;请勿修改,但需在信封的
message
中标记(
"FallbackQueue set but SessionHandler null — incomplete routing, review in Setup"
),因为如果没有SessionHandler,激活操作仍会因未就绪而失败。

Stage 2: Confirm the channel is Enhanced, then choose routing type

阶段2:确认通道为Enhanced类型,然后选择路由类型

First confirm
PlatformType
. The Stage 1 read didn't include it — add it, or re-query:
bash
sf data query --target-org '{ORG_ALIAS}' \
  --query "SELECT Id, PlatformType FROM MessagingChannel WHERE Id = '{CHANNEL_ID}'" --json > /tmp/ccr-platform.json
If
PlatformType != 'Enhanced'
(i.e. Standard/SCRT1), only Flow routing is writable. These skills only create Enhanced channels, so a Standard channel here is unexpected — emit
{ok:false, kind:"standard-channel", ...}
and stop rather than guessing.
Then ask the user (via a prompt — do NOT auto-pick):
text
The MessagingChannel '{developerName}' ({CHANNEL_ID}) has no routing configured.
Which routing type do you want?

  1) queue          — Omni-Channel queue routing
  2) flow           — Omni-Flow (RoutingFlow) + fallback queue
  3) asa            — Agentforce Service Agent (requires Agentforce license) + fallback queue
  4) digital_worker — Digital Worker (Agentic) + fallback queue
  5) user           — Direct to a specific user (requires a RoutingConfiguration on the user)

Pick [1-5]:
Branch on the user's pick. For every non-queue path, load
references/target-locate.md
— it holds the per-domain locate SOQL, eligibility filters, FallbackQueue rules, and exact PATCH shape:
  • 1 (queue) — continue to Stage 3-Queue below.
  • 2 (flow) — locate an eligible
    FlowDefinition
    (ProcessType=RoutingFlow, active version) + a FallbackQueue, then Stage 5.
  • 3 (asa) — continue to Stage 3-ASA; ASA requires a FallbackQueue too.
  • 4 (digital_worker) — locate an eligible
    AgenticCtxtDecorDefinition
    + a FallbackQueue, then Stage 5.
  • 5 (user) — locate a
    User
    that has a RoutingConfiguration, then Stage 5.
If a path finds no eligible target, emit
{ok:false, kind:"no-eligible-target", routingType, hint}
(see
references/target-locate.md
for the per-domain Setup pointer) and return — do not fabricate an id.

首先确认
PlatformType
。阶段1的查询未包含该字段——需添加该字段重新查询:
bash
sf data query --target-org '{ORG_ALIAS}' \
  --query "SELECT Id, PlatformType FROM MessagingChannel WHERE Id = '{CHANNEL_ID}'" --json > /tmp/ccr-platform.json
如果
PlatformType != 'Enhanced'
(即Standard/SCRT1),则仅支持Flow路由写入。本技能仅创建Enhanced通道,因此出现Standard通道属于意外情况——返回
{ok:false, kind:"standard-channel", ...}
并终止,而非尝试猜测处理。
然后提示用户选择(需手动选择,请勿自动选择):
text
The MessagingChannel '{developerName}' ({CHANNEL_ID}) has no routing configured.
Which routing type do you want?

  1) queue          — Omni-Channel queue routing
  2) flow           — Omni-Flow (RoutingFlow) + fallback queue
  3) asa            — Agentforce Service Agent (requires Agentforce license) + fallback queue
  4) digital_worker — Digital Worker (Agentic) + fallback queue
  5) user           — Direct to a specific user (requires a RoutingConfiguration on the user)

Pick [1-5]:
根据用户的选择分支处理。对于所有非Queue路径,加载
references/target-locate.md
——该文件包含按域定位的SOQL、 eligibility过滤器、FallbackQueue规则和精确的PATCH格式:
  • 1(queue)——继续执行下方的阶段3-Queue。
  • 2(flow)——定位符合条件的
    FlowDefinition
    (ProcessType=RoutingFlow,版本处于激活状态)+ 一个FallbackQueue,然后进入阶段5。
  • 3(asa)——继续执行阶段3-ASA;ASA也需要FallbackQueue。
  • 4(digital_worker)——定位符合条件的
    AgenticCtxtDecorDefinition
    + 一个FallbackQueue,然后进入阶段5。
  • 5(user)——定位带有RoutingConfiguration的
    User
    ,然后进入阶段5。
如果某路径未找到符合条件的目标,返回
{ok:false, kind:"no-eligible-target", routingType, hint}
(参考
references/target-locate.md
中的域特定Setup指引)并终止——请勿伪造ID。

Stage 3-Queue: Pick an existing queue, or create a new one

阶段3-Queue:选择现有队列,或创建新队列

(This stage runs only on the Queue path. ASA path: see Stage 3-ASA below.)
Enumerate eligible queues. The UI's routing dropdown (
MessagingRoutingMethodDataProviderController.getOmniQueues
) lists Groups where
QueueRoutingConfigId != null
— i.e. Omni-Channel-enabled queues. For a MessagingChannel we additionally want the queue to accept
MessagingSession
. Query the intersection: enumerate MessagingSession-capable queues, then keep only those with a QueueRoutingConfig.
bash
undefined
(本阶段仅在Queue路径中执行。ASA路径:请查看下方的阶段3-ASA。)
枚举符合条件的队列。UI中的路由下拉菜单(
MessagingRoutingMethodDataProviderController.getOmniQueues
)列出了
QueueRoutingConfigId != null
的Group——即启用Omni-Channel的队列。对于MessagingChannel,我们还需要队列支持
MessagingSession
。查询两者的交集:枚举支持MessagingSession的队列,然后仅保留带有QueueRoutingConfig的队列。
bash
undefined

MessagingSession-capable queues that are also Omni-enabled (QueueRoutingConfigId != null)

支持MessagingSession且已启用Omni的队列(QueueRoutingConfigId != null)

sf data query --target-org '{ORG_ALIAS}'
--query "SELECT Id, Name, DeveloperName FROM Group WHERE Type = 'Queue' AND QueueRoutingConfigId != null AND Id IN (SELECT QueueId FROM QueueSobject WHERE SobjectType = 'MessagingSession') ORDER BY Name"
--json > /tmp/ccr-queues.json

Each row's `Id` is the `00G` `Group.Id` — that is what gets written to `SessionHandlerId`. (If the semi-join subquery errors on an org, fall back to two queries: list `QueueSobject WHERE SobjectType='MessagingSession'`, then filter to those whose `Group.QueueRoutingConfigId != null`.)

Present the user with a numbered list plus a final "create new" option:

```text
Omni-enabled MessagingSession queues on {ORG_ALIAS}:

  1) Messaging Queue (Messaging_Queue) — 00GSG0000000LSf2AM
  2) MyQueue (MyQueue) — 00GSG000000144n2AA
  ...
  N) Create a new queue

Pick [1-N]:
  • If the user picks an existing queue: record its
    Id
    as
    {QUEUE_ID}
    (this is the
    Group.Id
    ). Skip to Stage 5.
  • If the user picks "create new": go to Stage 4.
If the list is empty AND the user picks (1) "Create a new queue" implicitly, skip directly to Stage 4.

sf data query --target-org '{ORG_ALIAS}'
--query "SELECT Id, Name, DeveloperName FROM Group WHERE Type = 'Queue' AND QueueRoutingConfigId != null AND Id IN (SELECT QueueId FROM QueueSobject WHERE SobjectType = 'MessagingSession') ORDER BY Name"
--json > /tmp/ccr-queues.json

每行的`Id`是`00G`格式的`Group.Id`——该ID将被写入`SessionHandlerId`。(如果半连接子查询在某些组织中报错,可退化为两次查询:先列出`QueueSobject WHERE SobjectType='MessagingSession'`,然后筛选出`Group.QueueRoutingConfigId != null`的队列。)

向用户展示编号列表,最后添加“创建新队列”选项:

```text
Omni-enabled MessagingSession queues on {ORG_ALIAS}:

  1) Messaging Queue (Messaging_Queue) — 00GSG0000000LSf2AM
  2) MyQueue (MyQueue) — 00GSG000000144n2AA
  ...
  N) Create a new queue

Pick [1-N]:
  • 如果用户选择现有队列:记录其
    Id
    {QUEUE_ID}
    (即
    Group.Id
    )。跳至阶段5。
  • 如果用户选择“创建新队列”:进入阶段4。
如果列表为空,用户默认选择(1)“创建新队列”,则直接跳至阶段4。

Stage 3-Queue, continued: Create a new Queue via Metadata API

阶段3-Queue续:通过Metadata API创建新队列

(Continuation of the Queue path. Skip if the user picked an existing queue above.)
We deploy a Queue + QueueRoutingConfig pair using a minimal scratch sfdx project (the
help-agent-accelerator
pattern), then look up the new Queue's Id and optionally add the current user as a member.
To create a new Queue via the Metadata API (sfdx project scaffold → deploy → ID lookup → optional member add), load
references/queue-creation.md
and follow it — it is the complete guide for this flow.
After that stage, jump to Stage 5 (PATCH).

(Queue路径的延续。如果用户选择了现有队列,请跳过本阶段。)
我们使用最小化的scratch sfdx项目(
help-agent-accelerator
模式)部署Queue + QueueRoutingConfig组合,然后查找新Queue的Id,并可选地将当前用户添加为成员。
要通过Metadata API创建新队列(sfdx项目脚手架→部署→ID查找→可选成员添加),请加载
references/queue-creation.md
并按照指引操作——该文件包含完整的流程说明。
完成本阶段后,跳至阶段5(PATCH操作)。

Stage 3-ASA: Pick an existing ASA

阶段3-ASA:选择现有ASA

(This stage runs only on the ASA path. Queue path: skip to Stage 5.)
ASA routing points
SessionHandlerId
at an existing, live Agentforce Service Agent (
BotDefinition
). This skill never creates a new ASA — it verifies the org supports one (Agentforce licensed), enumerates the live/routable ones, and lets the user pick.
For ASA precondition checks, enumeration, and selection, load
references/asa-routing.md
.
After selection, continue to Stage 5 (PATCH).

(本阶段仅在ASA路径中执行。Queue路径:跳至阶段5。)
ASA路由将
SessionHandlerId
指向现有的、已激活的Agentforce Service Agent(
BotDefinition
)。本技能从不创建新的ASA——它会验证组织是否支持ASA(已授权Agentforce),枚举可用的/可路由的ASA,让用户选择。
关于ASA的前置条件检查、枚举和选择,请加载
references/asa-routing.md
选择完成后,继续执行阶段5(PATCH操作)。

Stage 5: PATCH
MessagingChannel.SessionHandlerId
(+
FallbackQueueId
)

阶段5:PATCH
MessagingChannel.SessionHandlerId
(+
FallbackQueueId

By this point we have a routing target id in
{TARGET_ID}
and know its
{ROUTING_TYPE}
:
routingType
{TARGET_ID}
FallbackQueue write
queue
00G
Group.Id
none (must stay null)
flow
300
FlowDefinition
id
set
FallbackQueueId={FALLBACK_QUEUE_ID}
asa
0Xx
BotDefinition.Id
set
FallbackQueueId={FALLBACK_QUEUE_ID}
digital_worker
1iE
AgenticCtxtDecorDefinition.Id
set
FallbackQueueId={FALLBACK_QUEUE_ID}
user
005
User.Id
none (must stay null)
SessionHandler
is a polymorphic FK spanning
[Group, FlowDefinition, User, BotDefinition, AgenticCtxtDecorDefinition]
(per
MessagingChannel.entity.xml
; the BotDefinition/AgenticCtxtDecorDefinition targets only materialize on Agentforce-licensed orgs). The standard REST sObject PATCH accepts whichever Id type fits. The FallbackQueue rule is enforced server-side (
validateSessionHandler
): Flow/ASA/Digital Worker reject a null FallbackQueue; Queue/User reject a non-null one.
For the FallbackQueue paths, write both fields in one PATCH so the record never passes through an invalid intermediate state:
bash
undefined
此时我们已获得
{TARGET_ID}
形式的路由目标ID,并知晓其
{ROUTING_TYPE}
routingType
{TARGET_ID}
FallbackQueue写入操作
queue
00G
格式的
Group.Id
无(必须保持为null)
flow
300
格式的
FlowDefinition
ID
设置
FallbackQueueId={FALLBACK_QUEUE_ID}
asa
0Xx
格式的
BotDefinition.Id
设置
FallbackQueueId={FALLBACK_QUEUE_ID}
digital_worker
1iE
格式的
AgenticCtxtDecorDefinition.Id
设置
FallbackQueueId={FALLBACK_QUEUE_ID}
user
005
格式的
User.Id
无(必须保持为null)
SessionHandler
是跨
[Group, FlowDefinition, User, BotDefinition, AgenticCtxtDecorDefinition]
的多态外键(根据
MessagingChannel.entity.xml
;BotDefinition/AgenticCtxtDecorDefinition目标仅在已授权Agentforce的组织中可用)。标准REST sObject PATCH接受任何符合要求的ID类型。FallbackQueue规则由服务器端强制执行
validateSessionHandler
):Flow/ASA/Digital Worker路由会拒绝null的FallbackQueue;Queue/User路由会拒绝非null的FallbackQueue。
对于需要FallbackQueue的路径,在一次PATCH操作中同时写入两个字段,确保记录不会处于无效的中间状态:
bash
undefined

queue / user — SessionHandler only

queue / user — 仅设置SessionHandler

sf data update record --target-org '{ORG_ALIAS}' --sobject MessagingChannel
--record-id '{CHANNEL_ID}'
--values 'SessionHandlerId={TARGET_ID}' --json > /tmp/ccr-patch.json
sf data update record --target-org '{ORG_ALIAS}' --sobject MessagingChannel
--record-id '{CHANNEL_ID}'
--values 'SessionHandlerId={TARGET_ID}' --json > /tmp/ccr-patch.json

flow / asa / digital_worker — SessionHandler + FallbackQueue together

flow / asa / digital_worker — 同时设置SessionHandler + FallbackQueue

sf data update record --target-org '{ORG_ALIAS}' --sobject MessagingChannel
--record-id '{CHANNEL_ID}'
--values 'SessionHandlerId={TARGET_ID} FallbackQueueId={FALLBACK_QUEUE_ID}' --json > /tmp/ccr-patch.json

If `status !== 0`: emit `{ok:false, kind:"patch-failed", message: ...}` and return. Surface the server message verbatim — it names the exact linking rule that failed (see the failure-envelope note under "Output (to caller)").

---
sf data update record --target-org '{ORG_ALIAS}' --sobject MessagingChannel
--record-id '{CHANNEL_ID}'
--values 'SessionHandlerId={TARGET_ID} FallbackQueueId={FALLBACK_QUEUE_ID}' --json > /tmp/ccr-patch.json

如果`status !== 0`:返回`{ok:false, kind:"patch-failed", message: ...}`并终止。直接展示服务器返回的信息——它会指出未通过的具体链接规则(请参考“输出结果(返回给调用方)”下的失败信封说明)。

---

Stage 6: Verify

阶段6:验证

Re-read the channel:
bash
sf data query --target-org '{ORG_ALIAS}' \
  --query "SELECT Id, SessionHandlerId, FallbackQueueId FROM MessagingChannel WHERE Id = '{CHANNEL_ID}'" \
  --json
If the freshly-read
SessionHandlerId
doesn't equal
{TARGET_ID}
— or (for flow/asa/digital_worker)
FallbackQueueId
doesn't equal
{FALLBACK_QUEUE_ID}
:
json
{"ok": false, "kind": "verify-failed", "hint": "PATCH returned success but re-read shows SessionHandlerId/FallbackQueueId not persisted — check user permissions or field-level security on MessagingChannel"}
Otherwise, emit the path-appropriate success envelope (see "Output (to caller)" at the top of this file — one shape per routingType, each carrying
fallbackQueueId
).

重新读取通道信息:
bash
sf data query --target-org '{ORG_ALIAS}' \
  --query "SELECT Id, SessionHandlerId, FallbackQueueId FROM MessagingChannel WHERE Id = '{CHANNEL_ID}'" \
  --json
如果重新读取到的
SessionHandlerId
不等于
{TARGET_ID}
——或者(对于flow/asa/digital_worker路径)
FallbackQueueId
不等于
{FALLBACK_QUEUE_ID}
json
{"ok": false, "kind": "verify-failed", "hint": "PATCH returned success but re-read shows SessionHandlerId/FallbackQueueId not persisted — check user permissions or field-level security on MessagingChannel"}
否则,返回对应路径的成功信封(请参考本文档顶部的“输出结果(返回给调用方)”——每种routingType对应一种格式,均包含
fallbackQueueId
)。

Stage 7: Report to caller

阶段7:向调用方报告结果

Report the JSON envelope. If this skill is the leaf (user invoked it directly), render:
Queue path:
  • Success — Routing configured — channel {CHANNEL_ID} now routes to Queue '{QUEUE_LABEL}' ({QUEUE_ID}).{'' if created else ' (reused existing queue)'}
  • Info: Routing already configured — Queue '{name}' ({QUEUE_ID}). No changes.
    (no-op path)
Flow path:
  • Success — Routing configured — channel {CHANNEL_ID} now routes to Omni-Flow '{FLOW_LABEL}' ({TARGET_ID}), fallback Queue {FALLBACK_QUEUE_ID}.
ASA path:
  • Success — Routing configured — channel {CHANNEL_ID} now routes to Agentforce Service Agent '{ASA_LABEL}' ({ASA_ID}), fallback Queue {FALLBACK_QUEUE_ID}. Bot user: {BOT_USER_ID}. Active version: {BOT_VERSION_ID}.
  • Info: Routing already configured — ASA '{MasterLabel}' ({ASA_ID}). No changes.
    (no-op path)
Digital Worker path:
  • Success — Routing configured — channel {CHANNEL_ID} now routes to Digital Worker '{WORKER_LABEL}' ({TARGET_ID}), fallback Queue {FALLBACK_QUEUE_ID}.
User path:
  • Success — Routing configured — channel {CHANNEL_ID} now routes directly to User '{USER_NAME}' ({TARGET_ID}).
Failure / precondition:
  • Warning: No eligible {routingType} target found. {per-domain Setup pointer from references/target-locate.md}. Then re-run this skill.
    (no-eligible-target)
  • Warning: {routingType} routing needs a fallback queue but none exists. Create a MessagingSession queue first (queue path), then re-run.
    (no-fallback-queue)
  • Warning: This org doesn't have Agentforce licensed (no BotDefinition entity). Use Queue routing instead.
    (asa-not-supported)
  • Warning: This is a Standard (SCRT1) channel — only Flow routing is supported. These skills only create Enhanced channels, so this is unexpected; check the channel.
    (standard-channel)
  • Error: {kind}: {message}
    (other failures — the message names the server-side validation rule that failed)

返回JSON信封。如果本技能是直接由用户调用的叶子技能,则展示以下内容:
Queue路径:
  • Success — Routing configured — channel {CHANNEL_ID} now routes to Queue '{QUEUE_LABEL}' ({QUEUE_ID}).{'' if created else ' (reused existing queue)'}
  • Info: Routing already configured — Queue '{name}' ({QUEUE_ID}). No changes.
    (不操作路径)
Flow路径:
  • Success — Routing configured — channel {CHANNEL_ID} now routes to Omni-Flow '{FLOW_LABEL}' ({TARGET_ID}), fallback Queue {FALLBACK_QUEUE_ID}.
ASA路径:
  • Success — Routing configured — channel {CHANNEL_ID} now routes to Agentforce Service Agent '{ASA_LABEL}' ({ASA_ID}), fallback Queue {FALLBACK_QUEUE_ID}. Bot user: {BOT_USER_ID}. Active version: {BOT_VERSION_ID}.
  • Info: Routing already configured — ASA '{MasterLabel}' ({ASA_ID}). No changes.
    (不操作路径)
Digital Worker路径:
  • Success — Routing configured — channel {CHANNEL_ID} now routes to Digital Worker '{WORKER_LABEL}' ({TARGET_ID}), fallback Queue {FALLBACK_QUEUE_ID}.
User路径:
  • Success — Routing configured — channel {CHANNEL_ID} now routes directly to User '{USER_NAME}' ({TARGET_ID}).
失败 / 前置条件未满足:
  • Warning: No eligible {routingType} target found. {per-domain Setup pointer from references/target-locate.md}. Then re-run this skill.
    (no-eligible-target)
  • Warning: {routingType} routing needs a fallback queue but none exists. Create a MessagingSession queue first (queue path), then re-run.
    (no-fallback-queue)
  • Warning: This org doesn't have Agentforce licensed (no BotDefinition entity). Use Queue routing instead.
    (asa-not-supported)
  • Warning: This is a Standard (SCRT1) channel — only Flow routing is supported. These skills only create Enhanced channels, so this is unexpected; check the channel.
    (standard-channel)
  • Error: {kind}: {message}
    (其他失败——message字段会指出未通过的服务器端验证规则)

Worked examples

实际运行示例

For reference runs of both the reuse-an-existing-queue fast path (validated on test1) and the create-a-new-queue-via-Metadata-API path, see
references/worked-examples.md
.

如需参考复用现有队列的快速路径(已在test1上验证)和通过Metadata API创建新队列的路径的实际运行示例,请查看
references/worked-examples.md

Gotchas

常见问题

Known gotchas —
Group.Type
filtering, DeveloperName uniqueness, QueueRoutingConfig naming, empty-queue caveats, Metadata-API-only queue creation, the per-domain FallbackQueue requirement matrix, the server-side
nullQueueId
/ readiness enforcement point, the Standard-vs-Enhanced SessionHandler write restriction, and
SessionHandler
polymorphism across org shapes.
When troubleshooting an unexpected result, or before modifying this skill, load
references/gotchas.md
and follow it — it is the complete list.
已知的问题点——
Group.Type
过滤、DeveloperName唯一性、QueueRoutingConfig命名、空队列注意事项、仅通过Metadata API创建队列、按域划分的FallbackQueue要求矩阵、服务器端
nullQueueId
/ 就绪状态强制检查点、Standard与Enhanced通道的SessionHandler写入限制,以及跨组织形态的
SessionHandler
多态性。
排查意外结果或修改本技能之前,请加载
references/gotchas.md
并查看——该文件包含完整的问题列表。