Web Asset Generator
alonw0/web-asset-generator
Generate web assets including favicons, app icons (PWA), and social media meta images (Open Graph) for Facebook, Twitter, WhatsApp, and LinkedIn.
Top-level orchestrator: given a messaging channel type and its inputs, produces an activated Enhanced MessagingChannel in the target org — without the Meta/LINE/Apple setup popups.
$ npx skills add forcedotcom/sf-skills --skill service-de-headless-channel-configure -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install forcedotcom/sf-skills service-de-headless-channel-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-headless-channel-configure .claude/skills/service-de-headless-channel-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-headless-channel-configure" agent skill from https://github.com/forcedotcom/sf-skills/tree/main/skills/service-de-headless-channel-configure into .claude/skills/service-de-headless-channel-configure/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "service-de-headless-channel-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-headless-channel-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-headless-channel-configure -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install forcedotcom/sf-skills service-de-headless-channel-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-headless-channel-configure .agents/skills/service-de-headless-channel-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-headless-channel-configure" agent skill from https://github.com/forcedotcom/sf-skills/tree/main/skills/service-de-headless-channel-configure into .agents/skills/service-de-headless-channel-configure/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "service-de-headless-channel-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-headless-channel-configure -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install forcedotcom/sf-skills service-de-headless-channel-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-headless-channel-configure .cursor/skills/service-de-headless-channel-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-headless-channel-configure" agent skill from https://github.com/forcedotcom/sf-skills/tree/main/skills/service-de-headless-channel-configure into .cursor/skills/service-de-headless-channel-configure/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "service-de-headless-channel-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-headless-channel-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-headless-channel-configure -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install forcedotcom/sf-skills service-de-headless-channel-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-headless-channel-configure .gemini/skills/service-de-headless-channel-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-headless-channel-configure" agent skill from https://github.com/forcedotcom/sf-skills/tree/main/skills/service-de-headless-channel-configure into .gemini/skills/service-de-headless-channel-configure/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "service-de-headless-channel-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-headless-channel-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-headless-channel-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-headless-channel-configure .github/skills/service-de-headless-channel-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-headless-channel-configure" agent skill from https://github.com/forcedotcom/sf-skills/tree/main/skills/service-de-headless-channel-configure into .github/skills/service-de-headless-channel-configure/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "service-de-headless-channel-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-headless-channel-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-headless-channel-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-headless-channel-configure .opencode/skills/service-de-headless-channel-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-headless-channel-configure" agent skill from https://github.com/forcedotcom/sf-skills/tree/main/skills/service-de-headless-channel-configure into .opencode/skills/service-de-headless-channel-configure/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "service-de-headless-channel-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-headless-channel-configureTop-level orchestrator: given a messaging channel type and its inputs, produces an activated Enhanced MessagingChannel in the target org — without the Meta/LINE/Apple setup popups.
Service De Headless Channel Configure is an agent skill from forcedotcom/sf-skills. Top-level orchestrator: given a messaging channel type and its inputs, produces an activated Enhanced MessagingChannel in the target org — without the Meta/LINE/Apple setup popups. Prompts for {MESSAGETYPE} if not supplied, then sequences insert → route → consent → activate via the type-agnostic dispatcher (service-de-channel-create) plus the shared routing/consent/activation leaves. Resumes from partial state on re-run. Use to set up an Enhanced channel (WhatsApp, Facebook, LINE, Apple, SMS) end-to-end…
Its SKILL.md is about 5.3k tokens, which your agent loads only when the skill is triggered. The skill folder holds 7 other files, including reference files (for example `references/gotchas.md`, `references/inputs.md` and `references/output-envelopes.md`).
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.
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.
Shell commands in SKILL.md call:
sfFrom 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 these keys or tokens, usually read from environment variables:
PLATFORM_KEYFrom names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Service De Headless Channel Configure loads about 5.3k tokens when it runs, and up to ~11k if it reads all its reference files. Until then it costs about 200 tokens; SKILL.md has 2,324 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). 2,324 words, ~5,274 tokens.
.claude/skills/service-de-headless-channel-configure/SKILL.md (or your agent's skills folder). This skill also uses 6 other files; get the full folder from GitHub.Takes a channel type (WhatsApp | Line | AppleBusinessChat | Facebook | Text) plus its type-specific inputs and drives it to an activated MessagingChannel. It first gates on the Enhanced Messaging Terms and Conditions, then runs four steps:
service-de-channel-create, which handles the per-type third-party prereq internally (e.g. WhatsApp's service-de-waba-integrate runs inside service-de-channel-create). (skill: service-de-channel-create)SessionHandlerId to an Omni-Channel Queue (pick existing or create new). Message-type-agnostic. (skill: service-de-channel-routing-configure)ConsentType + matching MsgChannelLanguageKeyword record. The Connect insert auto-seeds a default ConsentType=ImplicitOptIn + opt-out keyword, so on a fresh channel this step is frequently a no-op — or an upgrade if the caller wants ExplicitOptIn/DoubleOptIn. Activation's readiness check requires both routing AND consent, so this runs before activation. (skill: service-de-channel-settings-configure)MessagingChannelUsage.DeploymentStatus to Provisioning via REST; the server-side save-hook drives the full observer chain synchronously and returns 204 once the MCU reaches Active and MessagingChannel.IsActive=true. Message-type-agnostic. (skill: service-de-channel-activate)Resume-by-default. Each step is idempotent — if you re-run after a failure, the orchestrator detects existing state and skips steps that already succeeded.
Prompt mid-flow. If {MESSAGE_TYPE} isn't in the initial request, the orchestrator asks upfront. Routing choices (pick queue / create new) are prompted when step 2 runs, not upfront — keeps leaf skills self-contained.
| Reference file | Load when |
|---|---|
references/inputs.md | You need the full input field list — MESSAGE_TYPE/ORG_ALIAS plus per-type fields for WhatsApp, LINE, AppleBusinessChat, Facebook, Text (SMS). |
references/terms-and-conditions.md | Rendering the Stage 0.5 disclaimer and certification prompt — verbatim text and per-type label/third-party mappings. |
references/output-envelopes.md | Wiring error handling or parsing the canonical success/failure/terms-declined JSON envelope shapes. |
references/partial-success.md | The orchestrator fails mid-way and you need to render the partial-success/resume report. |
references/gotchas.md | Debugging unexpected behavior — duplicate-key errors, resume/idempotency questions, preflight SOQL shape, unattended/CI usage. |
references/worked-examples.md | You need a reference trace (fresh WhatsApp run, resume after failure, Apple dispatch, unsupported-type rejection) for exact envelope shapes. |
This orchestrator MUST run all stages (0-5) in a SINGLE response without stopping between stages.
When you invoke a leaf skill (service-de-channel-create, service-de-channel-routing-configure, service-de-channel-settings-configure, service-de-channel-activate) and it returns via function_results:
Why this matters: The user invoked THIS orchestrator skill to get an end-to-end activated channel. They did NOT invoke the individual leaf skills. Your job is to run the entire pipeline autonomously and report the final result. Stopping mid-flow breaks the orchestrator pattern and forces the user to manually resume each stage.
Exception: Only stop mid-flow if a leaf skill returns ok: false with a terminal error (not a recoverable prompt), or if the user declines the Stage 0.5 Terms and Conditions gate (emit terms-not-accepted and halt). Then report the failure immediately with context about which stage failed and what state was reached.
Stage 0.5 is a required blocking prompt. The Terms and Conditions gate is the one prompt that must be answered affirmatively before any org work. It is not optional and must not be auto-accepted. A no/decline ends the run per the exception above; a yes continues to Stage 1 in the same response.
Leaf skill prompts: Some leaf skills (like service-de-waba-integrate or service-de-channel-routing-configure) may prompt the user for input mid-execution. That's fine — answer those prompts as they come up, but then CONTINUE to the next stage immediately after the prompt is answered. Don't stop just because a prompt was involved.
service-de-channel-create, service-de-channel-routing-configure, service-de-channel-activate). This orchestrator is for the full automated path from nothing → activated channel.WhatsApp / Line / AppleBusinessChat / Facebook / Text. The dispatcher will return unsupported-type. WeChat / MsCopilot / Alexa would need their own leaves + a dispatcher update.provisioning-error.){MESSAGE_TYPE} (prompted if omitted) and {ORG_ALIAS} (optional), plus type-specific fields for WhatsApp, LINE, AppleBusinessChat, Facebook, and Text (SMS) forwarded to the dispatcher. Load references/inputs.md and follow it for the full field list and the omitted-type prompt text.
Three top-level outcomes: success, step-annotated failure, and terms-declined. Load references/output-envelopes.md and follow it for the exact JSON shapes.
{MESSAGE_TYPE} and type-specific keyIf {MESSAGE_TYPE} is omitted, prompt the user (see "Inputs" above). Refuse to proceed without one — there's no sensible default.
Once known, determine the preflight key — the field we'll filter the MessagingChannel SOQL on to detect existing state. It's always MessagingPlatformKey, but what that value is varies by type:
{MESSAGE_TYPE} | Preflight key value {PLATFORM_KEY} | Notes |
|---|---|---|
WhatsApp | {PHONE_NUMBER_ID} | Required upfront |
Line | {LINE_CHANNEL_ID} | Required upfront |
AppleBusinessChat | {APPLE_BC_ID} | Required upfront |
Facebook | {PAGE_ID} | Optional - OAuth → fetch pages → prompt if not provided |
Text | {SMS_NUMBER} | Required upfront (the phone number / short code itself) |
Facebook is unique: If {PAGE_ID} is not provided, the orchestrator cannot run its own Stage 1 preflight. Instead, skip Stage 1 and let service-de-channel-create handle the full OAuth → page selection → preflight → creation flow. The insertion skill has its own Stage 1 preflight that runs after page selection.
For non-Facebook types, validate that the caller provided the required type-specific inputs for {MESSAGE_TYPE} (see Inputs above). If missing, prompt or halt — don't call the dispatcher, it will re-validate and return missing-input, wasting a round trip.
Run this before any org query or channel work. The in-org "Add a Channel" wizard requires the admin to accept the Enhanced Messaging Terms and Conditions before it will let them proceed to channel setup. The headless flow must enforce the same gate — do not skip it, do not accept on the user's behalf. This runs once per orchestrator invocation, after {MESSAGE_TYPE} is known (the disclaimer names the channel) and before Stage 1.
Render the disclaimer and certification prompt from references/terms-and-conditions.md (verbatim, substituting the channel label) — load it and follow it for the exact wording and per-type label/third-party mappings.
Gate behavior:
{TC_ACCEPTED} = true and continue to Stage 1.{"ok": false, "kind": "terms-not-accepted",
"hint": "user did not accept the Enhanced Messaging Terms and Conditions — channel setup cannot proceed. Re-run when ready to accept."}Skip this stage entirely if MESSAGE_TYPE=Facebook and {PAGE_ID} was not provided. The Facebook insertion skill needs to run OAuth first before we know which PAGE_ID to check for. Let the insertion skill handle its own preflight in Stage 1 after page selection.
For all other cases, query the org to see how far a prior run got. This enables skip-ahead on resume. Two queries, not a subquery — the (SELECT ... FROM MessagingChannelUsages) subquery fails on some orgs where the child relationship is unnameable. Use FK-keyed second query instead (see gotcha #9).
sf data query --target-org '{ORG_ALIAS}' \
--query "SELECT Id, DeveloperName, MessageType, IsActive, SessionHandlerId, FallbackQueueId FROM MessagingChannel WHERE MessagingPlatformKey = '{PLATFORM_KEY}' AND MessageType = '{MESSAGE_TYPE}'" \
--json > /tmp/hcs-preflight.jsonIf the channel query returns a row, fire a second query to resolve its MCU:
sf data query --target-org '{ORG_ALIAS}' \
--query "SELECT Id, DeploymentStatus FROM MessagingChannelUsage WHERE MessagingChannelId = '{CHANNEL_ID}'" \
--json > /tmp/hcs-preflight-mcu.jsonParse the combined result to figure out {CURRENT_STATE}:
| Preflight result | CURRENT_STATE | First step to run |
|---|---|---|
| No records | fresh | Step 1 (insert) |
Record exists, IsActive=false, SessionHandlerId=null and FallbackQueueId=null | inserted-no-routing | Step 2 (configure routing) |
Record exists, IsActive=false, routing set | routed-not-active | Step 3 (configure consent), then Step 4 (activate) |
Record exists, IsActive=true | already-active | Emit no-op success envelope; return. |
Record the existing {CHANNEL_ID} and {MCU_ID} if present — downstream steps need them.
Initialize {STEPS_RUN} = [], {STEPS_SKIPPED} = [], {T0} = Date.now().
Skip this stage if CURRENT_STATE ∈ {inserted-no-routing, routed-not-active, already-active} — the channel already exists. Append "insert" to STEPS_SKIPPED in that case.
Otherwise invoke service-de-channel-create with:
{MESSAGE_TYPE} = (from Stage 0){ORG_ALIAS}The insertion skill handles per-type prereqs internally (e.g., for WhatsApp, service-de-channel-create invokes service-de-waba-integrate as its Stage 2). This orchestrator doesn't need to know about WABA linking, LINE token verification, or Apple registration — service-de-channel-create owns the prereq semantics for whichever type it's running.
Handle the envelope:
| Leaf envelope | Orchestrator action |
|---|---|
{ok: true, channelId, mcuId, ...} | Record {CHANNEL_ID} and {MCU_ID}. Append "insert" to STEPS_RUN. Continue. |
{ok: false, kind: "partnership-blocked" | "user-declined" | "apple-registration-pending" | "line-prereq-missing"} | These come from the per-type prereq stage. Pass through as failedStep: "insert", failedStepIndex: 1. Return. |
{ok: false, kind: "missing-input" | "unsupported-type"} | Should have been caught in Stage 0 — emit failure with failedStep: "insert" and a note that the caller's inputs were incomplete. |
{ok: false, kind: <anything else>} | Emit failure envelope with failedStep: "insert", failedStepIndex: 1. Return. |
At this point we have {CHANNEL_ID} and {MCU_ID} regardless of whether step 1 ran or was skipped.
→ Continue immediately to Stage 3 in this same response. DO NOT STOP.
Skip this stage if CURRENT_STATE === "routed-not-active" — routing is already set. Append "route" to STEPS_SKIPPED.
Otherwise invoke service-de-channel-routing-configure:
{CHANNEL_ID} = recorded above{ORG_ALIAS}This is the step that prompts the user for queue choice (pick existing / create new / escape hatch). Don't try to pre-empt the prompts — forward the user's answers as-is.
Handle the envelope:
| Leaf envelope | Orchestrator action |
|---|---|
{ok: true, sessionHandlerId, queueName, ...} (including noop: true) | Record {SESSION_HANDLER_ID} and {QUEUE_NAME}. Append "route" to STEPS_RUN. Continue. |
{ok: false, kind: "unsupported-routing-type", ...} | User chose flow/user/asa/aea. Emit partial-success with failedStep: "route" and a resume hint pointing at the UI. Return. |
{ok: false, kind: "metadata-deploy-failed" | "patch-failed" | "verify-failed"} | Emit failure envelope with failedStep: "route". Return. |
→ Continue immediately to Stage 3.5 in this same response. DO NOT STOP.
Activation's readiness check requires consent AND routing — a fully-routed channel still fails to activate if consent isn't configured. Invoke service-de-channel-settings-configure:
{CHANNEL_ID} = recorded above{CONSENT_TYPE}, {LANGUAGE}, and the keyword/prompt values — forward whatever the user supplied; omit what they didn't{ORG_ALIAS}This stage ensures consent is activation-ready — it doesn't always write. The Connect insert auto-seeds ConsentType=ImplicitOptIn plus a default opt-out MsgChannelLanguageKeyword, which already satisfies the readiness check. So the leaf's Stage 1 will frequently find the channel already ready and return noop: true — the expected outcome on a fresh ImplicitOptIn channel, not a bug. It performs a real write only to upgrade (ExplicitOptIn/DoubleOptIn) or override the seeded keywords/prompts. When the user pre-supplied inputs asking for an upgrade, expect a write and let the leaf prompt for missing values — don't suppress those prompts.
Handle the envelope:
| Leaf envelope | Orchestrator action |
|---|---|
{ok: true, ...} (including noop: true) | Append "consent" to STEPS_RUN (or STEPS_SKIPPED if noop). Continue. |
{ok: false, kind: "not-enhanced"} | Shouldn't happen — these skills only create Enhanced channels. Emit failure with failedStep: "consent". Return. |
{ok: false, kind: "missing-consent-input", hint} | The user didn't supply a required keyword/prompt for the chosen ConsentType. Emit failure with failedStep: "consent" and pass through the hint. Return. |
{ok: false, ...} (any other kind — channel-patch-failed, keyword-record-failed, verify-failed, or an unrecognized envelope) | Emit failure with failedStep: "consent" and pass through the leaf's kind and message verbatim. Return. |
→ Continue immediately to Stage 4 in this same response. DO NOT STOP.
Always run (unless CURRENT_STATE === "already-active", in which case Stage 1 returned early).
Invoke service-de-channel-activate:
{CHANNEL_ID} = recorded above{ORG_ALIAS}No timeout knobs — activation is a single synchronous PATCH. The leaf does a defensive poll if the server ever returns mid-transition, but the expected path is one round-trip.
Handle the envelope:
| Leaf envelope | Orchestrator action |
|---|---|
{ok: true, isActive: true, ...} (including noop: true) | Record results. Append "activate" to STEPS_RUN. Continue to Stage 5. |
{ok: false, kind: "no-routing"} | Unusual (we just set it) — probably a race or permission issue. Emit failure with a hint about the permissions check. Return. |
{ok: false, kind: "no-mcu" | "channel-missing"} | Shouldn't happen after successful insert. Emit failure with the leaf's envelope. Return. |
{ok: false, kind: "readiness-failed", errorMessage} | validateChannelReadinessOnProvisioning rejected the PATCH — missing consent (STOP/HELP keyword record). Stage 3.5 should have caught this; if it re-appears, re-run service-de-channel-settings-configure for the channel. Emit failure and pass through the resume hint. Return. |
{ok: false, kind: "provisioning-error", errorReason, errorDetails} | Third-party side rejected (Meta /register failed, etc.). MCU is now in Error. Emit failure and pass through errorReason/errorDetails. Return. |
{ok: false, kind: "auth" | "transport"} | REST call failed at the HTTP layer (401 from sf auth, 5xx from the instance). Pass through. Return. |
Build the success envelope:
{
"ok": true,
"messageType": "{MESSAGE_TYPE}",
"channelId": "{CHANNEL_ID}",
"mcuId": "{MCU_ID}",
"channelName": "{CHANNEL_NAME or inferred}",
"sessionHandlerId": "{SESSION_HANDLER_ID}",
"queueName": "{QUEUE_NAME}",
"isActive": true,
"stepsRun": [...],
"stepsSkipped": [...],
"totalDurationMs": Date.now() - T0
}Render to the user as:
Success — {MESSAGE_TYPE} channel '{CHANNEL_NAME}' is live on {ORG_ALIAS}.
Channel ID: {CHANNEL_ID}
Routed to: {queueName} ({SESSION_HANDLER_ID})
Steps: ran {STEPS_RUN.join(", ")}{, skipped " + STEPS_SKIPPED.join(", ") if any}
Total time: {formatted from durationMs}If any step was skipped due to resume, the report should make that visible.
If the orchestrator fails mid-way, the envelope always includes stateSoFar describing what landed. stateSoFar must always carry both stepsRun and stepsSkipped (each an array, empty if nothing landed/skipped yet) alongside the fields that landed — the partial-success renderer reads both. When rendering a failure, load references/partial-success.md and follow it — it has the exact template for showing which steps already landed and how to retry.
For reference traces (fresh WhatsApp run, resume after routing failure, Apple dispatch, unsupported-type rejection), see references/worked-examples.md.
Nine known gotchas covering prereq ownership, MessagingPlatformKey uniqueness, resume semantics, CSOT-only support, error-classification boundaries, prompt placement, platform-key mapping, wall-clock duration, and the two-query preflight workaround. When debugging unexpected behavior, load references/gotchas.md and follow it.
© 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 (references) in skills/service-de-headless-channel-configure of forcedotcom/sf-skills.
Open the folder on GitHubat commit 4bbae5c
Service De Headless Channel 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 Headless Channel Configure this skillforcedotcom/sf-skills | 1.1k | — | ~5.3k | Automated safety check: Pass | Apache-2.0 | |
| Web Asset Generatoralonw0/web-asset-generator | 514 | 1 repos | ~6.6k | Automated safety check: Pass | MIT | |
| Deskcomm Contribuirmelgarafael/DeskcommCRM | 4.5k | — | ~3.6k | Automated safety check: Notes | MIT | |
| Send User MessageTinyAGI/tinyagi | 3.6k | — | ~829 | Automated safety check: Pass | MIT | |
| Wacliopenclaw/wacli | 2.8k | — | ~811 | Automated safety check: Pass | MIT | |
| Deskcomm Extensaomelgarafael/DeskcommCRM | 4.5k | — | ~2.7k | Automated safety check: Pass | MIT |
alonw0/web-asset-generator
Generate web assets including favicons, app icons (PWA), and social media meta images (Open Graph) for Facebook, Twitter, WhatsApp, and LinkedIn.
melgarafael/DeskcommCRM
Guia de contribuição ao DeskcommCRM para quem vai mexer no código e abrir um pull request, sobretudo de um fork.
TinyAGI/tinyagi
Send a proactive message to a paired user via their channel (Discord, Telegram, or WhatsApp).
openclaw/wacli
wacli: WhatsApp linked devices, stores, sync/auth/send, repo/release work.
melgarafael/DeskcommCRM
Guia para criar uma extensão do DeskcommCRM — o pacote declarativo — em vez de abrir um PR no núcleo.
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.
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
Top-level orchestrator: given a messaging channel type and its inputs, produces an activated Enhanced MessagingChannel in the target org — without the Meta/LINE/Apple setup popups. Service De Headless Channel Configure is an agent skill from forcedotcom/sf-skills. Top-level orchestrator: given a messaging channel type and its inputs, produces an activated Enhanced MessagingChannel in the target org — without the Meta/LINE/Apple setup popups.
Service De Headless Channel Configure fits situations like: set up an Enhanced channel (WhatsApp; SMS) end-to-end; bypassing in-org setup popups; A single stage of an already-inserted channel — use the matching leaf skill (service-de-channel-activate.
Run `npx skills add forcedotcom/sf-skills --skill service-de-headless-channel-configure -a claude-code`. Or copy the skill folder (skills/service-de-headless-channel-configure in forcedotcom/sf-skills) into .claude/skills/service-de-headless-channel-configure in your project. Claude Code loads it when a task matches its description.
Run `npx skills add forcedotcom/sf-skills --skill service-de-headless-channel-configure -a codex`. Or copy the skill folder (skills/service-de-headless-channel-configure in forcedotcom/sf-skills) into .agents/skills/service-de-headless-channel-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-headless-channel-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-headless-channel-configure, .gemini/skills/service-de-headless-channel-configure, .github/skills/service-de-headless-channel-configure and .opencode/skills/service-de-headless-channel-configure in your project.
Going by SKILL.md and its folder, Service De Headless Channel Configure needs the command-line tools its instructions call (sf) and credentials named PLATFORM_KEY. Our summary lists: A credential in PLATFORM_KEY.
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. Review the folder before installing.
Service De Headless Channel 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.3k tokens (SKILL.md is roughly 21k 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 5.4k tokens, read only when the agent opens those files.
Skills that share tags, products or a category with Service De Headless Channel Configure: Web Asset Generator (alonw0/web-asset-generator, 514 stars), Deskcomm Contribuir (melgarafael/DeskcommCRM, 4.5k stars), Send User Message (TinyAGI/tinyagi, 3.6k stars) and Wacli (openclaw/wacli, 2.8k 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.