Configuring Horizon
coollabsio/coolify
A skill your agent uses whenever the user mentions Horizon by name in a Laravel context.
Configure routing on a newly-inserted Enhanced MessagingChannel so activation will accept it.
$ npx skills add forcedotcom/sf-skills --skill service-de-channel-routing-configure -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install forcedotcom/sf-skills service-de-channel-routing-configure --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/forcedotcom/sf-skills.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/service-de-channel-routing-configure .claude/skills/service-de-channel-routing-configure && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "service-de-channel-routing-configure" agent skill from https://github.com/forcedotcom/sf-skills/tree/main/skills/service-de-channel-routing-configure into .claude/skills/service-de-channel-routing-configure/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "service-de-channel-routing-configure", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/forcedotcom/sf-skills/tree/main/skills/service-de-channel-routing-configureType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add forcedotcom/sf-skills --skill service-de-channel-routing-configure -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install forcedotcom/sf-skills service-de-channel-routing-configure --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/forcedotcom/sf-skills.git skills-src && mkdir -p .agents/skills && cp -r skills-src/skills/service-de-channel-routing-configure .agents/skills/service-de-channel-routing-configure && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "service-de-channel-routing-configure" agent skill from https://github.com/forcedotcom/sf-skills/tree/main/skills/service-de-channel-routing-configure into .agents/skills/service-de-channel-routing-configure/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "service-de-channel-routing-configure", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add forcedotcom/sf-skills --skill service-de-channel-routing-configure -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install forcedotcom/sf-skills service-de-channel-routing-configure --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/forcedotcom/sf-skills.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/skills/service-de-channel-routing-configure .cursor/skills/service-de-channel-routing-configure && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "service-de-channel-routing-configure" agent skill from https://github.com/forcedotcom/sf-skills/tree/main/skills/service-de-channel-routing-configure into .cursor/skills/service-de-channel-routing-configure/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "service-de-channel-routing-configure", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/forcedotcom/sf-skills.git --path skills/service-de-channel-routing-configure--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add forcedotcom/sf-skills --skill service-de-channel-routing-configure -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install forcedotcom/sf-skills service-de-channel-routing-configure --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/forcedotcom/sf-skills.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/skills/service-de-channel-routing-configure .gemini/skills/service-de-channel-routing-configure && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "service-de-channel-routing-configure" agent skill from https://github.com/forcedotcom/sf-skills/tree/main/skills/service-de-channel-routing-configure into .gemini/skills/service-de-channel-routing-configure/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "service-de-channel-routing-configure", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install forcedotcom/sf-skills service-de-channel-routing-configureInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add forcedotcom/sf-skills --skill service-de-channel-routing-configure -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/forcedotcom/sf-skills.git skills-src && mkdir -p .github/skills && cp -r skills-src/skills/service-de-channel-routing-configure .github/skills/service-de-channel-routing-configure && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "service-de-channel-routing-configure" agent skill from https://github.com/forcedotcom/sf-skills/tree/main/skills/service-de-channel-routing-configure into .github/skills/service-de-channel-routing-configure/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "service-de-channel-routing-configure", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add forcedotcom/sf-skills --skill service-de-channel-routing-configure -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install forcedotcom/sf-skills service-de-channel-routing-configure --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/forcedotcom/sf-skills.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/skills/service-de-channel-routing-configure .opencode/skills/service-de-channel-routing-configure && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "service-de-channel-routing-configure" agent skill from https://github.com/forcedotcom/sf-skills/tree/main/skills/service-de-channel-routing-configure into .opencode/skills/service-de-channel-routing-configure/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "service-de-channel-routing-configure", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
service-de-channel-routing-configureConfigure routing on a newly-inserted Enhanced MessagingChannel so activation will accept it.
Service De Channel Routing Configure is an agent skill from forcedotcom/sf-skills. Configure routing on a newly-inserted Enhanced MessagingChannel so activation will accept it. Given a {CHANNELID}, walks through picking a routing type (Omni-Channel Queue, Omni-Flow, Agentforce Service Agent, Digital Worker, or direct User), locates or provisions the target, then PATCHes SessionHandlerId (plus FallbackQueueId where required). Use between insertion and activation — activation fails server-side with nullQueueId/LiveMessageSetupException if no valid SessionHandlerId is set. Do not use for full…
Its SKILL.md is about 5.6k tokens, which your agent loads only when the skill is triggered. The skill folder holds 9 other files, including scripts and reference files (for example `references/asa-routing.md`, `references/gotchas.md` and `references/queue-creation.md`).
It sits in Backend & APIs, covering Backend development. The repository describes itself as: Salesforce's curated collection of agent skills for building applications. Optimized for Agentforce Vibes, compatible with all AI tools. The licence is Apache-2.0.
8 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit 4bbae5c. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Ships 1 file in scripts/ (Python), which the agent can run.
Shell commands in SKILL.md call:
sfnodeFrom the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Service De Channel Routing Configure loads about 5.6k tokens when it runs, and up to ~13k if it reads all its reference files. Until then it costs about 157 tokens; SKILL.md has 1,868 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); the scripts in this folder are not scanned.
The full file from forcedotcom/sf-skills at commit 4bbae5c, republished under its Apache-2.0 licence (© forcedotcom). 1,868 words, ~5,647 tokens.
.claude/skills/service-de-channel-routing-configure/SKILL.md (or your agent's skills folder). This skill also uses 6 other files; get the full folder from GitHub.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-settings-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:
| Type | SessionHandler target | Id prefix | FallbackQueue |
|---|---|---|---|
| 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:
MessagingSession-capable Queue, or create a new Queue + QueueRoutingConfig via Metadata API.| Reference file | Load 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. |
SessionHandlerId or FallbackQueueId set. This skill revalidates the existing target before no-op. An ASA must still have a BotUser and an Active BotVersion; otherwise it reports asa-target-inactive and does not claim readiness.MessagingChannel.Id.SessionHandlerId manually in the UI, then re-run this skill. The no-op check is a guardrail, not a limitation worth bypassing automatically.{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.One of:
Success — no change needed:
{"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:
{"ok": true, "routingType": "queue", "sessionHandlerId": "00G...", "fallbackQueueId": null, "queueName": "...", "queueDeveloperName": "...", "created": true|false}Success — Flow routing configured:
{"ok": true, "routingType": "flow", "sessionHandlerId": "300...", "fallbackQueueId": "00G...", "flowName": "...", "flowDeveloperName": "...", "created": false}Success — ASA routing configured:
{"ok": true, "routingType": "asa", "sessionHandlerId": "0Xx...", "fallbackQueueId": "00G...", "asaName": "...", "asaDeveloperName": "...", "botUserId": "005...", "botVersionId": "0X9...", "created": false}Success — Digital Worker routing configured:
{"ok": true, "routingType": "digital_worker", "sessionHandlerId": "1iE...", "fallbackQueueId": "00G...", "workerName": "...", "created": false}Success — User routing configured:
{"ok": true, "routingType": "user", "sessionHandlerId": "005...", "fallbackQueueId": null, "userName": "...", "created": false}Precondition not met:
{"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:
{"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).
Query the channel. If it already has SessionHandlerId OR FallbackQueueId, no-op. Otherwise, continue.
sf data query --target-org '{ORG_ALIAS}' \
--query "SELECT Id, DeveloperName, SessionHandlerId, FallbackQueueId FROM MessagingChannel WHERE Id = '{CHANNEL_ID}'" \
--json > /tmp/ccr-channel.jsonParse 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). Existing routing is not automatically healthy: the target lookup must return exactly one eligible row before reporting a successful no-op.
| Prefix | Domain / Target | Lookup query | 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, BotUserId, (SELECT Id, Status FROM BotVersions WHERE Status='Active' LIMIT 1) 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 |
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, BotUserId, (SELECT Id, Status FROM BotVersions WHERE Status='Active' LIMIT 1) 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 ;;
esacFor an existing ASA (0Xx), require a non-null BotUserId and one returned BotVersions row with Status='Active'. If either is missing, return the following failure instead of a successful no-op. Do not clear or replace the channel routing automatically:
{"ok":false,"kind":"asa-target-inactive","routingType":"asa","sessionHandlerId":"0Xx...","hint":"The configured Agentforce Service Agent has no BotUser or active BotVersion. Activate the agent in Setup, then re-run routing validation."}For other prefixes, require exactly one target lookup row. Report the success-noop envelope (include the existing FallbackQueueId from the Stage 1 read) only after the target-specific eligibility check succeeds, then 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.
First confirm PlatformType. The Stage 1 read didn't include it — add it, or re-query:
sf data query --target-org '{ORG_ALIAS}' \
--query "SELECT Id, PlatformType FROM MessagingChannel WHERE Id = '{CHANNEL_ID}'" --json > /tmp/ccr-platform.jsonIf 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):
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:
FlowDefinition (ProcessType=RoutingFlow, active version) + a FallbackQueue, then Stage 5.AgenticCtxtDecorDefinition + a FallbackQueue, then Stage 5.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.
(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.
# MessagingSession-capable queues that are also Omni-enabled (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.jsonEach 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:
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 as {QUEUE_ID} (this is the Group.Id). Skip to Stage 5.If the list is empty AND the user picks (1) "Create a new queue" implicitly, skip directly to Stage 4.
(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).
(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).
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:
# queue / user — SessionHandler only
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
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.jsonIf 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)").
Re-read the channel:
sf data query --target-org '{ORG_ALIAS}' \
--query "SELECT Id, SessionHandlerId, FallbackQueueId FROM MessagingChannel WHERE Id = '{CHANNEL_ID}'" \
--jsonIf the freshly-read SessionHandlerId doesn't equal {TARGET_ID} — or (for flow/asa/digital_worker) FallbackQueueId doesn't equal {FALLBACK_QUEUE_ID}:
{"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).
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)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.
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.
© forcedotcom, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 6 other files (scripts, references) in skills/service-de-channel-routing-configure of forcedotcom/sf-skills.
Open the folder on GitHubat commit 4bbae5c
Service De Channel Routing Configure next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Service De Channel Routing Configure this skillforcedotcom/sf-skills | 1.1k | — | ~5.6k | Automated safety check: Pass | Apache-2.0 | |
| Configuring Horizoncoollabsio/coolify | 63k | 4 repos | ~898 | Automated safety check: Pass | MIT | |
| Fortify Developmentcoollabsio/coolify | 63k | 4 repos | ~1.9k | Automated safety check: Pass | MIT | |
| Node Backend Development Guidelinesdiet103/claude-code-infrastructure-showcase | 10k | 2 repos | ~2k | Automated safety check: Pass | MIT | |
| Laravel Best Practicesanonaddy/anonaddy | 4.9k | 13 repos | ~1.2k | Automated safety check: Pass | MIT | |
| Laravel Actionscoollabsio/coolify | 63k | — | ~2.4k | Automated safety check: Pass | Apache-2.0 |
coollabsio/coolify
A skill your agent uses whenever the user mentions Horizon by name in a Laravel context.
coollabsio/coolify
ACTIVATE when the user works on authentication in Laravel. An agent skill from coollabsio/coolify.
diet103/claude-code-infrastructure-showcase
Sets layered architecture and coding rules for Node.js, Express and TypeScript microservices, covering routes, controllers, services, repositories, Prisma, Sentry and Zod.
anonaddy/anonaddy
Apply this skill whenever writing, reviewing, or refactoring Laravel PHP code.
coollabsio/coolify
Build, refactor, and troubleshoot Laravel Actions using lorisleiva/laravel-actions.
ever-works/ever-works
Build production-ready Node.js backend services with Express/Fastify, implementing middleware patterns, error handling, authentication, database integration, and API design best practices.
forcedotcom/sf-skills
Declared architecture snapshot for one Agentforce agent: planner, topics, actions, flows, Apex, prompt templates, and NGA plugins.
forcedotcom/sf-skills
Data Cloud 360° view of a single Agentforce session. An agent skill from forcedotcom/sf-skills.
forcedotcom/sf-skills
Apply a Salesforce sandbox post-copy automation JSON config against a target org.
forcedotcom/sf-skills
Apply a Salesforce sandbox post-copy automation JSON config against a target org.
forcedotcom/sf-skills
Apply SLDS-compliant UI using the correct blueprints, styling hooks, utility classes, and icons.
forcedotcom/sf-skills
Lightning Web Components with PICKLES methodology and 165-point scoring.
Categories
Configure routing on a newly-inserted Enhanced MessagingChannel so activation will accept it. Service De Channel Routing Configure is an agent skill from forcedotcom/sf-skills. Configure routing on a newly-inserted Enhanced MessagingChannel so activation will accept it.
Service De Channel Routing Configure fits situations like: full end-to-end setup — use service-de-headless-channel-configure; tasks that involve Backend development.
Run `npx skills add forcedotcom/sf-skills --skill service-de-channel-routing-configure -a claude-code`. Or copy the skill folder (skills/service-de-channel-routing-configure in forcedotcom/sf-skills) into .claude/skills/service-de-channel-routing-configure in your project. Claude Code loads it when a task matches its description.
Run `npx skills add forcedotcom/sf-skills --skill service-de-channel-routing-configure -a codex`. Or copy the skill folder (skills/service-de-channel-routing-configure in forcedotcom/sf-skills) into .agents/skills/service-de-channel-routing-configure in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add forcedotcom/sf-skills --skill service-de-channel-routing-configure -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/service-de-channel-routing-configure, .gemini/skills/service-de-channel-routing-configure, .github/skills/service-de-channel-routing-configure and .opencode/skills/service-de-channel-routing-configure in your project.
Going by SKILL.md and its folder, Service De Channel Routing Configure needs Python for the scripts in its folder and the command-line tools its instructions call (sf and node). Our summary lists: Python 3.
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. The check reads SKILL.md only: the scripts in the folder are not scanned, so read them before running anything.
Service De Channel Routing Configure is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 5.6k tokens (SKILL.md is roughly 23k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 7.8k tokens, read only when the agent opens those files.
Skills that share tags, products or a category with Service De Channel Routing Configure: Configuring Horizon (coollabsio/coolify, 63k stars), Fortify Development (coollabsio/coolify, 63k stars), Node Backend Development Guidelines (diet103/claude-code-infrastructure-showcase, 10k stars) and Laravel Best Practices (anonaddy/anonaddy, 4.9k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
forcedotcom (a GitHub organization) maintains it in forcedotcom/sf-skills, which has 1,067 GitHub stars. The repository holds 252 skills in this directory. The repository was last updated on October 9, 2026.
Source: forcedotcom/sf-skills on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.