Integrate Whatsapp
gokapso/agent-skills
Connect WhatsApp to your product with Kapso: onboard customers with setup links, detect connections, receive events via webhooks, and send messages/templates/media.
INTERNAL USE ONLY — invoked by service-de-headless-channel-configure.
$ npx skills add forcedotcom/sf-skills --skill service-de-channel-create -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install forcedotcom/sf-skills service-de-channel-create --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-create .claude/skills/service-de-channel-create && 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-create" agent skill from https://github.com/forcedotcom/sf-skills/tree/main/skills/service-de-channel-create into .claude/skills/service-de-channel-create/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "service-de-channel-create", 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-createType 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-create -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install forcedotcom/sf-skills service-de-channel-create --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-create .agents/skills/service-de-channel-create && 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-create" agent skill from https://github.com/forcedotcom/sf-skills/tree/main/skills/service-de-channel-create into .agents/skills/service-de-channel-create/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "service-de-channel-create", 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-create -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install forcedotcom/sf-skills service-de-channel-create --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-create .cursor/skills/service-de-channel-create && 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-create" agent skill from https://github.com/forcedotcom/sf-skills/tree/main/skills/service-de-channel-create into .cursor/skills/service-de-channel-create/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "service-de-channel-create", 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-create--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-create -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install forcedotcom/sf-skills service-de-channel-create --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-create .gemini/skills/service-de-channel-create && 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-create" agent skill from https://github.com/forcedotcom/sf-skills/tree/main/skills/service-de-channel-create into .gemini/skills/service-de-channel-create/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "service-de-channel-create", 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-createInstalls 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-create -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-create .github/skills/service-de-channel-create && 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-create" agent skill from https://github.com/forcedotcom/sf-skills/tree/main/skills/service-de-channel-create into .github/skills/service-de-channel-create/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "service-de-channel-create", 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-create -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-create --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-create .opencode/skills/service-de-channel-create && 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-create" agent skill from https://github.com/forcedotcom/sf-skills/tree/main/skills/service-de-channel-create into .opencode/skills/service-de-channel-create/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "service-de-channel-create", 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-createINTERNAL USE ONLY — invoked by service-de-headless-channel-configure.
Service De Channel Create is an agent skill from forcedotcom/sf-skills. INTERNAL USE ONLY — invoked by service-de-headless-channel-configure. Insert an Enhanced messaging MessagingChannel (plus child MessagingChannelUsage as a free side-effect) of any type — WhatsApp, LINE, Apple Business Chat, Facebook, or SMS. Given a {MESSAGETYPE} and its inputs, runs the shared preflight → Connect-insert → verify flow, branching only where a type differs. Uses POST /services/data/v{V}/connect/livemessage/channels — no Aura session, no shell-stored token. Invoke…
Its SKILL.md is about 5k tokens, which your agent loads only when the skill is triggered. The skill folder holds 8 other files, including reference files (for example `references/apple.md`, `references/connect-insert.md` and `references/facebook.md`).
It sits in Backend & APIs. It works with WhatsApp. 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.
6 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.
Shell commands in SKILL.md call:
sfjqFrom the folder's file list and the shell code blocks in SKILL.md.
Hosts in commands or code, which the agent is likely to contact:
api.line.meFrom URLs in SKILL.md, links to its own repository left out.
Names these keys or tokens, usually read from environment variables:
LINE_CHANNEL_SECRETLINE_ACCESS_TOKENPLATFORM_KEYFrom names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Service De Channel Create loads about 5k tokens when it runs, and up to ~15k if it reads all its reference files. Until then it costs about 170 tokens; SKILL.md has 1,855 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); files beside SKILL.md are not scanned.
The full file from forcedotcom/sf-skills at commit 4bbae5c, republished under its Apache-2.0 licence (© forcedotcom). 1,855 words, ~5,030 tokens.
.claude/skills/service-de-channel-create/SKILL.md (or your agent's skills folder). This skill also uses 7 other files; get the full folder from GitHub.| Reference file | Load when |
|---|---|
references/whatsapp.md | MESSAGE_TYPE=WhatsApp — WABA partnership (Stage 2) + SF-side manage-WABA (Stage 3) prereqs, request body, WhatsApp gotchas. |
references/line.md | MESSAGE_TYPE=Line — optional token verify, authDetails body shape, LINE gotchas. |
references/apple.md | MESSAGE_TYPE=AppleBusinessChat — empty-config body, Apple-precondition errors, Apple gotchas. |
references/facebook.md | MESSAGE_TYPE=Facebook — browser OAuth → page-selection flow, Facebook gotchas. |
references/sms.md | MESSAGE_TYPE=Text — phone-number platform key, present-but-unvalidated smsProvider, number-provisioning prerequisite (caller's), SMS gotchas. |
references/connect-insert.md | Shared authProviderId lookup + Connect POST + response-classification detail (Stage 4). |
references/worked-examples.md | End-to-end traces per type (fresh insert, preflight short-circuit, OAuth). |
Given a {MESSAGE_TYPE} and its inputs, creates a MessagingChannel record with
PlatformType=Enhanced, IsActive=false. The same server-side path
(LiveMessageSetupServiceImpl.addChannel → LiveMessageChannelsUtil.findOrCreateCsotMessagingChannel)
also inserts a MessagingChannelUsage row (DeploymentType=Conversation, DeploymentStatus=New
on fresh insert — Disabled on a channel that was previously activated then deactivated) — we get
it for free.
One primary path for every type: Connect REST API.
POST /services/data/v{V}/connect/livemessage/channels with an org OAuth session managed by
sf api request rest. Public, sanctioned, live since API v66+. No Aura session, no token extracted
into shell state.
Idempotent on (MessagingPlatformKey, MessageType) — re-firing with the same platform key
returns the existing channel's id. This matters because MessagingChannel records are not deletable
via standard means, so the preflight (Stage 1) is the practical idempotency guard.
All types return the same envelope shape, so callers don't branch on type after insert:
{ok, channelId, mcuId, developerName, isActive:false, messageType, messagingPlatformKey, path, created, durationMs}.
{MESSAGE_TYPE} | Platform key (messagingPlatformKey) | Prerequisite (caller supplies) | Body extras | Ref |
|---|---|---|---|---|
WhatsApp | Phone Number ID | service-de-waba-integrate (run in Stage 2-3) | externalAccountId, isoCountryCode | whatsapp.md |
Line | LINE channel id | LINE id + secret + token (LINE Developers Console) | authDetails.{client_secret,access_token} | line.md |
AppleBusinessChat | Apple BC Account ID (GUID) | Apple BC Account ID (register.apple.com/business-chat) | (none — empty config) | apple.md |
Facebook | Facebook Page ID | OAuth handled internally | authDetails: {} (OAuth-derived) | facebook.md |
Text | Phone number / short code | number already provisioned (caller supplies) | smsProvider (key required, value may be ""), isoCountryCode | sms.md |
Unsupported (would need their own leaf logic, not yet built): WeChat, MsCopilot, Alexa.
For these, emit the unsupported-type envelope (Stage 0).
service-de-headless-channel-configure — it orchestrates this skill plus routing, consent, and
activation. This skill only handles the insertion step (see Stage 0).service-de-channel-routing-configure / service-de-channel-activate with the existing
channelId.{MESSAGE_TYPE} — one of WhatsApp, Line, AppleBusinessChat, Facebook, Text.
Case-sensitive (matches the SF picklist). Text is the enum value for SMS — there is no SMS type.{ORG_ALIAS} — optional; sf CLI target-org alias. Default: sf config get target-org.{API_VERSION} — optional; Connect API version. Default: the org's current API version
(sf org display --json | jq -r '.result.apiVersion'). Always use the org's native version to
avoid 404s.{CHANNEL_NAME} — display name shown in Setup → Messaging Settings. Required for
AppleBusinessChat (no phone/screen-name fallback); prompted if omitted for others.Type-specific inputs:
{WABA_ID} (sent as externalAccountId), {PHONE_NUMBER_ID} (the platform
key — must differ from WABA_ID), {ISO_COUNTRY_CODE} (optional, default US).{LINE_CHANNEL_ID} (platform key), {LINE_CHANNEL_SECRET}, {LINE_ACCESS_TOKEN},
{VERIFY_TOKEN_FIRST} (optional, default true).{APPLE_BC_ID} (platform key, GUID).{PAGE_ID} (optional — OAuth fetches/prompts if absent).{SMS_NUMBER} (the platform key — the phone number / short code string, already
provisioned to the org), {SMS_PROVIDER} (sent as smsProvider — the smsProvider key must be
present in the body or the insert 400s with "SMS provider is missing", but its value is not
validated or stored, so an empty string "" works; default to "" when the caller doesn't supply
a provider), {ISO_COUNTRY_CODE} (optional, default US). This skill does not provision the
number — the caller must already know their number.Success:
{"ok": true, "channelId": "0Mj...", "mcuId": "0gL...", "developerName": "...",
"isActive": false, "messageType": "{MESSAGE_TYPE}", "messagingPlatformKey": "...",
"path": "connect" | "preflight", "created": true | false, "durationMs": 1234}created: false + path: "preflight" means the row already existed and was returned idempotently.
Failure (shared):
{"ok": false, "kind": "wrong-skill", "correctSkill": "service-de-headless-channel-configure", "hint": "..."}
{"ok": false, "kind": "unsupported-type", "supportedTypes": ["WhatsApp","Line","AppleBusinessChat","Facebook","Text"], "hint": "..."}
{"ok": false, "kind": "missing-input", "missing": ["..."], "hint": "caller must provide all required inputs for this type"}
{"ok": false, "kind": "auth", "hint": "OAuth token invalid / expired — run 'sf org login web'"}
{"ok": false, "kind": "business", "message": "...", "errorCode": "..."}
{"ok": false, "kind": "transport","status": 500, "message": "..."}
{"ok": false, "kind": "verify-failed", "hint": "Connect returned 201 but follow-up SOQL shows no matching channel"}Type-specific failure kinds (partnership-blocked, user-declined, waba-manage-failed,
meta-precondition for WhatsApp; line-token-invalid for LINE; apple-precondition for Apple;
oauth-not-complete, oauth-failed for Facebook) are documented in the per-type reference files.
This skill is INTERNAL USE ONLY. It should only be invoked by the
service-de-headless-channel-configure orchestrator.
If the user's original request was to "install", "set up", "create", or "activate" a messaging channel (or any phrasing that implies end-to-end setup), immediately return:
{
"ok": false,
"kind": "wrong-skill",
"hint": "This is an internal insertion skill. For end-to-end channel setup (insert → route → activate), invoke 'service-de-headless-channel-configure' instead with the desired MESSAGE_TYPE.",
"correctSkill": "service-de-headless-channel-configure"
}And render to the user:
Error: Wrong skill invoked.
This skill (service-de-channel-create) only handles the insertion step.
For complete channel setup, use: /service-de-headless-channel-configure
That orchestrator runs: insert → configure routing → activate in one flow.Only proceed to Stage 0.1 if:
service-de-headless-channel-configureWhen in doubt, redirect to the orchestrator.
Look up {MESSAGE_TYPE} in the supported-types table. If absent, emit the unsupported-type
envelope and return.
Validate the type's required inputs are present (Facebook is the exception — no required
inputs; OAuth → page selection → prompts happen inside the Facebook flow). If any are missing,
emit missing-input with the list and return.
WhatsApp only: additionally assert {WABA_ID} != {PHONE_NUMBER_ID} — they are distinct Meta
entities and reusing one value for both causes cryptic activation failures. If equal, emit
{ok:false, kind:"invalid-input", hint:"WABA_ID and PHONE_NUMBER_ID must differ — WABA_ID is the WhatsApp Business Account ID; PHONE_NUMBER_ID is a specific phone number within it. Find both in Meta Business Manager → WhatsApp Accounts."}.
Capture {T0} = Date.now() for durationMs.
Every transient artifact this skill writes (preflight query results, request bodies, Connect
responses) goes into a per-run scratch directory rooted inside the harness working area — never a
bare absolute /tmp path, which is world-writable and non-portable. Establish it once:
SCRATCH_DIR="$(mktemp -d "${outputDir:-${TMPDIR:-/tmp}}/icc.XXXXXX")"The base dir is the harness-provided ${outputDir} when set, else the private user-scoped
${TMPDIR}, else /tmp only as a last resort. All later stages (and the reference flows) write
under ${SCRATCH_DIR}/; the durable report stays under ${outputDir}.
SOQL-probe for an existing row first; a hit lets us skip all prerequisites and the insert.
For Facebook without a {PAGE_ID}, skip this stage — the page id isn't known until OAuth →
page selection completes (see references/facebook.md). Run the preflight after page selection.
Two queries, not a subquery. The (SELECT ... FROM MessagingChannelUsages) child subquery
fails with INVALID_TYPE on orgs where the child relationship is unnameable (verified on
wadtesting / PRODDEBUG). The FK-keyed form works everywhere.
sf data query --target-org '{ORG_ALIAS}' \
--query "SELECT Id, DeveloperName, MasterLabel, IsActive, MessagingPlatformKey FROM MessagingChannel WHERE MessagingPlatformKey = '{PLATFORM_KEY}' AND MessageType = '{MESSAGE_TYPE}'" \
--json > "${SCRATCH_DIR}/preflight.json"If records.length === 1:
{CHANNEL_ID}, {DEVELOPER_NAME}, {IS_ACTIVE}.sf data query --target-org '{ORG_ALIAS}' \
--query "SELECT Id, DeploymentStatus FROM MessagingChannelUsage WHERE MessagingChannelId = '{CHANNEL_ID}'" \
--json > "${SCRATCH_DIR}/preflight-mcu.json"{MCU_ID} (empty MCU: flag, don't fail — the activation skill handles it).path: "preflight", created: false. Return.If records.length > 1: ambiguous (uniqueness should prevent this) — proceed with the first,
note a warning in the envelope.
If records.length === 0: proceed to Stage 2.
Most types have no prerequisite here — go straight to Stage 4.
service-de-waba-integrate) and the SF-side webhook subscription + credit-line share
(Stage 3, POST /connect/livemessage/whatsapp/business-account). Load references/whatsapp.md
and follow it before inserting.https://api.line.me/v2/bot/info if
{VERIFY_TOKEN_FIRST} is true. See references/line.md.references/facebook.md and follow it.references/apple.md.)smsProvider, but this skill performs no provisioning step — it inserts the record for
a number the caller already has. (ESP registration runs at activation, not insert — see
references/sms.md.)Shared across all types. The only per-type difference is the request body; the authProviderId lookup, the POST invocation, and the response-classification table are identical.
sf data query --target-org '{ORG_ALIAS}' \
--query "SELECT Id FROM AuthProvider WHERE DeveloperName = 'LiveMessageSetup'" \
--json > "${SCRATCH_DIR}/authprovider.json"One row → {AUTH_PROVIDER_ID}. Zero rows → branch on type:
Text — non-fatal. Text's Connect signature doesn't take authProviderId, so leave
{AUTH_PROVIDER_ID} unset and continue to Stage 4.2; the POST omits the parameter entirely (see
below). Do not emit the business error for Text — an org that has never run LiveMessage setup
is exactly where the Text-only path matters, and blocking here would make the advertised SMS insert
unreachable on those orgs.WhatsApp, Line, AppleBusinessChat, Facebook) — the org has never run
LiveMessage setup and the insert can't proceed; emit
{ok:false, kind:"business", message:"No AuthProvider 'LiveMessageSetup' found — run the Messaging Setup wizard once on this org first"}.The Connect endpoint rejects the POST with 400 ILLEGAL_QUERY_PARAMETER_VALUE "Missing argument authProviderId" if this URL parameter is absent — verified for every type except Text, Apple
included. (Text has its own Connect signature that doesn't require it.) When the lookup finds a row,
send authProviderId for every type including Text (harmless there); when it finds none, only Text may
proceed, and it proceeds without the parameter. authProviderId goes in the URL query string,
never the body (body → 400 JSON_PARSER_ERROR "Unrecognized field 'authProviderId'").
Resolve {CHANNEL_NAME} first (prompt if required and absent — see per-type ref). Then build the
body from the supported-types table and POST. Write the body to a file (--body @...) — LINE
tokens are long and can contain shell-hostile characters.
Append the authProviderId query parameter only when Stage 4.1 resolved one — otherwise (the
Text-with-no-AuthProvider case) POST to the bare endpoint, since an empty ?authProviderId= would
trip the same ILLEGAL_QUERY_PARAMETER_VALUE:
URL="/services/data/v{API_VERSION}/connect/livemessage/channels"
[ -n "${AUTH_PROVIDER_ID:-}" ] && URL="${URL}?authProviderId=${AUTH_PROVIDER_ID}"
sf api request rest "${URL}" \
--method POST --target-org '{ORG_ALIAS}' \
--header 'Content-Type: application/json' --header 'Accept: application/json' \
--body @"${SCRATCH_DIR}/body.json" --include > "${SCRATCH_DIR}/connect-response.txt" 2>&1--include prints the HTTP status/header block before the body — read the status from there, not
a trailing -w marker. sf api request rest manages OAuth internally.
For the exact per-type body shape and the full response-classification table (including the
DUPLICATE_VALUE race back to Stage 1, the Facebook AUTH_PROVIDER_NEEDS_AUTH 401-vs-400
disambiguation, and per-type precondition errors), load references/connect-insert.md plus the
per-type ref.
Two queries (same no-subquery reason as Stage 1). Keep to the universal field set —
ExternalAccountId and MessagingPlatform don't exist on all orgs.
sf data query --target-org '{ORG_ALIAS}' \
--query "SELECT Id, DeveloperName, MasterLabel, MessageType, IsActive, MessagingPlatformKey FROM MessagingChannel WHERE Id = '{CHANNEL_ID}'" --json
sf data query --target-org '{ORG_ALIAS}' \
--query "SELECT Id, DeploymentStatus, DeploymentType FROM MessagingChannelUsage WHERE MessagingChannelId = '{CHANNEL_ID}'" --jsonExpected: channel IsActive=false; exactly one MCU, DeploymentType=Conversation,
DeploymentStatus in {New, Disabled} (fresh inserts land in New; Disabled is a
previously-activated-then-deactivated channel — both are valid starting states for activation).
Empty MCU query → {ok:false, kind:"verify-failed", hint:"Connect returned {CHANNEL_ID} but no child MessagingChannelUsage was created"}.
Trust the DB, not the Connect response body, for MasterLabel / DeveloperName — the 201 body
carries stale input-rep projections (see per-type gotchas).
{"ok": true, "channelId": "{CHANNEL_ID}", "mcuId": "<from Stage 5>",
"developerName": "<authoritative, from Stage 5>", "isActive": false,
"messageType": "{MESSAGE_TYPE}", "messagingPlatformKey": "{PLATFORM_KEY}",
"path": "connect", "created": true, "durationMs": <Date.now() - T0>}Rendered (when invoked directly rather than by the orchestrator):
Success — MessagingChannel {CHANNEL_ID} ({developerName}) created via {path}. MCU {mcuId} auto-created. IsActive=false — run routing, then consent, then activate next.Info: Channel already exists — {CHANNEL_ID} ({developerName}). Proceed to routing/activation.Error: {kind}: {message or hint}On success the caller can immediately invoke service-de-channel-routing-configure with the
returned channelId, then service-de-channel-settings-configure, then
service-de-channel-activate. Those three are message-type-agnostic (they operate on
MessagingChannel.Id + MessagingChannelUsage.Id), so there's no downstream dispatch concern.
"whatsapp" ≠ "WhatsApp" — the SF picklist, SOQL filters,
and Connect enum all match exactly. Normalize upstream; don't make Stage 0.1 case-insensitive.MessagingChannel rows aren't deletable via standard
means, so re-runs rely on Stage 1 finding the existing row.service-de-headless-channel-configure) silently sees the change — break loudly
in tests rather than remap field names.references/<type>.md when debugging that type.© 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 7 other files (references) in skills/service-de-channel-create of forcedotcom/sf-skills.
Open the folder on GitHubat commit 4bbae5c
Service De Channel Create 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 Create this skillforcedotcom/sf-skills | 1.1k | — | ~5k | Automated safety check: Pass | Apache-2.0 | |
| Integrate Whatsappgokapso/agent-skills | 177 | — | ~4.8k | Automated safety check: Pass | None | |
| Observe Whatsappgokapso/agent-skills | 177 | — | ~1.8k | Automated safety check: Pass | None | |
| Add Channel Connect Buttonnovuhq/novu | 40k | — | ~1.6k | Automated safety check: Pass | Custom licence | |
| Better Notifybetter-notify/better-notify | 313 | — | ~783 | Automated safety check: Pass | MIT | |
| Whatsapp Cloud APIsickn33/agentic-awesome-skills | 47k | 2 repos | ~4.5k | Automated safety check: Pass | MIT |
gokapso/agent-skills
Connect WhatsApp to your product with Kapso: onboard customers with setup links, detect connections, receive events via webhooks, and send messages/templates/media.
gokapso/agent-skills
Observe and troubleshoot WhatsApp in Kapso: search Logs across API, Meta webhook, workflow, and webhook-delivery events; debug message delivery; inspect webhook retries; triage API errors; and run…
novuhq/novu
Build a new channel Connect button (e.g. An agent skill from novuhq/novu.
better-notify/better-notify
End-to-end typed notification infrastructure for Node.js — typed catalog of email, SMS, push, web push, WhatsApp, Slack, Discord, Telegram, and GitHub notifications with provider-agnostic transports.
sickn33/agentic-awesome-skills
Integracao com WhatsApp Business Cloud API (Meta). An agent skill from sickn33/agentic-awesome-skills.
gokapso/agent-skills
Build and debug Kapso WhatsApp workflows, triggers, functions, and executions.
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.
Works with
Categories
INTERNAL USE ONLY — invoked by service-de-headless-channel-configure. Service De Channel Create is an agent skill from forcedotcom/sf-skills. INTERNAL USE ONLY — invoked by service-de-headless-channel-configure.
Service De Channel Create fits situations like: backend & APIs work in your project.
Run `npx skills add forcedotcom/sf-skills --skill service-de-channel-create -a claude-code`. Or copy the skill folder (skills/service-de-channel-create in forcedotcom/sf-skills) into .claude/skills/service-de-channel-create in your project. Claude Code loads it when a task matches its description.
Run `npx skills add forcedotcom/sf-skills --skill service-de-channel-create -a codex`. Or copy the skill folder (skills/service-de-channel-create in forcedotcom/sf-skills) into .agents/skills/service-de-channel-create 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-create -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-create, .gemini/skills/service-de-channel-create, .github/skills/service-de-channel-create and .opencode/skills/service-de-channel-create in your project.
Going by SKILL.md and its folder, Service De Channel Create needs the command-line tools its instructions call (sf and jq) and credentials named LINE_CHANNEL_SECRET, LINE_ACCESS_TOKEN and PLATFORM_KEY. Our summary lists: A credential in LINE_CHANNEL_SECRET; A credential in LINE_ACCESS_TOKEN.
SKILL.md names 1 domain. In commands or code: api.line.me; the agent is likely to contact it when it follows the instructions. 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. Review the folder before installing.
Service De Channel Create 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 5k tokens (SKILL.md is roughly 20k 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 9.8k tokens, read only when the agent opens those files.
Skills that share tags, products or a category with Service De Channel Create: Integrate Whatsapp (gokapso/agent-skills, 177 stars), Observe Whatsapp (gokapso/agent-skills, 177 stars), Add Channel Connect Button (novuhq/novu, 40k stars) and Better Notify (better-notify/better-notify, 313 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.