Loading...
Loading...
Wires an existing, active Agentforce agent to a channel by resolving a fallback queue, setting up inbound routing (either PATCH SessionHandlerId on the MessagingChannel, or an inbound RoutingFlow for Voice/Email), and optionally configuring outbound escalation. Use when the user wants to add a channel to an existing agent, connect an agent to a messaging or voice channel, route Voice or Email-to-Case to an Agentforce agent, or set up a fallback queue for an agent channel. Applies to any already-created agent, including an existing Help Agent. The channel infrastructure (MessagingChannel, Voice config, email-to-case) must already exist — this skill only adds the routing. DO NOT TRIGGER when the agent does not yet exist or still needs Help Agent setup (use agentforce-generate or service-helpagent-coordinate), when creating the MessagingChannel itself (use service-digital-engagement-channel-configure), or when creating an Embedded Service Deployment (use service-digital-engagement-deployment-configure).
npx skill4agent add forcedotcom/sf-skills service-agentforce-channel-configureQueueSobjectsessionHandlerType=AgentforceServiceAgentsessionHandlerQueueSessionHandlerIdPstnVoiceservice-helpagent-coordinateroutingType: Copilotconnection {type}:agentforce-generateservice-helpagent-coordinateservice-digital-engagement-channel-configureservice-digital-engagement-deployment-configureDeveloperNameMasterLabelDeveloperNamereferences/channel-types.md# Get the definition
sf data query --target-org $ORG --json \
--query "SELECT Id, DeveloperName, MasterLabel FROM BotDefinition WHERE DeveloperName='{AGENT_DEVELOPER_NAME}'"
# Check for an Active version
sf data query --target-org $ORG --json \
--query "SELECT Id, Status FROM BotVersion WHERE BotDefinitionId='{BOT_DEFINITION_ID}' AND Status='Active' LIMIT 1"Status = Activereferences/queue-resolution.mdreferences/channel-types.mdAskUserQuestionQueueRoutingConfigQUEUE_DEVELOPER_NAMEQUEUE_NAMEQUEUE_IDSessionHandlerTypeAskUserQuestionDEFER_INBOUND_ROUTING=trueAskUserQuestionreferences/live-traffic-gate.mdsessionHandlerTypesessionHandlerQueuesessionHandlerAsaSessionHandlerId.messagingChannel-meta.xmlforce-appsf project retrieve start \
--metadata "MessagingChannel:{CHANNEL_DEVELOPER_NAME}" \
--target-org $ORG.messagingChannel-meta.xml<sessionHandlerAsa><sessionHandlerType>AgentforceServiceAgent</sessionHandlerType>
<sessionHandlerQueue>{QUEUE_DEVELOPER_NAME}</sessionHandlerQueue>force-app/main/default/messagingChannels/{CHANNEL_DEVELOPER_NAME}.messagingChannel-meta.xmlsedcatsf project deploy start \
--metadata "MessagingChannel:{CHANNEL_DEVELOPER_NAME}" \
--target-org $ORGCHAN_ID=$(sf data query --target-org $ORG --json \
--query "SELECT Id FROM MessagingChannel WHERE DeveloperName='{CHANNEL_DEVELOPER_NAME}'" \
| python3 -c "import sys,json; print(json.load(sys.stdin)['result']['records'][0]['Id'])")
BOT_ID=$(sf data query --target-org $ORG --json \
--query "SELECT Id FROM BotDefinition WHERE DeveloperName='{AGENT_DEVELOPER_NAME}'" \
| python3 -c "import sys,json; print(json.load(sys.stdin)['result']['records'][0]['Id'])")
QUEUE_ID=$(sf data query --target-org $ORG --json \
--query "SELECT Id FROM Group WHERE Type='Queue' AND DeveloperName='{QUEUE_DEVELOPER_NAME}'" \
| python3 -c "import sys,json; print(json.load(sys.stdin)['result']['records'][0]['Id'])")
sf api request rest --method PATCH -o $ORG \
"/services/data/v67.0/sobjects/MessagingChannel/${CHAN_ID}" \
--body "{\"SessionHandlerId\":\"${BOT_ID}\",\"FallbackQueueId\":\"${QUEUE_ID}\"}"
# Expected: HTTP 204sf data query --target-org $ORG --json \
--query "SELECT SessionHandlerId, FallbackQueueId FROM MessagingChannel WHERE Id='${CHAN_ID}'"SessionHandlerIdFallbackQueueIdPstnVoiceCopilotsessionHandlerAsasessionHandlerType=Flowmodality voice:references/channel-branch-voice.mdPstnVoiceservice-helpagent-coordinatereferences/channel-voice.mdreferences/channel-types.mdreferences/routing-flow.mdActiveVersionIdMessagingChannel{CHANNEL_DEVELOPER_NAME}sessionHandlerType=FlowsessionHandlerFlow={FLOW_DEVELOPER_NAME}sessionHandlerQueue={QUEUE_DEVELOPER_NAME}SessionHandlerId300modality voice:UgBBYS2sOqTuMpoF3BR0.agentreferences/agent-wiring.mdconnection service_email:references/channel-branch-email.mdemailToCase.enableEmailToCaseemailToCase.enableOnDemandEmailToCasetrueEmailRoutingAddresscaseOriginsaveEmailHeaders: trueaddressType: EmailToCaseCaseSettings.Metadata.caseEmailRoutingAddressessf project deploy start --metadata Settings:Casereferences/channel-types.mdreferences/routing-flow.mdActiveVersionId{AgentDevName}_Outbound_Email_Flowreferences/routing-flow.mdconnection service_email:references/agent-wiring.md{ORG_INSTANCE_URL}/lightning/setup/AsaForEmail/homeBranch C (Email-to-Case): outbound escalation was handled inline in Branch C above. Do not run Phase 3 for Email-to-Case.
"Inbound routing is now set up — the channel will route to [agent name]. Do you also want to configure outbound escalation so the agent can hand off to a human when requested?"
references/queue-resolution.mdESCALATION_QUEUE_DEVELOPER_NAMEESCALATION_QUEUE_IDreferences/routing-flow.mdsf data query --target-org $ORG --json \
--query "SELECT ApiName, ActiveVersionId FROM FlowDefinitionView WHERE ApiName='{OUTBOUND_FLOW_DEVELOPER_NAME}' AND ProcessType='RoutingFlow'"ActiveVersionIdActiveVersionIdreferences/routing-flow.mdESCALATION_QUEUE_DEVELOPER_NAMEQUEUE_DEVELOPER_NAMEActiveVersionId.agentreferences/agent-wiring.mdconnection customer_web_client:connection messaging:connection telephony:connection service_email:| Rule | Rationale |
|---|---|
| Verify the agent exists and is Active before making any changes | Wiring a channel to a non-existent or inactive agent silently fails at runtime |
If the channel already has active inbound routing, honor an explicit defer/cutover intent in the prompt without asking; otherwise warn via | Re-routing takes effect immediately and affects live traffic — queue and RoutingFlow creation always proceed; only the activation step is gated, and the safe default is non-destructive |
| When deferred, print exact manual wiring instructions before Phase 3 | The operator needs to know precisely what to run when they're ready to cut over |
| Never modify the MessagingChannel without retrieving the current metadata first | Overwriting without retrieval discards existing settings |
Branch A: no RoutingFlow, no agent republish; deploy | |
| Branches B/C: always create a new RoutingFlow — never reuse existing org flows | OOB platform flows commonly have |
Branches B/C: use | |
Queue | The |
Queue naming: | Named after the channel type, not the agent |
| Outbound escalation is optional for Branches A/B — mandatory for Branch C (Email-to-Case) | BotEmailDefinition (Email Configuration in Setup) requires |
QueueSobjectSobjectTypeQueueRoutingConfigCapacityPercentageSessionHandlerType = AgentforceServiceAgentSessionHandlerIdBotDefinition.Id0XxFallbackQueueIdActiveVersionIdroutingType = CopilotrouteWorkcopilotLabelMasterLabelqueueIdEmailRoutingAddressPersonalNameAddresscaseOriginsaveEmailHeaders: trueaddressType: EmailToCase/lightning/setup/AsaForEmail/homecustomer_web_client:messaging:telephony:service_email:outboundRouteNameoutboundRouteType<plannerSurfaces>| File | When to read |
|---|---|
| Phase 1 — determine SobjectType and routing branch |
| Phase 1 — queue lookup, creation, and Id capture |
| Phase 2 — detection queries, deferred-flow rules, and manual wiring copy for the live-traffic warning gate |
| Branch B — full Voice inbound wiring: PstnVoice channel selection, RoutingFlow, MessagingChannel assignment, |
| Branch C — full Email-to-Case wiring: CaseSettings flags, EmailRoutingAddress + read-modify-write patch, inbound RoutingFlow, mandatory outbound |
| Branches B/C — inbound RoutingFlow XML template, deploy, verify |
| Phase 3 (optional) — outbound escalation |