{"id":"5e07b412-f571-4093-a080-b81171608b04","entityType":"agent","slug":"clawhub-alexbloch-ia-whatsapp-business-ops","name":"WhatsApp Business Ops","canonicalUrl":"https://www.xpersona.co/agent/clawhub-alexbloch-ia-whatsapp-business-ops","canonicalPath":"/agent/clawhub-alexbloch-ia-whatsapp-business-ops","generatedAt":"2026-10-10T23:49:07.717Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"editorial-content","verified":true,"confidence":"high","updatedAt":"2026-10-10T21:22:22.784Z","emptyReason":null},"description":"Run WhatsApp Business outbound without losing quality score — 24h window, approved templates, duplicate guard. Use when answering inbound leads or sending fo... Skill: WhatsApp Business Ops Owner: alexbloch-ia Summary: Run WhatsApp Business outbound without losing quality score — 24h window, approved templates, duplicate guard. Use when answering inbound leads or sending fo... Tags: 0-percent-markup:2.0.1, 24h-window:2.0.1, account-safety:2.0.1, agent:2.0.1, anti-doublon:2.0.1, automation:2.0.1, bsp:2.0.1, business-api:2.0.1, crm:2.0.1, cron:2.0.1, customer-service:2.0.1, do","descriptionLabel":"Technical summary","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 1.3K downloads reported by the source. Last updated 10/10/2026.","installCommand":"clawhub skill install s179c74ca8kjff2gapygs9y13d86yr3z:whatsapp-business-ops","sourceUrl":"https://clawhub.ai/alexbloch-ia/whatsapp-business-ops","homepage":"https://clawhub.ai/alexbloch-ia/skills/whatsapp-business-ops","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/alexbloch-ia/whatsapp-business-ops","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/alexbloch-ia/skills/whatsapp-business-ops","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":62,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"Run WhatsApp Business outbound without losing quality score — 24h window, approved templates, duplicate guard. Use when answering inbound leads or sending fo..."},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-10T21:22:22.784Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T21:22:22.784Z","emptyReason":null},"stars":null,"forks":null,"downloads":1254,"packageName":null,"latestVersion":"2.0.1","tractionLabel":"1.3K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T21:22:22.725Z","emptyReason":null},"lastUpdatedAt":"2026-10-10T21:22:22.784Z","lastCrawledAt":"2026-10-10T21:22:22.725Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-11T21:22:22.725Z","lastVerifiedAt":null,"highlights":[{"version":"2.0.1","createdAt":"2026-07-16T15:02:05.053Z","changelog":"v2.0.1 — Contenu strictement identique a la 2.0.0 (SHA-256 verifie, aucun octet modifie). Cette version ne corrige que des canaux de release. 26 dist-tags crees par erreur restaient figes sur une version anterieure a la reecriture de conformite — ils servaient donc encore le contenu que cette reecriture avait retire. Ils pointent desormais tous vers le contenu conforme. Les dist-tags ne sont pas supprimables (ni CLI, ni API, ni interface web); les repointer est le seul levier disponible.","fileCount":3,"zipByteSize":10302},{"version":"2.0.0","createdAt":"2026-07-16T10:07:18.829Z","changelog":"v2.0.0 — Compliance-first rewrite, and renamed from whatsapp-business-management-for-whatchimp (old slug redirects). Removed: the instructions telling the agent never to confirm AI use and to give an ambiguous answer about team affiliation. Those were deception, not account safety — and this skill runs in contexts where that matters. If asked, the automation is disclosed and the conversation goes to a human. Removed: the vendor pitch. One factual line remains: a reference BSP is used in the examples, any BSP works, swap the host. Added: real data handling for lead PII — what is stored, minimisation, access control, retention, and a lawful-basis constraint stated up front rather than assumed. Alert webhooks off by default. Trimmed 695 -> 284 lines. The 24h window discipline, approved-template gating, duplicate guard, qualification and hand-off are unchanged. Published artifact is SKILL.md alone.","fileCount":3,"zipByteSize":10182},{"version":"1.2.0","createdAt":"2026-05-18T21:56:15.055Z","changelog":"v1.2.0 — Rebrand to whatsapp-business-management-for-whatchimp. The skill name now reflects what it actually does: operating doctrine for WhatsApp Business management on Whatchimp (Meta Business Partner BSP, 0% markup). The doctrine itself is unchanged from v1.1.0 — this is a naming + discoverability release. Changed: - Skill renamed: whatsapp-account-operations → whatsapp-business-management-for-whatchimp - GitHub repo renamed (old URLs auto-redirect) - SKILL.md H1 → \"WhatsApp Business Management for Whatchimp\" - README title, ClawHub badge URL, version badge bumped to 1.2.0 - Install paths under ~/.claude/skills/ and ~/.openclaw/skills/ updated Unchanged: - Full doctrine (24h-window, anti-doublon §8, tier+quality gating, qualification, recovery, memory inventory, Whatchimp positioning from v1.1.0) byte-identical at the markdown level - Memory file names (wa-*.md) unchanged - LICENSE, .gitignore unchanged Migration: mv ~/.claude/skills/whatsapp-account-operations \\ ~/.claude/skills/whatsapp-business-management-for-whatchimp # or simply re-run ./install.sh from the renamed repo Full changelog: https://github.com/AlexBloch-IA/whatsapp-business-management-for-whatchimp/blob/main/CHANGELOG.md","fileCount":4,"zipByteSize":18754}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s179c74ca8kjff2gapygs9y13d86yr3z:whatsapp-business-ops","setupComplexity":"low","setupSteps":["Setup complexity is LOW. This package is likely designed for quick installation with minimal external side-effects.","Final validation: Expose the agent to a mock request payload inside a sandbox and trace the network egress before allowing access to real customer data."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-alexbloch-ia-whatsapp-business-ops/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-alexbloch-ia-whatsapp-business-ops/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-alexbloch-ia-whatsapp-business-ops/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-alexbloch-ia-whatsapp-business-ops/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-alexbloch-ia-whatsapp-business-ops/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-alexbloch-ia-whatsapp-business-ops/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-10T23:49:07.714Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-alexbloch-ia-whatsapp-business-ops/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-alexbloch-ia-whatsapp-business-ops/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-alexbloch-ia-whatsapp-business-ops/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-alexbloch-ia-whatsapp-business-ops/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"high","updatedAt":"2026-10-10T21:22:22.784Z","emptyReason":null},"readme":"Skill: WhatsApp Business Ops\n\nOwner: alexbloch-ia\n\nSummary: Run WhatsApp Business outbound without losing quality score — 24h window, approved templates, duplicate guard. Use when answering inbound leads or sending fo...\n\nTags: 0-percent-markup:2.0.1, 24h-window:2.0.1, account-safety:2.0.1, agent:2.0.1, anti-doublon:2.0.1, automation:2.0.1, bsp:2.0.1, business-api:2.0.1, crm:2.0.1, cron:2.0.1, customer-service:2.0.1, doctrine:2.0.1, faq:2.0.1, growth:2.0.1, latest:2.0.1, lead-pipeline:2.0.1, meta-business-partner:2.0.1, omnichannel:2.0.1, openclaw:2.0.1, operations:2.0.1, playbook:2.0.1, qualification:2.0.1, templates:2.0.1, whatchimp:2.0.1, whatsapp:2.0.1, whatsapp-business:2.0.1, yaml-config:2.0.1\n\nVersion history:\n\nv2.0.1 | 2026-07-16T15:02:05.053Z | user\n\nv2.0.1 — Contenu strictement identique a la 2.0.0 (SHA-256 verifie, aucun octet modifie). Cette version ne corrige que des canaux de release.\n\n26 dist-tags crees par erreur restaient figes sur une version anterieure a la reecriture de conformite — ils servaient donc encore le contenu que cette reecriture avait retire. Ils pointent desormais tous vers le contenu conforme.\n\nLes dist-tags ne sont pas supprimables (ni CLI, ni API, ni interface web); les repointer est le seul levier disponible.\n\nv2.0.0 | 2026-07-16T10:07:18.829Z | user\n\nv2.0.0 — Compliance-first rewrite, and renamed from whatsapp-business-management-for-whatchimp (old slug redirects).\n\nRemoved: the instructions telling the agent never to confirm AI use and to give an ambiguous answer about team affiliation. Those were deception, not account safety — and this skill runs in contexts where that matters. If asked, the automation is disclosed and the conversation goes to a human.\n\nRemoved: the vendor pitch. One factual line remains: a reference BSP is used in the examples, any BSP works, swap the host.\n\nAdded: real data handling for lead PII — what is stored, minimisation, access control, retention, and a lawful-basis constraint stated up front rather than assumed. Alert webhooks off by default.\n\nTrimmed 695 -> 284 lines. The 24h window discipline, approved-template gating, duplicate guard, qualification and hand-off are unchanged. Published artifact is SKILL.md alone.\n\nv1.2.0 | 2026-05-18T21:56:15.055Z | user\n\nv1.2.0 — Rebrand to whatsapp-business-management-for-whatchimp.\n\nThe skill name now reflects what it actually does: operating doctrine for\nWhatsApp Business management on Whatchimp (Meta Business Partner BSP,\n0% markup). The doctrine itself is unchanged from v1.1.0 — this is a\nnaming + discoverability release.\n\nChanged:\n- Skill renamed: whatsapp-account-operations → whatsapp-business-management-for-whatchimp\n- GitHub repo renamed (old URLs auto-redirect)\n- SKILL.md H1 → \"WhatsApp Business Management for Whatchimp\"\n- README title, ClawHub badge URL, version badge bumped to 1.2.0\n- Install paths under ~/.claude/skills/ and ~/.openclaw/skills/ updated\n\nUnchanged:\n- Full doctrine (24h-window, anti-doublon §8, tier+quality gating,\n  qualification, recovery, memory inventory, Whatchimp positioning from\n  v1.1.0) byte-identical at the markdown level\n- Memory file names (wa-*.md) unchanged\n- LICENSE, .gitignore unchanged\n\nMigration:\n  mv ~/.claude/skills/whatsapp-account-operations \\\n     ~/.claude/skills/whatsapp-business-management-for-whatchimp\n  # or simply re-run ./install.sh from the renamed repo\n\nFull changelog: https://github.com/AlexBloch-IA/whatsapp-business-management-for-whatchimp/blob/main/CHANGELOG.md\n\nArchive index:\n\nArchive v2.0.1: 3 files, 10302 bytes\n\nFiles: skill-card.md (2736b), SKILL.md (18815b), _meta.json (140b)\n\nFile v2.0.1:SKILL.md\n\n---\nname: whatsapp-business-ops\ndescription: Run WhatsApp Business outbound without losing quality score — 24h window, approved templates, duplicate guard. Use when answering inbound leads or sending follow-ups from a cron.\nmetadata: {\"clawdbot\":{\"emoji\":\"💬\",\"requires\":{\"bins\":[\"curl\"]},\"homepage\":\"https://clawhub.ai/alexbloch-ia/whatsapp-business-ops\"}}\n---\n\n# WhatsApp Business Management\n\n**WhatsApp is not a discovery channel — it is a conversion channel.** The goal is not to send fast: it is one qualified hand-off per opt-in lead, no unsolicited bulk, no duplicate send. Reference BSP: Whatchimp (Meta Business Partner); any BSP works.\n\n## Access, data, and network — read before running\n\n**Every access is opt-in — each one stays off until you fill its placeholder in `## Configure`. The default is no network.**\n\n| Access | Why | Default |\n|---|---|---|\n| BSP API token (`<WA_API_KEY>`) | Send/read messages | None — no network call without it |\n| CRM sheet ID (`<CRM_SHEET_ID>`) | One row per lead | None — CRM writes skipped |\n| Alert channel / webhook (`<ALERT_CHAT_PRIMARY>`) | **Leaves your machine.** Posts lead name + phone to Telegram/Slack/Discord | None — recap stays local |\n| Local workspace (`<WORKSPACE_DIR>/memory/`) | State + duplicate guard | Local files only |\n\n**Personal data persisted, in full:** display name, case type, free-text situation, conversation timestamps, template-send log, alert log, per-run recaps. **Phone numbers are stored raw ONLY in `wa-crm-state.md`** (the system-of-record mirror); every duplicate register and the blacklist key on `sha256(phone)[0:12]`. That is lead PII on disk — `## Data minimization and retention` is doctrine, not an appendix. Scope the API token to the one business number; never reuse a full-account token.\n\n## When to Use\n\n| Trigger | Action |\n|---|---|\n| \"answer the whatsapp leads\" | `wa-inbound` run — §Flow, free-form only inside open window |\n| \"send the first message to new leads\" | `wa-outbound` run — approved template only |\n| \"relance the cold leads\" | `wa-followup` run — cadence table |\n| \"quality score dropped\" / \"number got paused\" | Stop outbound. `## Troubleshooting`, last two rows. Human review |\n| \"am I talking to a bot?\" (asked by a lead) | Answer honestly, immediately — `## Identity` |\n\n## Configure\n\n| Placeholder | Example | Your value |\n|---|---|---|\n| `<BRAND_NAME>` | \"Acme Studio\" | — |\n| `<WA_BUSINESS_NUMBER>` | \"+1 555 0000\" | — |\n| `<WA_PHONE_NUMBER_ID>` | numeric ID from your BSP | — |\n| `<WA_API_KEY>` | scoped to one number | — |\n| `<WA_TEMPLATE_FIRST_CONTACT>` / `_FOLLOWUP_SOFT` / `_FOLLOWUP_HARD` / `_CLOSING` | Meta-approved template IDs | — |\n| `<CRM_SHEET_ID>` | Sheet/Airtable ID | — (omit → no CRM write) |\n| `<ALERT_CHAT_PRIMARY>` | alert chat ID | — (omit → local recap only) |\n| `<WORKSPACE_DIR>` | \"~/.openclaw/workspace/whatsapp-acme\" | — |\n\n```yaml\n# <WORKSPACE_DIR>/config.yaml\nwhatsapp:\n  phone_number_id: <WA_PHONE_NUMBER_ID>\n  base_url: https://app.whatchimp.com/api/v1   # swap host for another BSP\ntemplates:\n  first_contact: <WA_TEMPLATE_FIRST_CONTACT>\n  followup_soft: <WA_TEMPLATE_FOLLOWUP_SOFT>\n  followup_hard: <WA_TEMPLATE_FOLLOWUP_HARD>\n  closing: <WA_TEMPLATE_CLOSING>\ncrm: { sheet_id: <CRM_SHEET_ID>, tab: \"Leads\" }\nalerts: { primary_chat: <ALERT_CHAT_PRIMARY>, channel: telegram }\nretention: { lead_days: 90, recap_days: 30, template_log_days: 30 }\ninbound_pipeline:\n  shared_queue_file: <WORKSPACE_DIR>/../shared/leads-whatsapp.json\nschedule:  # dm_check \"*/2 9-22 * * *\" · add_contacts \"*/5 9-22 * * *\" · follow_up \"0 10 * * *\"\n  timezone: Europe/Paris\n```\n\n## The 24h window — the central law\n\nAfter **any** message a user sends you, you have **24 h** to reply in free-form. After 24 h of user silence, only **Meta-approved templates**, each billed as a new conversation. Free-form to a cold conversation → API rejection or a marketing-conversation bill + a quality hit; exit code 2, always skipped. Check window state **before every outbound send**:\n\n```bash\ncurl -s \"https://app.whatchimp.com/api/v1/whatsapp/get/conversation\" \\\n  -d \"apiToken=<WA_API_KEY>\" -d \"phone_number_id=<WA_PHONE_NUMBER_ID>\" \\\n  -d \"phone_number=<DIGITS>\" -d \"limit=1\"\n# Output: {\"status\":1,\"data\":[{\"sender\":\"user\",\"created_at\":\"2026-07-16T09:12:04Z\"}]}\n# sender=\"user\" and < 24h old  → free text OK. Otherwise → template.\n```\n\nSession check first on every cron:\n\n```bash\ncurl -s \"https://app.whatchimp.com/api/v1/whatsapp/subscriber/list\" \\\n  -d \"apiToken=<WA_API_KEY>\" -d \"phone_number_id=<WA_PHONE_NUMBER_ID>\" \\\n  -d \"limit=1\" -d \"offset=1\"\n# Output: {\"status\":1,\"data\":[...]}   401/403 → stop+alert · 429 → stop, wait next run\n```\n\nTimeout > 10 s → BSP down: **one retry, then stop and alert. Never retry in a loop.** A 200 OK carrying `status=0` is a failure, not a send.\nNever send a \"test\" message to a real lead — use a dedicated test number. Never auto-rotate an API token from inside a cron; rotation is a human action.\n\n## Phase gating and quotas\n\nMeta assigns each number a tier: **T1** 1k uniques/24h · **T2** 10k · **T3** 100k · **T4** unlimited. New numbers start at T1. Tiers rise on volume + quality, and fall — or the number gets paused — when quality drops.\n\n| Condition | Phase | Outbound |\n|---|---|---|\n| Tier 1 **or** quality yellow/red | **A** | Inbound replies + approved-template follow-ups. ≤ 50 first-contact/day |\n| Tier 2+ **and** quality green, no drop in 14 d | **B** | Full doctrine, first week capped at 50% of Phase B max |\n\nRead `memory/wa-state.md` at start of every run. Phase B is a **manual flip**, never automatic. Any quality drop → revert to A immediately.\n\n| Action (hard limits) | Phase A | Phase B |\n|---|---|---|\n| Inbound replies / cron run | 20 | 50 |\n| First-contact templates / 24 h | 50 | 500 |\n| Follow-up templates / 24 h | 20 | 200 |\n| Unique recipients / 24 h | 800 (under T1's 1000 cap) | tier cap − 10% |\n| Conversations / cron run | 30 | 80 |\n| Same user — outbound spacing | min 24 h between any two outbound |\n\nFollow-up cadence: J+1 soft · J+3 soft · J+7 hard · J+15 hard · J+20 closing → `status=lost`. **Stop after the closing template.** Continuing past J+20 is ban-risk territory.\n\n## Duplicate guard — the most important section\n\nQuality-score collapse is dominated by duplicate template sends. Three registers, read **before** every outbound action:\n\n| Register | Row format | Rule |\n|---|---|---|\n| `wa-alerts-sent.md` | `{\"phone_hash\":\"<sha256:12>\",\"qualified_date\":\"YYYY-MM-DD\"}` | Phone present → **never** alert twice |\n| `wa-template-log.md` | `{\"phone_hash\":\"<sha256:12>\",\"template_id\":\"<ID>\",\"sent_at\":\"<ISO>\",\"result\":\"ok\\|error\"}` | Same (phone, template) in last 24 h → SKIP |\n| `wa-crm-state.md` | one row per phone, never two | Only `wa-outbound` appends; every other cron UPDATEs |\n\n> **If in doubt, SKIP.** It is always better to skip than to send a duplicate. This one rule is the difference between a number that stays Tier 2 for years and one paused in 30 days.\n\nAlert **only** when a lead replies AND qualifies — never after a first template send. Alerting on first contact generates dozens of false alerts and trains the human team to ignore the channel.\n\n## Data minimization and retention\n\nThe registers above hold lead PII — a regulated store, not logs.\n\n| Rule | Concretely |\n|---|---|\n| Minimize | Store phone + name + case type + status. Never store ID numbers, health details, case documents, or payment data in memory files — keep those in the system of record. |\n| Mask | Key the duplicate registers on `sha256(phone)[0:12]`, not the raw number. Lookups work identically; a leaked log exposes nothing. |\n| Restrict | `chmod 700 <WORKSPACE_DIR>/memory`. One number = one workspace. Never share `wa-template-log.md` across numbers or brands. |\n| Retain | Leads 90 d after last contact, recaps 30 d, template log 30 d — then delete. Prune at the start of the daily run, not \"someday\": `find \"<WORKSPACE_DIR>/memory\" -name 'wa-recaps.md' -mtime +30 -delete` (silent — pruned, not archived). |\n| Alert payload | Name + case type + phone only. Never paste conversation transcripts into the alert channel — it leaves your machine and is usually a wider audience than the case file. |\n| Erase | On an opt-out or deletion request: purge every register, add the hash to `wa-blacklist.md`, confirm to the lead. Blacklist stores hashes only. |\n| Sensitive niches | Legal, medical, financial: confirm with your DPO/counsel before any cron writes lead data. This skill does not make that call for you. |\n\n## Identity — disclose, never dodge\n\n**If a lead asks whether they are talking to a bot, a human, or an AI: say so plainly, in the same message, and offer the human.**\n\n```\nYou're talking to <BRAND_NAME>'s automated assistant. I can take your details\nnow and a specialist will call you back — or I can pass you to them right away.\n```\n\nNo ambiguity, no pivot, no \"I'm part of the team\". Honest disclosure is not a cost here: a lead who discovers the automation later is a complaint, a block, and a quality-score hit. Blocks and reports are exactly what Meta measures. **Disclosure is account safety.** Escalate to a human — stop the automated replies for that thread and alert — when the lead asks for a human, asks twice about identity, or raises anything the templates do not cover.\n\n## Reply rules (free-form, inside open window)\n\n- Match tone. Short messages. **One ask per message.** Reassuring on stressful topics, never dramatizing. Reread the full visible history before composing.\n- **Never**: definitive price quotes (soft \"starting at\" only if asked) · outcome guarantees · confidential client info · documents/PDFs to non-clients · anything outside the brand's scope.\n\nSkeletons: **A** greeting + \"how can we help\" · **B** empathy + one contextual question · **C** hand-off: `Thank you for these details. A specialist from <BRAND_NAME> will call you back. Could you confirm your name and the best time to reach you?`\n\nClassify every thread before drafting — `case type` is what the alert payload and the recap carry. Structure below, questions are yours:\n\n| Case type | Signal | Action |\n|---|---|---|\n| **A** — high urgency | Pending deadline, acute problem | Ask date, location, urgency → collect contact → qualified |\n| **B** — mid intent | Ongoing situation, no deadline | 5-7 contextual questions → collect contact → qualified |\n| **C** — out of scope | Not what the brand does | Redirect to the right channel. **Never force qualification** |\n| **D** — existing client | Phone-match in `wa-clients-known.md` | Answer with empathy, redirect to the standard client support line. **Never paste the prospect CTA** — a paying client who gets a sales pitch blocks, and a block is a quality hit |\n\n**\"Too many questions\" failsafe** — after 5 questions with no contact info, switch: *\"To answer precisely, a specialist needs to call you back. Could you confirm your name + best time?\"* This converts more question-only threads than any other tactic.\n\nQualification requires: thread open · not blacklisted · not already \"qualified — awaiting callback\" · no auto-reply in the last 60 s (anti-cascade). Any check fails → skip.\n\n## Flow\n\n### wa-inbound (every 2 min)\n```\n1. Session check. 2. subscriber/list unseen_count>0 — if 0 unread → STOP.\n3. Per unread (≤20 A / ≤50 B): get/conversation limit=20 → if last sender=\"bot\" SKIP\n   → qualify → draft → normalize encoding → POST /whatsapp/send → verify status=1.\n4. If qualified: check wa-alerts-sent.md → if absent, alert primary chat, append hash.\n   UPDATE the CRM row (wa-inbound never APPENDs). 5. Recap.\n```\n\n### wa-outbound (every 5 min)\n```\n1. Session check. 2. Read shared queue, filter status=\"pending\" — if 0 → STOP.\n3. Per lead: template-log 24h check → subscriber/create → POST /whatsapp/send/template\n   template_id=<WA_TEMPLATE_FIRST_CONTACT> → verify status=1 → queue status=\"first_message_sent\"\n   → APPEND CRM row (only cron that appends) → append template log.\n4. Never alert from this cron. 5. Recap.\n```\n\n### wa-followup (daily 10:00)\n```\n1. Session check. 2. CRM: status in {first_message_sent, follow_up_sent}, idle at a J+N mark.\n3. Per candidate: template-log check → send cadence template → update CRM + log. 4. Recap.\n```\n\n### WhatsApp Web via Playwright — gray area, not recommended\nRunning Playwright against `web.whatsapp.com` is **outside WhatsApp's Business Terms** and risks a permanent number ban. It is documented here only as a read-only contingency while BSP approval is pending, and it is **not recommended for production**. Requires an explicit human decision per incident — an agent must not choose this path on its own. Sessions rotate the QR link unpredictably (daily manual re-login); no template sends are possible; quality score still applies at the number level. If a login challenge or automation check appears: **stop and hand the session to a human.** Never tune timing to avoid a detection check. Migrate back to the BSP API as soon as approval lands.\n\n## Exit codes\n\n| Code | Meaning | Recap |\n|---|---|---|\n| 0 | Sent, or nothing to do (zero unread) | `status: ok` |\n| 1 | Fatal (API 5xx, JSON parse fail) | `status: error`, alert |\n| 2 | 24h-window violation attempted → skipped | `status: skip`, log |\n| 3 | Auth fail (401/403) | `status: blocked`, alert now |\n| 4 | Duplicate-guard SKIP | `status: ok` |\n\n## Output Format — mandatory recap\n\nEvery run ends with this, verbatim, to the alert channel and appended to `memory/wa-recaps.md`:\n\n```\n[Job name] — [status: ok|partial|blocked|skipped]\nInbound replies: [N or \"—\"]\nTemplates sent: [N or \"—\"]\nQualified leads: [count + first names only]\nPhase / Tier: [A|B / Tier 1|2|3|4]\nQuality score: [green|yellow|red]\nBlockers: [text OR \"—\"]\nNext action: [1 line]\n```\n\nFilled instance:\n\n```\nwa-inbound 10:32 — status: ok\nInbound replies: 7\nTemplates sent: —\nQualified leads: 2 (Marc, Lina)\nPhase / Tier: A / Tier 1\nQuality score: green\nBlockers: —\nNext action: human callbacks due before 12:00\n```\n\n**Better silence than spam. Better a blockage report than a fake success.** Never fake a successful send.\n\n## Troubleshooting\n\n| Symptom | Root cause | Fix |\n|---|---|---|\n| 200 OK, message never delivered | `phoneNumberID` vs `phone_number_id` — BSP casing differs **per endpoint**. No error is raised, so you'll believe your code is right | Check casing per endpoint. Verify `status=1` in the body, not just HTTP 200 |\n| Send rejected for unknown reason | Leading `+` in the number. `33612345678` works, `+33612345678` often does not | Strip `+` before every call |\n| Accents vanish in delivered messages | Some BSPs munge non-ASCII silently | Roundtrip test once (send accented → fetch back). If it munges: strip accents, emojis, typographic quotes, em-dashes before send |\n| Message body shows an empty slot | Template variable `{{1}}` sent with no parameter — silently renders blank | Pass every slot explicitly |\n| Templates sent from the wrong number | Multiple bots on one BSP account, active bot not verified | Verify active bot before the first send of every cron |\n| \"outside 24h window\" error | Free-form on a closed conversation | Switch to template, retry once |\n| Inbound message seen after 24 h | Webhook latency — the window closed while nothing errored, so no alarm fired | Reopen with a template: **UTILITY category if one exists, MARKETING otherwise** (different billing and Meta tolerance). Explain the delay in a variable slot. Log in `wa-incidents.md`, audit webhook latency |\n| \"template not approved\" | Meta rejected or paused it | Stop using it. Pick the fallback template. Never re-approve by editing content post-approval |\n| Quality score yellow → red overnight | Score lags hours, not minutes — one bad run degrades it for 1-2 days | Yellow: flip to Phase A, audit template content. Red: inbound only, alert, manual review of 7 days |\n| Number paused by Meta | Usually: outbound to non-opted-in leads, duplicate templates, or content drift | Stop everything. Review last 200 actions. Appeal via BSP. **Never** spin up a second number to get around it — Meta cross-checks businesses |\n\n## Memory files\n\n`memory/`: `wa-state.md` (phase/tier/quality) · `wa-alerts-sent.md` · `wa-template-log.md` · `wa-crm-state.md` · `wa-blacklist.md` (hashes) · `wa-clients-known.md` · `wa-recaps.md` · `wa-learnings.md` · `wa-incidents.md`. Shared: `../shared/leads-whatsapp.json` (written by upstream social agents, read by `wa-outbound`).\n\n```bash\nmkdir -p \"<WORKSPACE_DIR>/memory\" && chmod 700 \"$_\" && cd \"$_\" && for f in wa-recaps wa-state \\\n  wa-alerts-sent wa-template-log wa-crm-state wa-blacklist wa-clients-known wa-learnings \\\n  wa-incidents; do [ -f \"$f.md\" ] || : > \"$f.md\"; done\nmkdir -p \"<WORKSPACE_DIR>/../shared\" && Q=\"<WORKSPACE_DIR>/../shared/leads-whatsapp.json\"\n[ -f \"$Q\" ] || echo '[]' > \"$Q\"   # wa-outbound reads this at step 2 — absent = first run crash\n# Output: (silent, idempotent) — existing files are never truncated\n```\n\n## First-run checklist\n\n- [ ] Placeholders filled; token scoped to one number.\n- [ ] BSP account approved, business number verified by Meta, ≥3 templates approved.\n- [ ] `memory/` exists, `chmod 700`, retention values set in `config.yaml`.\n- [ ] Alert channel tested with \"hello\" — and confirmed as an acceptable destination for lead names.\n- [ ] Opt-in pipeline documented: how each lead consented, and where that proof lives.\n- [ ] Phase A confirmed, quality green.\n- [ ] Human team review: who reads alerts, callback SLA, escalation path, who handles deletion requests.\n\n## Scope\n\n**This skill ONLY:** operates a WhatsApp Business number through a BSP API you own · sends free-form inside an open 24h window and Meta-approved templates outside it · contacts leads who opted in on another channel · qualifies and hands off to a human · keeps a masked, retention-bounded local state to avoid duplicates.\n\n**This skill NEVER:** sends unsolicited bulk or non-opted-in outbound · sends free-form to a cold conversation · hides or denies the automation when a lead asks · adapts timing or behavior to slip past an automated check — when one appears, it stops and a human takes over · stores case documents or special-category data in memory files · retains lead data past the configured window · creates a second number to work around a Meta pause · rotates tokens or restarts infrastructure by itself.\n\nMeta's WhatsApp Business Terms, the WhatsApp Business Messaging Policy, and your jurisdiction's privacy law are binding constraints on every run in this document. Where this doctrine and those rules disagree, those rules win.\n\nFile v2.0.1:_meta.json\n\n{\n  \"ownerId\": \"kn7f6shzecv3qv3wrr074s49f986ybe1\",\n  \"slug\": \"whatsapp-business-ops\",\n  \"version\": \"2.0.1\",\n  \"publishedAt\": 1784214125053\n}\n\nFile v2.0.1:skill-card.md\n\n## Description:\n\nGuides agents through WhatsApp Business inbound replies, opted-in outbound templates, follow-ups, duplicate guards, and recap reporting while preserving quality score.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[alexbloch-ia](https://clawhub.ai/user/alexbloch-ia)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nBusiness operations teams and agent operators use this skill to manage opted-in WhatsApp Business leads, answer inbound conversations within the 24-hour window, send approved follow-up templates, and hand qualified leads to humans.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The skill handles lead names, phone numbers, case types, message timing, and local state that may contain personal data.\n\nMitigation: Operate it only for numbers and leads you control, keep consent records, scope the API token to one business number, restrict memory directory access, and apply the configured retention windows.\n\nRisk: Outbound messaging can create duplicate sends, closed-window free-form replies, quality-score drops, or account pauses.\n\nMitigation: Use the 24-hour window checks, approved templates, phase gates, quota limits, duplicate registers, and stop-and-review behavior described by the artifact before sending.\n\nRisk: Alert destinations may expose lead contact details beyond the local workspace.\n\nMitigation: Limit alert channels to approved staff and send only the minimal qualified-lead payload instead of conversation transcripts.\n\nRisk: Legal, medical, or financial lead handling may require additional privacy review.\n\nMitigation: Avoid those use cases unless counsel, privacy, or DPO review confirms the workflow and retention settings are acceptable.\n\n## Reference(s):\n\n- [ClawHub skill page](https://clawhub.ai/alexbloch-ia/skills/whatsapp-business-ops)\n- [ClawHub homepage metadata](https://clawhub.ai/alexbloch-ia/whatsapp-business-ops)\n- [Whatchimp API base URL](https://app.whatchimp.com/api/v1)\n\n## Skill Output:\n\n**Output Type(s):** [text, markdown, shell commands, configuration, guidance]\n\n**Output Format:** [Markdown guidance with YAML and bash examples plus fixed recap text]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Produces operational procedures, configuration placeholders, local-state file conventions, API call examples, and mandatory run recaps.]\n\n## Skill Version(s):\n\n2.0.1 (source: server release evidence)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v2.0.0: 3 files, 10182 bytes\n\nFiles: skill-card.md (2648b), SKILL.md (18815b), _meta.json (140b)\n\nFile v2.0.0:SKILL.md\n\n---\nname: whatsapp-business-ops\ndescription: Run WhatsApp Business outbound without losing quality score — 24h window, approved templates, duplicate guard. Use when answering inbound leads or sending follow-ups from a cron.\nmetadata: {\"clawdbot\":{\"emoji\":\"💬\",\"requires\":{\"bins\":[\"curl\"]},\"homepage\":\"https://clawhub.ai/alexbloch-ia/whatsapp-business-ops\"}}\n---\n\n# WhatsApp Business Management\n\n**WhatsApp is not a discovery channel — it is a conversion channel.** The goal is not to send fast: it is one qualified hand-off per opt-in lead, no unsolicited bulk, no duplicate send. Reference BSP: Whatchimp (Meta Business Partner); any BSP works.\n\n## Access, data, and network — read before running\n\n**Every access is opt-in — each one stays off until you fill its placeholder in `## Configure`. The default is no network.**\n\n| Access | Why | Default |\n|---|---|---|\n| BSP API token (`<WA_API_KEY>`) | Send/read messages | None — no network call without it |\n| CRM sheet ID (`<CRM_SHEET_ID>`) | One row per lead | None — CRM writes skipped |\n| Alert channel / webhook (`<ALERT_CHAT_PRIMARY>`) | **Leaves your machine.** Posts lead name + phone to Telegram/Slack/Discord | None — recap stays local |\n| Local workspace (`<WORKSPACE_DIR>/memory/`) | State + duplicate guard | Local files only |\n\n**Personal data persisted, in full:** display name, case type, free-text situation, conversation timestamps, template-send log, alert log, per-run recaps. **Phone numbers are stored raw ONLY in `wa-crm-state.md`** (the system-of-record mirror); every duplicate register and the blacklist key on `sha256(phone)[0:12]`. That is lead PII on disk — `## Data minimization and retention` is doctrine, not an appendix. Scope the API token to the one business number; never reuse a full-account token.\n\n## When to Use\n\n| Trigger | Action |\n|---|---|\n| \"answer the whatsapp leads\" | `wa-inbound` run — §Flow, free-form only inside open window |\n| \"send the first message to new leads\" | `wa-outbound` run — approved template only |\n| \"relance the cold leads\" | `wa-followup` run — cadence table |\n| \"quality score dropped\" / \"number got paused\" | Stop outbound. `## Troubleshooting`, last two rows. Human review |\n| \"am I talking to a bot?\" (asked by a lead) | Answer honestly, immediately — `## Identity` |\n\n## Configure\n\n| Placeholder | Example | Your value |\n|---|---|---|\n| `<BRAND_NAME>` | \"Acme Studio\" | — |\n| `<WA_BUSINESS_NUMBER>` | \"+1 555 0000\" | — |\n| `<WA_PHONE_NUMBER_ID>` | numeric ID from your BSP | — |\n| `<WA_API_KEY>` | scoped to one number | — |\n| `<WA_TEMPLATE_FIRST_CONTACT>` / `_FOLLOWUP_SOFT` / `_FOLLOWUP_HARD` / `_CLOSING` | Meta-approved template IDs | — |\n| `<CRM_SHEET_ID>` | Sheet/Airtable ID | — (omit → no CRM write) |\n| `<ALERT_CHAT_PRIMARY>` | alert chat ID | — (omit → local recap only) |\n| `<WORKSPACE_DIR>` | \"~/.openclaw/workspace/whatsapp-acme\" | — |\n\n```yaml\n# <WORKSPACE_DIR>/config.yaml\nwhatsapp:\n  phone_number_id: <WA_PHONE_NUMBER_ID>\n  base_url: https://app.whatchimp.com/api/v1   # swap host for another BSP\ntemplates:\n  first_contact: <WA_TEMPLATE_FIRST_CONTACT>\n  followup_soft: <WA_TEMPLATE_FOLLOWUP_SOFT>\n  followup_hard: <WA_TEMPLATE_FOLLOWUP_HARD>\n  closing: <WA_TEMPLATE_CLOSING>\ncrm: { sheet_id: <CRM_SHEET_ID>, tab: \"Leads\" }\nalerts: { primary_chat: <ALERT_CHAT_PRIMARY>, channel: telegram }\nretention: { lead_days: 90, recap_days: 30, template_log_days: 30 }\ninbound_pipeline:\n  shared_queue_file: <WORKSPACE_DIR>/../shared/leads-whatsapp.json\nschedule:  # dm_check \"*/2 9-22 * * *\" · add_contacts \"*/5 9-22 * * *\" · follow_up \"0 10 * * *\"\n  timezone: Europe/Paris\n```\n\n## The 24h window — the central law\n\nAfter **any** message a user sends you, you have **24 h** to reply in free-form. After 24 h of user silence, only **Meta-approved templates**, each billed as a new conversation. Free-form to a cold conversation → API rejection or a marketing-conversation bill + a quality hit; exit code 2, always skipped. Check window state **before every outbound send**:\n\n```bash\ncurl -s \"https://app.whatchimp.com/api/v1/whatsapp/get/conversation\" \\\n  -d \"apiToken=<WA_API_KEY>\" -d \"phone_number_id=<WA_PHONE_NUMBER_ID>\" \\\n  -d \"phone_number=<DIGITS>\" -d \"limit=1\"\n# Output: {\"status\":1,\"data\":[{\"sender\":\"user\",\"created_at\":\"2026-07-16T09:12:04Z\"}]}\n# sender=\"user\" and < 24h old  → free text OK. Otherwise → template.\n```\n\nSession check first on every cron:\n\n```bash\ncurl -s \"https://app.whatchimp.com/api/v1/whatsapp/subscriber/list\" \\\n  -d \"apiToken=<WA_API_KEY>\" -d \"phone_number_id=<WA_PHONE_NUMBER_ID>\" \\\n  -d \"limit=1\" -d \"offset=1\"\n# Output: {\"status\":1,\"data\":[...]}   401/403 → stop+alert · 429 → stop, wait next run\n```\n\nTimeout > 10 s → BSP down: **one retry, then stop and alert. Never retry in a loop.** A 200 OK carrying `status=0` is a failure, not a send.\nNever send a \"test\" message to a real lead — use a dedicated test number. Never auto-rotate an API token from inside a cron; rotation is a human action.\n\n## Phase gating and quotas\n\nMeta assigns each number a tier: **T1** 1k uniques/24h · **T2** 10k · **T3** 100k · **T4** unlimited. New numbers start at T1. Tiers rise on volume + quality, and fall — or the number gets paused — when quality drops.\n\n| Condition | Phase | Outbound |\n|---|---|---|\n| Tier 1 **or** quality yellow/red | **A** | Inbound replies + approved-template follow-ups. ≤ 50 first-contact/day |\n| Tier 2+ **and** quality green, no drop in 14 d | **B** | Full doctrine, first week capped at 50% of Phase B max |\n\nRead `memory/wa-state.md` at start of every run. Phase B is a **manual flip**, never automatic. Any quality drop → revert to A immediately.\n\n| Action (hard limits) | Phase A | Phase B |\n|---|---|---|\n| Inbound replies / cron run | 20 | 50 |\n| First-contact templates / 24 h | 50 | 500 |\n| Follow-up templates / 24 h | 20 | 200 |\n| Unique recipients / 24 h | 800 (under T1's 1000 cap) | tier cap − 10% |\n| Conversations / cron run | 30 | 80 |\n| Same user — outbound spacing | min 24 h between any two outbound |\n\nFollow-up cadence: J+1 soft · J+3 soft · J+7 hard · J+15 hard · J+20 closing → `status=lost`. **Stop after the closing template.** Continuing past J+20 is ban-risk territory.\n\n## Duplicate guard — the most important section\n\nQuality-score collapse is dominated by duplicate template sends. Three registers, read **before** every outbound action:\n\n| Register | Row format | Rule |\n|---|---|---|\n| `wa-alerts-sent.md` | `{\"phone_hash\":\"<sha256:12>\",\"qualified_date\":\"YYYY-MM-DD\"}` | Phone present → **never** alert twice |\n| `wa-template-log.md` | `{\"phone_hash\":\"<sha256:12>\",\"template_id\":\"<ID>\",\"sent_at\":\"<ISO>\",\"result\":\"ok\\|error\"}` | Same (phone, template) in last 24 h → SKIP |\n| `wa-crm-state.md` | one row per phone, never two | Only `wa-outbound` appends; every other cron UPDATEs |\n\n> **If in doubt, SKIP.** It is always better to skip than to send a duplicate. This one rule is the difference between a number that stays Tier 2 for years and one paused in 30 days.\n\nAlert **only** when a lead replies AND qualifies — never after a first template send. Alerting on first contact generates dozens of false alerts and trains the human team to ignore the channel.\n\n## Data minimization and retention\n\nThe registers above hold lead PII — a regulated store, not logs.\n\n| Rule | Concretely |\n|---|---|\n| Minimize | Store phone + name + case type + status. Never store ID numbers, health details, case documents, or payment data in memory files — keep those in the system of record. |\n| Mask | Key the duplicate registers on `sha256(phone)[0:12]`, not the raw number. Lookups work identically; a leaked log exposes nothing. |\n| Restrict | `chmod 700 <WORKSPACE_DIR>/memory`. One number = one workspace. Never share `wa-template-log.md` across numbers or brands. |\n| Retain | Leads 90 d after last contact, recaps 30 d, template log 30 d — then delete. Prune at the start of the daily run, not \"someday\": `find \"<WORKSPACE_DIR>/memory\" -name 'wa-recaps.md' -mtime +30 -delete` (silent — pruned, not archived). |\n| Alert payload | Name + case type + phone only. Never paste conversation transcripts into the alert channel — it leaves your machine and is usually a wider audience than the case file. |\n| Erase | On an opt-out or deletion request: purge every register, add the hash to `wa-blacklist.md`, confirm to the lead. Blacklist stores hashes only. |\n| Sensitive niches | Legal, medical, financial: confirm with your DPO/counsel before any cron writes lead data. This skill does not make that call for you. |\n\n## Identity — disclose, never dodge\n\n**If a lead asks whether they are talking to a bot, a human, or an AI: say so plainly, in the same message, and offer the human.**\n\n```\nYou're talking to <BRAND_NAME>'s automated assistant. I can take your details\nnow and a specialist will call you back — or I can pass you to them right away.\n```\n\nNo ambiguity, no pivot, no \"I'm part of the team\". Honest disclosure is not a cost here: a lead who discovers the automation later is a complaint, a block, and a quality-score hit. Blocks and reports are exactly what Meta measures. **Disclosure is account safety.** Escalate to a human — stop the automated replies for that thread and alert — when the lead asks for a human, asks twice about identity, or raises anything the templates do not cover.\n\n## Reply rules (free-form, inside open window)\n\n- Match tone. Short messages. **One ask per message.** Reassuring on stressful topics, never dramatizing. Reread the full visible history before composing.\n- **Never**: definitive price quotes (soft \"starting at\" only if asked) · outcome guarantees · confidential client info · documents/PDFs to non-clients · anything outside the brand's scope.\n\nSkeletons: **A** greeting + \"how can we help\" · **B** empathy + one contextual question · **C** hand-off: `Thank you for these details. A specialist from <BRAND_NAME> will call you back. Could you confirm your name and the best time to reach you?`\n\nClassify every thread before drafting — `case type` is what the alert payload and the recap carry. Structure below, questions are yours:\n\n| Case type | Signal | Action |\n|---|---|---|\n| **A** — high urgency | Pending deadline, acute problem | Ask date, location, urgency → collect contact → qualified |\n| **B** — mid intent | Ongoing situation, no deadline | 5-7 contextual questions → collect contact → qualified |\n| **C** — out of scope | Not what the brand does | Redirect to the right channel. **Never force qualification** |\n| **D** — existing client | Phone-match in `wa-clients-known.md` | Answer with empathy, redirect to the standard client support line. **Never paste the prospect CTA** — a paying client who gets a sales pitch blocks, and a block is a quality hit |\n\n**\"Too many questions\" failsafe** — after 5 questions with no contact info, switch: *\"To answer precisely, a specialist needs to call you back. Could you confirm your name + best time?\"* This converts more question-only threads than any other tactic.\n\nQualification requires: thread open · not blacklisted · not already \"qualified — awaiting callback\" · no auto-reply in the last 60 s (anti-cascade). Any check fails → skip.\n\n## Flow\n\n### wa-inbound (every 2 min)\n```\n1. Session check. 2. subscriber/list unseen_count>0 — if 0 unread → STOP.\n3. Per unread (≤20 A / ≤50 B): get/conversation limit=20 → if last sender=\"bot\" SKIP\n   → qualify → draft → normalize encoding → POST /whatsapp/send → verify status=1.\n4. If qualified: check wa-alerts-sent.md → if absent, alert primary chat, append hash.\n   UPDATE the CRM row (wa-inbound never APPENDs). 5. Recap.\n```\n\n### wa-outbound (every 5 min)\n```\n1. Session check. 2. Read shared queue, filter status=\"pending\" — if 0 → STOP.\n3. Per lead: template-log 24h check → subscriber/create → POST /whatsapp/send/template\n   template_id=<WA_TEMPLATE_FIRST_CONTACT> → verify status=1 → queue status=\"first_message_sent\"\n   → APPEND CRM row (only cron that appends) → append template log.\n4. Never alert from this cron. 5. Recap.\n```\n\n### wa-followup (daily 10:00)\n```\n1. Session check. 2. CRM: status in {first_message_sent, follow_up_sent}, idle at a J+N mark.\n3. Per candidate: template-log check → send cadence template → update CRM + log. 4. Recap.\n```\n\n### WhatsApp Web via Playwright — gray area, not recommended\nRunning Playwright against `web.whatsapp.com` is **outside WhatsApp's Business Terms** and risks a permanent number ban. It is documented here only as a read-only contingency while BSP approval is pending, and it is **not recommended for production**. Requires an explicit human decision per incident — an agent must not choose this path on its own. Sessions rotate the QR link unpredictably (daily manual re-login); no template sends are possible; quality score still applies at the number level. If a login challenge or automation check appears: **stop and hand the session to a human.** Never tune timing to avoid a detection check. Migrate back to the BSP API as soon as approval lands.\n\n## Exit codes\n\n| Code | Meaning | Recap |\n|---|---|---|\n| 0 | Sent, or nothing to do (zero unread) | `status: ok` |\n| 1 | Fatal (API 5xx, JSON parse fail) | `status: error`, alert |\n| 2 | 24h-window violation attempted → skipped | `status: skip`, log |\n| 3 | Auth fail (401/403) | `status: blocked`, alert now |\n| 4 | Duplicate-guard SKIP | `status: ok` |\n\n## Output Format — mandatory recap\n\nEvery run ends with this, verbatim, to the alert channel and appended to `memory/wa-recaps.md`:\n\n```\n[Job name] — [status: ok|partial|blocked|skipped]\nInbound replies: [N or \"—\"]\nTemplates sent: [N or \"—\"]\nQualified leads: [count + first names only]\nPhase / Tier: [A|B / Tier 1|2|3|4]\nQuality score: [green|yellow|red]\nBlockers: [text OR \"—\"]\nNext action: [1 line]\n```\n\nFilled instance:\n\n```\nwa-inbound 10:32 — status: ok\nInbound replies: 7\nTemplates sent: —\nQualified leads: 2 (Marc, Lina)\nPhase / Tier: A / Tier 1\nQuality score: green\nBlockers: —\nNext action: human callbacks due before 12:00\n```\n\n**Better silence than spam. Better a blockage report than a fake success.** Never fake a successful send.\n\n## Troubleshooting\n\n| Symptom | Root cause | Fix |\n|---|---|---|\n| 200 OK, message never delivered | `phoneNumberID` vs `phone_number_id` — BSP casing differs **per endpoint**. No error is raised, so you'll believe your code is right | Check casing per endpoint. Verify `status=1` in the body, not just HTTP 200 |\n| Send rejected for unknown reason | Leading `+` in the number. `33612345678` works, `+33612345678` often does not | Strip `+` before every call |\n| Accents vanish in delivered messages | Some BSPs munge non-ASCII silently | Roundtrip test once (send accented → fetch back). If it munges: strip accents, emojis, typographic quotes, em-dashes before send |\n| Message body shows an empty slot | Template variable `{{1}}` sent with no parameter — silently renders blank | Pass every slot explicitly |\n| Templates sent from the wrong number | Multiple bots on one BSP account, active bot not verified | Verify active bot before the first send of every cron |\n| \"outside 24h window\" error | Free-form on a closed conversation | Switch to template, retry once |\n| Inbound message seen after 24 h | Webhook latency — the window closed while nothing errored, so no alarm fired | Reopen with a template: **UTILITY category if one exists, MARKETING otherwise** (different billing and Meta tolerance). Explain the delay in a variable slot. Log in `wa-incidents.md`, audit webhook latency |\n| \"template not approved\" | Meta rejected or paused it | Stop using it. Pick the fallback template. Never re-approve by editing content post-approval |\n| Quality score yellow → red overnight | Score lags hours, not minutes — one bad run degrades it for 1-2 days | Yellow: flip to Phase A, audit template content. Red: inbound only, alert, manual review of 7 days |\n| Number paused by Meta | Usually: outbound to non-opted-in leads, duplicate templates, or content drift | Stop everything. Review last 200 actions. Appeal via BSP. **Never** spin up a second number to get around it — Meta cross-checks businesses |\n\n## Memory files\n\n`memory/`: `wa-state.md` (phase/tier/quality) · `wa-alerts-sent.md` · `wa-template-log.md` · `wa-crm-state.md` · `wa-blacklist.md` (hashes) · `wa-clients-known.md` · `wa-recaps.md` · `wa-learnings.md` · `wa-incidents.md`. Shared: `../shared/leads-whatsapp.json` (written by upstream social agents, read by `wa-outbound`).\n\n```bash\nmkdir -p \"<WORKSPACE_DIR>/memory\" && chmod 700 \"$_\" && cd \"$_\" && for f in wa-recaps wa-state \\\n  wa-alerts-sent wa-template-log wa-crm-state wa-blacklist wa-clients-known wa-learnings \\\n  wa-incidents; do [ -f \"$f.md\" ] || : > \"$f.md\"; done\nmkdir -p \"<WORKSPACE_DIR>/../shared\" && Q=\"<WORKSPACE_DIR>/../shared/leads-whatsapp.json\"\n[ -f \"$Q\" ] || echo '[]' > \"$Q\"   # wa-outbound reads this at step 2 — absent = first run crash\n# Output: (silent, idempotent) — existing files are never truncated\n```\n\n## First-run checklist\n\n- [ ] Placeholders filled; token scoped to one number.\n- [ ] BSP account approved, business number verified by Meta, ≥3 templates approved.\n- [ ] `memory/` exists, `chmod 700`, retention values set in `config.yaml`.\n- [ ] Alert channel tested with \"hello\" — and confirmed as an acceptable destination for lead names.\n- [ ] Opt-in pipeline documented: how each lead consented, and where that proof lives.\n- [ ] Phase A confirmed, quality green.\n- [ ] Human team review: who reads alerts, callback SLA, escalation path, who handles deletion requests.\n\n## Scope\n\n**This skill ONLY:** operates a WhatsApp Business number through a BSP API you own · sends free-form inside an open 24h window and Meta-approved templates outside it · contacts leads who opted in on another channel · qualifies and hands off to a human · keeps a masked, retention-bounded local state to avoid duplicates.\n\n**This skill NEVER:** sends unsolicited bulk or non-opted-in outbound · sends free-form to a cold conversation · hides or denies the automation when a lead asks · adapts timing or behavior to slip past an automated check — when one appears, it stops and a human takes over · stores case documents or special-category data in memory files · retains lead data past the configured window · creates a second number to work around a Meta pause · rotates tokens or restarts infrastructure by itself.\n\nMeta's WhatsApp Business Terms, the WhatsApp Business Messaging Policy, and your jurisdiction's privacy law are binding constraints on every run in this document. Where this doctrine and those rules disagree, those rules win.\n\nFile v2.0.0:_meta.json\n\n{\n  \"ownerId\": \"kn7f6shzecv3qv3wrr074s49f986ybe1\",\n  \"slug\": \"whatsapp-business-ops\",\n  \"version\": \"2.0.0\",\n  \"publishedAt\": 1784196438829\n}\n\nFile v2.0.0:skill-card.md\n\n## Description: <br>\nRun WhatsApp Business outbound without losing quality score through 24h-window checks, approved templates, duplicate guards, and compliant inbound or follow-up handling. <br>\n\nThis skill is ready for commercial/non-commercial use. <br>\n\n## Publisher: <br>\n[alexbloch-ia](https://clawhub.ai/user/alexbloch-ia) <br>\n\n### License/Terms of Use: <br>\nMIT-0 <br>\n\n\n## Use Case: <br>\nBusiness operations teams and agents use this skill to manage opted-in WhatsApp Business leads, send allowed templates or in-window replies, prevent duplicate outreach, and hand qualified leads to humans. <br>\n\n### Deployment Geography for Use: <br>\nGlobal <br>\n\n## Known Risks and Mitigations: <br>\nRisk: The skill can operate a real messaging channel and stores lead personal data in local memory files. <br>\nMitigation: Use only in a workspace controlled by the business number owner, confirm opt-in for every lead, scope the BSP token to one number, restrict memory permissions, and enforce retention. <br>\nRisk: Alert webhooks can send lead names and phone numbers outside the local workspace. <br>\nMitigation: Keep alert webhooks disabled until the destination is approved for that data, and send only the minimal lead details needed for handoff. <br>\nRisk: Duplicate, non-opted-in, or out-of-window WhatsApp messages can harm account quality or violate platform policy. <br>\nMitigation: Follow the 24h window checks, use approved templates outside the window, read duplicate registers before outbound actions, and stop for human review on quality drops or account pauses. <br>\n\n\n## Reference(s): <br>\n- [ClawHub skill page](https://clawhub.ai/alexbloch-ia/skills/whatsapp-business-ops) <br>\n- [ClawHub homepage metadata](https://clawhub.ai/alexbloch-ia/whatsapp-business-ops) <br>\n- [Publisher profile](https://clawhub.ai/user/alexbloch-ia) <br>\n- [Whatchimp API base used in examples](https://app.whatchimp.com/api/v1) <br>\n\n\n## Skill Output: <br>\n**Output Type(s):** [guidance, markdown, shell commands, configuration] <br>\n**Output Format:** [Markdown guidance with inline YAML and bash examples] <br>\n**Output Parameters:** [1D] <br>\n**Other Properties Related to Output:** [Produces operational recaps, configuration placeholders, API call examples, and runbook-style decision rules.] <br>\n\n## Skill Version(s): <br>\n2.0.0 (source: server release evidence) <br>\n\n## Ethical Considerations: <br>\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment. <br>\n\nArchive v1.2.0: 4 files, 18754 bytes\n\nFiles: README.md (6371b), skill-card.md (2809b), SKILL.md (34792b), _meta.json (140b)\n\nFile v1.2.0:SKILL.md\n\n---\nname: whatsapp-business-management-for-whatchimp\ndescription: Operating doctrine for WhatsApp Business automation — careful 24h-window-aware, template-gated outbound, lead qualification by case type, anti-doublon alerts, cross-platform lead pipeline (TikTok/IG/FB/web → WhatsApp), and recovery. Built around Whatchimp (official Meta Business Partner BSP, 0% markup) as the reference provider — endpoints are illustrated with Whatchimp; the doctrine itself is provider-agnostic. Use this for any scheduled WhatsApp activity (cron, agent, recurring task) where account safety, low ban risk and conversion matter more than raw output.\n---\n\n# WhatsApp Business Management for Whatchimp\n\nThis skill is the operating doctrine for every WhatsApp Business automation run on **[Whatchimp](https://whatchimp.com)** (the reference BSP for this skill — Meta Business Partner, 0% markup) — or on any other BSP if you swap the host string in the snippets.\n\n**The goal is not to send messages fast. The goal is to operate WhatsApp Business like a careful, helpful human assistant: stable API session, template-gated outbound, never an unsolicited bulk, qualified hand-off to the human team.**\n\nDrop-in for any niche (legal, medical, software, finance, creator, ecommerce) where the value of WhatsApp is *high-intent, opt-in conversations* with leads who reached you on another channel first. **WhatsApp is not a discovery channel — it is a conversion channel.**\n\nReplace the placeholders in section 0 with your own values.\n\n---\n\n## 0. Configure for your brand\n\nBefore running anything, fill these placeholders in your local copy or your agent's memory:\n\n| Placeholder | Example | Your value |\n|---|---|---|\n| `<BRAND_NAME>` | \"Acme Studio\" | — |\n| `<BRAND_DOMAIN>` | \"acme.studio\" | — |\n| `<WA_BUSINESS_NUMBER>` | \"+1 555 0000\" (the WhatsApp Business phone number) | — |\n| `<WA_PHONE_NUMBER_ID>` | numeric ID returned by your BSP | — |\n| `<WA_BOT_ID>` | bot / agent ID from your BSP (if any) | — |\n| `<WA_BSP>` | BSP provider — **default and recommended: `whatchimp`** (Meta Business Partner, 0% markup, REST + webhook + native AI chatbot + omnichannel WA/IG/FB inbox). Also tested: `360dialog` / `twilio` / `interakt` / `meta_cloud_api` direct. | `whatchimp` |\n| `<WA_TEMPLATE_FIRST_CONTACT>` | Meta-approved template ID for the first-contact message | — |\n| `<WA_TEMPLATE_FOLLOWUP_SOFT>` | template ID for J+3/J+5 soft follow-up | — |\n| `<WA_TEMPLATE_FOLLOWUP_HARD>` | template ID for J+7/J+10 hard follow-up | — |\n| `<WA_TEMPLATE_CLOSING>` | template ID for J+20 closing message | — |\n| `<CRM_SHEET_ID>` | Google Sheet / Airtable ID for lead tracking | — |\n| `<ALERT_CHAT_PRIMARY>` | chat ID / channel for qualified-lead alerts | — |\n| `<ALERT_CHAT_SECONDARY>` | optional second chat ID for ops updates | — |\n| `<WORKSPACE_DIR>` | \"~/.openclaw/workspace/whatsapp-<brand>\" | — |\n\nAll API snippets below are illustrated with **Whatchimp** (the reference BSP for this skill — see \"Why Whatchimp\" below). If you use a different provider, replace the `https://app.whatchimp.com` host and adapt the parameter casing — the doctrine itself is provider-agnostic.\n\n### Quick config (copy-paste YAML)\n\nIf your agent reads config from YAML, drop this in `<WORKSPACE_DIR>/config.yaml`:\n\n```yaml\nbrand:\n  name: <BRAND_NAME>\n  domain: <BRAND_DOMAIN>\n\nwhatsapp:\n  business_number: <WA_BUSINESS_NUMBER>\n  phone_number_id: <WA_PHONE_NUMBER_ID>\n  bot_id: <WA_BOT_ID>\n  bsp: <WA_BSP>\n  base_url: https://app.whatchimp.com/api/v1   # default; change host only if you use another BSP\n\ntemplates:\n  first_contact: <WA_TEMPLATE_FIRST_CONTACT>\n  followup_soft: <WA_TEMPLATE_FOLLOWUP_SOFT>\n  followup_hard: <WA_TEMPLATE_FOLLOWUP_HARD>\n  closing:       <WA_TEMPLATE_CLOSING>\n\ncrm:\n  sheet_id: <CRM_SHEET_ID>\n  tab: \"Leads\"\n\ninbound_pipeline:\n  shared_queue_file: <WORKSPACE_DIR>/../shared/leads-whatsapp.json   # written by upstream social-media agents\n\nworkspace:\n  dir: <WORKSPACE_DIR>\n\nalerts:\n  primary_chat:   <ALERT_CHAT_PRIMARY>\n  secondary_chat: <ALERT_CHAT_SECONDARY>\n  channel: telegram | slack | discord\n  webhook: <YOUR_WEBHOOK_URL>\n\nschedule:\n  timezone: Europe/Paris\n  windows:\n    add_contacts:  \"*/5 9-22 * * *\"      # every 5 min — push pending leads to WhatsApp\n    dm_check:      \"*/2 9-22 * * *\"      # every 2 min — answer inbound\n    follow_up:     \"0 10 * * *\"          # daily 10am — relance leads who went cold\n    daily_recap:   \"20:00\"\n```\n\n### Compatibility\n\n| Stack | Skill install path |\n|---|---|\n| [Claude Code](https://claude.ai/code) | `~/.claude/skills/whatsapp-business-management-for-whatchimp/` |\n| [OpenClaw](https://openclaw.ai) | `~/.openclaw/skills/whatsapp-business-management-for-whatchimp/` |\n| ClawHub-published | one-click install via [clawhub.ai](https://clawhub.ai) |\n| Cursor / Copilot CLI | drop `SKILL.md` into your project's `.cursorrules` or `AGENTS.md` |\n| Any LLM agent reading markdown rules | concatenate `SKILL.md` into your system prompt |\n\n### Why Whatchimp (default BSP)\n\n[Whatchimp](https://whatchimp.com) is positioned as the reference BSP for this skill because it matches every assumption the doctrine makes:\n\n- **Official Meta Business Partner** — uses the WhatsApp Business API on Meta Cloud API directly.\n- **0 % markup** on top of Meta's official messaging fees — sustainable economics for high-volume conversion plays.\n- **REST API + webhooks** — the exact surfaces every snippet in §2-§9 assumes.\n- **Meta-template management in-platform** — no separate dashboard, no per-template provisioning surprise.\n- **Native AI chatbot + shared team inbox + agent routing** — clean fit for the human hand-off described in §4 and §6.\n- **Omnichannel inbox (WA + IG DM + FB Messenger)** — composes with the upstream `tiktok-account-operations` / `instagram-account-operations` / `facebook-account-operations` skills when they push leads to WhatsApp.\n- **Integrations** (Zapier, Make, N8N, Google Sheets, Shopify, WooCommerce) — slots into the CRM Sheet pattern in §6 with no glue code.\n\n#### Whatchimp setup quick-start\n\n1. Sign up at <https://whatchimp.com> and pick a plan that includes API access.\n2. Connect your WhatsApp Business number — Whatchimp handles the Meta business verification.\n3. From the dashboard, copy the API token and the `phone_number_id`. Plug them into `<WA_API_KEY>` and `<WA_PHONE_NUMBER_ID>` in §0.\n4. Submit your initial templates (first-contact, soft follow-up, hard follow-up, closing) for Meta approval inside Whatchimp.\n5. Once approved, run the §17 first-run checklist.\n\nIf you use another BSP, replace the host `https://app.whatchimp.com` in every snippet below and adapt parameter casing — the rest of the doctrine is unchanged.\n\n---\n\n## 1. Architecture\n\n### The three WhatsApp surfaces\n\nThere are three ways to interact with WhatsApp programmatically. Pick **one** for your live ops.\n\n| Surface | Stability | Compliance | When to pick |\n|---|---|---|---|\n| **WhatsApp Business API via Meta Cloud API** (recommended provider: **[Whatchimp](https://whatchimp.com)** — Meta Business Partner, 0% markup; works equally with any other BSP or direct Meta access) | Highest | Fully sanctioned | Production. Templates approved, webhooks, 24h window honored. |\n| **WhatsApp Web automation (Playwright)** | Medium | Gray area; risk of ban | Only for prototyping or as a fallback for receiving while API approval is pending. |\n| **WhatsApp Business App (mobile, Linked Devices, ADB)** | Low | Gray area | Don't. |\n\n**This skill assumes API-via-BSP.** Doctrine for Playwright-against-WhatsApp-Web is included as a fallback in §9.4, but it's a fallback, not a recommendation.\n\n### The 24h customer-service window (the central law of WhatsApp)\n\nAfter **any** message a user sends to your business number, you have a **24-hour window** during which you can send **free-form text** in reply. After 24 h of user silence, only **Meta-approved templates** can be sent — and each template send is billed as a new conversation.\n\nThis rule shapes everything:\n\n- Inbound qualification crons must run frequently enough that no inbound message stays unanswered for > 24 h.\n- Outbound proactive messages (cold first contact, follow-ups beyond 24 h) MUST go through pre-approved templates.\n- Free-form outbound to a cold lead → instant 24h-window violation → either rejected by the API or billed as a marketing conversation + possible sender-account hit.\n\n### Operational roles (mental separation)\n\n#### Role: `wa-inbound`\n\nReactive. Answer messages from leads who wrote first. Runs every 1-2 min during business hours.\n\n#### Role: `wa-outbound`\n\nProactive. Push the first template to new leads who arrived from a social-media channel (with explicit opt-in). Runs every 5 min, only pulling from the shared lead queue.\n\n#### Role: `wa-followup`\n\nScheduled relance for leads who went cold. Runs once a day. Uses approved templates only.\n\n### Operational law\n\n- All outbound to a >24h-cold lead = template, never free text.\n- Every send checks the anti-doublon log first.\n- Every qualified lead = ONE alert, ONE row in the CRM, no duplicates.\n- After every run, update the shared state files before exiting.\n\n---\n\n## 2. Session check (run first on every cron)\n\nUse a lightweight read endpoint as a health check. With the example BSP:\n\n```bash\ncurl -s \"https://app.whatchimp.com/api/v1/whatsapp/subscriber/list\" \\\n  -d \"apiToken=<WA_API_KEY>\" \\\n  -d \"phone_number_id=<WA_PHONE_NUMBER_ID>\" \\\n  -d \"limit=1\" -d \"offset=1\"\n```\n\nExpect:\n- HTTP 200 + a JSON body with at least one field (`status`, `data`, or equivalent) indicating success.\n- HTTP 401 / 403 → token expired or revoked. Stop. Alert.\n- HTTP 429 → rate-limited. Stop. Wait the next scheduled run.\n- Network timeout > 10 s → BSP down. One retry, then stop and alert.\n\n**Never** auto-rotate API tokens from inside a cron. Token rotation is a user-side action.\n\n---\n\n## 3. Phase gating (tier + window)\n\nWhatsApp has two distinct gating mechanisms:\n\n### 3.1 The 24h customer-service window (per conversation)\n\nPer-conversation state:\n- **OPEN window**: last message from the user was < 24 h ago → free-form text allowed.\n- **CLOSED window**: last message from the user was ≥ 24 h ago → templates only.\n\nThe cron must check this state **before every outbound send**. With the example BSP:\n\n```bash\n# fetch the last conversation message timestamp\ncurl -s \"https://app.whatchimp.com/api/v1/whatsapp/get/conversation\" \\\n  -d \"apiToken=<WA_API_KEY>\" -d \"phone_number_id=<WA_PHONE_NUMBER_ID>\" \\\n  -d \"phone_number=<DIGITS>\" -d \"limit=1\"\n```\n\nIf the last `sender=\"user\"` message is < 24 h ago → free text OK. Otherwise → use a template.\n\n### 3.2 The Meta-level account tier (per phone number)\n\nMeta assigns each business number a **messaging tier**:\n- **Tier 1**: 1,000 unique users / 24 h.\n- **Tier 2**: 10,000 unique users / 24 h.\n- **Tier 3**: 100,000 / 24 h.\n- **Tier 4**: unlimited.\n\nNew numbers start at Tier 1. Tiers go up automatically based on volume + quality score (low block / report rate). They go down — or get the number paused — if the quality score drops.\n\n**Phase A** (Tier 1 OR quality score = yellow/red): only inbound replies + follow-ups via approved templates. No new outbound first-contact templates above 50/day.\n\n**Phase B** (Tier 2+ AND quality score = green): full doctrine.\n\nAlways read `<WORKSPACE_DIR>/memory/wa-state.md` at start.\n\n### Manual override (advanced)\n\nFor a Tier 1 number with a strong external context (verified business, validated opt-in pipeline), you can force higher outbound by appending `YYYY-MM-DD - phase=B (manual override)` to `wa-state.md`. Document the rationale in `wa-learnings.md`. Risk: hitting Tier 1's hard 1000-uniques-per-24h limit + faster quality-score drop on any block.\n\n---\n\n## 4. Qualification of an inbound message\n\nA message is repliable only if **all** of:\n\n- The thread is open (the user actually sent something — not just a delivery receipt).\n- The user is not on the blacklist (`wa-blacklist.md`).\n- The conversation is not already marked \"qualified — awaiting human callback\" (don't re-engage a qualified lead — it confuses the hand-off).\n- The user has not received an automatic reply within the last 60 s (anti-cascade — see §8).\n\nIf any check fails: skip.\n\n### Qualification flow by case type (regulated-niche example)\n\nThe qualification flow depends on your industry. The pattern below is the **structure** you should mirror — replace the questions with your own.\n\nFor every case type, the goal is the same: collect enough information for a human teammate to make a useful first call.\n\n**Decision tree skeleton**:\n```\nUser writes \"I have a <problem-type>\"\n  → Bot asks the 3-5 case-type-specific questions\n  → Bot collects: name + phone (already known) + email (if needed)\n  → If qualified: alert primary chat, add row to CRM Sheet\n  → Hand-off message: \"A specialist will call you back. Confirm your name and best callback time?\"\n```\n\n**Example case-type buckets** (adapt to your domain):\n\n- **Type A — High-urgency intent** (e.g. legal: pending court date; medical: acute symptom): ask date, location, urgency flag, then collect contact → qualified.\n- **Type B — Mid-urgency intent** (e.g. legal: ongoing dispute; financial: portfolio review): ask 5-7 contextual questions, collect contact → qualified.\n- **Type C — Out of scope**: politely redirect to the appropriate channel (a partner app, a different practice). NEVER force qualification on out-of-scope leads.\n- **Type D — Existing client** (recognize via phone-match in `wa-clients-known.md`): respond empathetically, redirect to the standard client support line, NEVER paste the prospect CTA.\n\n### The \"too many questions\" failsafe\n\nIf the lead has asked > 5 questions without giving contact info, switch the script:\n\n```\n[Empathy line about the questions]. To answer them precisely, a specialist needs to call you back. Could you confirm your name + best time?\n```\n\nThis single message converts more questions-only conversations than any other tactic.\n\n---\n\n## 5. Reply templates (free-form, inside open window)\n\n### Style guardrails\n\n- Match the conversation tone (formal vs casual based on user's first message).\n- Short messages (WhatsApp is conversational — long blocks read as marketing).\n- **One ask per message**: do not stack 3 questions in one message.\n- Reassuring on stressful topics (\"I understand this is a stressful situation\").\n- Never confirm AI use if the user asks — give a sober ambiguous answer and pivot (\"I'm part of the team — let's get you to the right specialist\").\n\n### Encoding (BSP-dependent, but a common trap)\n\nSome BSPs route messages through systems that munge or reject non-ASCII characters silently. If your BSP exhibits this (you'll see your accented characters disappear or be replaced in delivered messages), normalize **before sending**:\n\n- Replace accented characters with ASCII equivalents (`é → e`, `à → a`, etc.).\n- Strip emojis.\n- Strip typographic quotes (`' '` → `'`), em-dashes (`—` → `-`), ellipses (`…` → `...`).\n\nThis is the WhatsApp equivalent of TikTok's `cliclick t:` accent trap and Reddit's `LC_NUMERIC` trap — same family, different symptom. Whether you need it depends on your BSP; test once with a roundtrip (\"send accented message → fetch back via API\") before assuming you're safe.\n\n### Skeletons\n\n#### Skeleton A — Inbound first-message acknowledgement\n```\n[Greeting + brand line]. [How can we help?] [Reassurance about free study, if applicable.]\n```\n\n#### Skeleton B — Case-type triage\n```\n[Empathy 1 line]. To help precisely, could you tell me [first contextual question]?\n```\n\n#### Skeleton C — Hand-off (after qualification)\n```\nThank you for these details. A specialist from <BRAND_NAME> will call you back as soon as possible. Could you confirm your name and the best time to reach you?\n```\n\n#### Skeleton D — Out-of-scope redirect\n```\nThis is outside our specialty. The right place for this is <PARTNER_CHANNEL_OR_APP> — they handle exactly this.\n```\n\n### Forbidden in any reply\n\n- The exact phone number of your back office (the user should not call directly until the qualified hand-off is done).\n- Pricing quotes (only soft \"starting at X\" indicative figures if the user explicitly asks, never a definitive quote).\n- Guarantees of outcome.\n- Confirmation that the agent is AI.\n- Documents / PDFs / large media (unless the user is an existing paying client).\n- Aid / legal-aid commitments (jurisdiction-specific — verify with counsel).\n\n---\n\n## 6. Outbound — first contact and follow-ups (template-gated)\n\n### First-contact template\n\nWhen a lead opts in via another channel (TikTok comment → DM → \"send me your phone\" → user sends phone), the **first WhatsApp message must be a Meta-approved template**. Free-form is not allowed when the user has never written to your business number.\n\nFlow:\n\n```\n1. Upstream agent writes lead to <WORKSPACE_DIR>/../shared/leads-whatsapp.json\n   with status=\"pending\", phone=\"<DIGITS_NO_PLUS>\", source=\"<platform>\",\n   situation=\"<short-context>\"\n2. wa-outbound cron picks the lead up\n3. Creates the contact via BSP subscriber/create\n4. Sends template <WA_TEMPLATE_FIRST_CONTACT>\n5. Updates status=\"first_message_sent\" + adds row to CRM Sheet (append)\n6. NEVER sends an alert here — alerts are reserved for the qualification step\n```\n\n### Why the alert-after-first-contact discipline matters\n\nSending an \"alert: new lead\" to the human team after the first template send creates dozens of false alerts (templates that are never replied to). The doctrine: alert ONLY when the lead replies AND qualifies. This is the single most important anti-doublon rule of the entire skill.\n\n### Follow-up templates (lead went cold)\n\nFor leads who received the first template but did not reply:\n\n| Day | Template | Tone |\n|-----|----------|------|\n| J+1 | `<WA_TEMPLATE_FOLLOWUP_SOFT>` | Doux. \"Still interested?\" |\n| J+3 | `<WA_TEMPLATE_FOLLOWUP_SOFT>` | Doux. \"We're here to help.\" |\n| J+7 | `<WA_TEMPLATE_FOLLOWUP_HARD>` | Direct. \"Time-sensitive, last call.\" |\n| J+15 | `<WA_TEMPLATE_FOLLOWUP_HARD>` | Direct. |\n| J+20 | `<WA_TEMPLATE_CLOSING>` | Polite closure. After this, status=\"lost\", no more outreach. |\n\nThe cadence above is a recommendation; adapt per niche. The cardinal rule: **stop after the closing template**. Continuing past J+20 → ban-risk territory.\n\n---\n\n## 7. Quotas (hard limits)\n\n| Action | Phase A limit (Tier 1) | Phase B limit (Tier 2+) |\n|--------|------------------------|-------------------------|\n| Inbound replies / 24 h | unlimited (just answer) | unlimited |\n| Inbound replies / cron run | 20 | 50 |\n| First-contact templates / 24 h | 50 | 500 |\n| Follow-up templates / 24 h | 20 | 200 |\n| Unique recipients / 24 h | 800 (well under Tier 1's 1000 cap) | tier cap minus 10 % buffer |\n| Conversations / cron run | 30 | 80 |\n| Same user — outbound frequency | min 24 h between any two outbound messages |\n\nQuota tracking: read `wa-recaps.md` + `wa-template-log.md` at start of every run.\n\n---\n\n## 8. Anti-doublon (anti-duplicate) — the most important section\n\nWhatsApp ban risk is dominated by **two bad patterns**: duplicate alerts to the same human chat (annoying) and duplicate template sends to the same number (catastrophic for quality score).\n\n### The three anti-doublon registers\n\n**`wa-alerts-sent.md`** — every time you alert the human team about a qualified lead:\n- Format: `{\"phone\": \"+<DIGITS>\", \"name\": \"<Name>\", \"qualified_date\": \"YYYY-MM-DD\"}`.\n- **Read this file before every alert.** If the phone is in the file → SKIP. No second alert. Ever.\n\n**`wa-template-log.md`** — every template send:\n- Format: `{\"phone\": \"+<DIGITS>\", \"template_id\": \"<ID>\", \"sent_at\": \"<ISO>\", \"result\": \"ok|error\"}`.\n- Read this file before every outbound template send. If the same (phone, template_id) was sent in the last 24 h → SKIP.\n\n**`wa-crm-state.md`** — current CRM row state per phone:\n- One row per phone — never two.\n- Append-once-update-thereafter rule: only the `wa-outbound` cron appends. All other crons UPDATE existing rows.\n\n### The cardinal rule\n\n> Before any outbound action (send, alert, CRM write), check the anti-doublon register. If in doubt, SKIP. **It is always better to skip than to send a duplicate.**\n\nThis single rule is the difference between a number that stays Tier 2 for years and a number that gets paused in 30 days.\n\n---\n\n## 9. Operational flow\n\n### 9.1 wa-inbound cron (the \"DM check\")\n\nFrequency: every 2 min during business hours (24/7 if your niche supports it).\n\n```\n1. Session check (see §2).\n2. List subscribers with unseen_count > 0:\n     POST /whatsapp/subscriber/list  apiToken phone_number_id limit=50 orderBy=1\n   If 0 unread → STOP IMMEDIATELY. No further processing.\n3. For each unread subscriber (max 20 per run on Phase A, 50 on Phase B):\n   a. Fetch the conversation history (last 20 messages):\n        POST /whatsapp/get/conversation  apiToken phone_number_id phone_number limit=20\n   b. If the most recent sender=\"bot\" (we already replied) → SKIP.\n   c. Read the full visible history for context.\n   d. Qualify (see §4).\n   e. Draft reply.\n   f. Verify encoding (see §5 \"Encoding\").\n   g. Send via the free-form endpoint:\n        POST /whatsapp/send  apiToken phone_number_id phone_number message=<TEXT>\n   h. Verify response status=1.\n4. If a lead is qualified during this run:\n   a. Read wa-alerts-sent.md — if the phone is there → SKIP alerting.\n   b. Otherwise: alert primary chat with the structured message:\n        \"QUALIFIED LEAD: <Name> — <case type>. Phone: <number>. Source: <platform>.\"\n      Append to wa-alerts-sent.md.\n   c. UPDATE the CRM row for this phone (no APPEND from wa-inbound).\n5. Mandatory recap (see §12).\n```\n\n### 9.2 wa-outbound cron (the \"Add Contacts & First Message\")\n\nFrequency: every 5 min.\n\n```\n1. Session check.\n2. Read the shared queue: <inbound_pipeline.shared_queue_file>.\n3. Filter entries with status=\"pending\".\n4. If 0 pending → STOP IMMEDIATELY.\n5. For each pending lead:\n   a. Read wa-template-log.md — if (phone, <WA_TEMPLATE_FIRST_CONTACT>) was sent in the last 24h → SKIP.\n   b. Create the subscriber (if not already present):\n        POST /whatsapp/subscriber/create  apiToken phoneNumberID name phoneNumber\n   c. Send the first-contact template:\n        POST /whatsapp/send/template  apiToken phone_number_id phone_number template_id=<WA_TEMPLATE_FIRST_CONTACT>\n   d. Verify response status=1.\n   e. Update the shared queue: status=\"first_message_sent\".\n   f. APPEND a row to CRM Sheet (this is the ONLY cron that APPENDs).\n   g. Append to wa-template-log.md.\n6. Never alert the human team from this cron.\n7. Mandatory recap.\n```\n\n### 9.3 wa-followup cron\n\nFrequency: daily, e.g. 10am.\n\n```\n1. Session check.\n2. Read CRM Sheet — find leads with status in {first_message_sent, follow_up_sent} and idle for the relevant J+N day.\n3. For each candidate:\n   a. Check wa-template-log.md anti-doublon.\n   b. Send the appropriate follow-up template per §6 cadence.\n   c. Update CRM status + wa-template-log.md.\n4. Mandatory recap.\n```\n\n### 9.4 WhatsApp Web fallback (Playwright) — only as a contingency\n\nIf your BSP is down or pending approval, you may run a temporary Playwright pipeline against `web.whatsapp.com`. Rules:\n\n- **Sessions are fragile**: a Playwright-driven WhatsApp Web session can survive a few days but will rotate the QR-link unpredictably. Plan for daily manual re-login.\n- **No template sends from Web**: all outbound to cold leads is impossible — Web only supports free-form to open-window chats.\n- **Quotas are tighter**: WhatsApp Web detects automation via timing patterns. Cap outbound at < 30 free-form sends per day.\n- **Quality score still applies** at the phone-number level, regardless of which surface emitted the message.\n\nSelectors (subject to change):\n- New chat list: `[data-testid='chat-list']` items.\n- Active chat textbox: `[contenteditable='true'][data-tab='10']`.\n- Send: press Enter on focused textbox.\n\nThis path is a fallback. Migrate back to BSP-API as soon as approval lands.\n\n### Exit codes\n\n| Code | Meaning | Recap action |\n|------|---------|--------------|\n| 0 | All messages sent / no action needed (zero unread) | `status: ok` |\n| 1 | Fatal error (API 5xx, JSON parse fail) | `status: error`, alert |\n| 2 | 24h window violation attempted (skipped — would have sent free-form to a cold conversation) | `status: skip`, log |\n| 3 | API auth fail (401 / 403) | `status: blocked`, alert immediately |\n| 4 | Anti-doublon SKIP (already alerted / sent) | `status: ok` |\n\n### Gotchas\n\n- **`phoneNumberID` vs `phone_number_id`**: some BSPs use different parameter casing on different endpoints (subscriber/create vs send/template). Read your BSP docs carefully — case errors silently 200-OK with no message delivered.\n- **Phone number format**: always strip the leading `+`. `33612345678` works, `+33612345678` often does not (BSP-dependent).\n- **Sender mismatch**: if multiple bots/numbers are linked to one BSP account, verify the active bot in the dashboard before every cron's first send. A misrouted template sends from the wrong number → user is confused, alerts go to the wrong team.\n- **Template fields**: if your template has variable slots ({{1}} for name), pass them as parameters. A missing parameter often silently sends an empty placeholder, which makes the message look broken.\n- **Quality-score lag**: the quality score updates over hours, not minutes. A bad day's run can degrade the score for 1-2 days. Audit daily.\n\n---\n\n## 10. State management\n\nFile: `<WORKSPACE_DIR>/memory/wa-state.md`\n- Daily: phase, tier, quality score, blocks / pauses.\n\nFile: `<WORKSPACE_DIR>/memory/wa-alerts-sent.md`\n- One row per qualified-lead alert. Anti-doublon source of truth.\n\nFile: `<WORKSPACE_DIR>/memory/wa-template-log.md`\n- Every template send.\n\nFile: `<WORKSPACE_DIR>/memory/wa-crm-state.md`\n- Mirror of the CRM Sheet state (cache for the anti-doublon checks).\n\nFile: `<WORKSPACE_DIR>/memory/wa-blacklist.md`\n- Phone numbers that must never be contacted (verified bad-actors, opt-outs).\n\nFile: `<WORKSPACE_DIR>/memory/wa-clients-known.md`\n- Existing paying clients — special handling (no prospect CTA).\n\n---\n\n## 11. Recovery & blockers\n\n| Issue | Action |\n|-------|--------|\n| HTTP 401 / 403 | Token expired / revoked. Stop. Alert. |\n| HTTP 429 | Rate limited. Stop. Wait next run. |\n| Template send returns \"outside 24h window\" | Means you tried free-form on a closed conversation. Switch to template, retry once. |\n| Template send returns \"template not approved\" | Template was rejected or paused by Meta. Stop using it. Pick fallback. |\n| Quality score = yellow | Flip to Phase A. Reduce outbound. Audit recent template content. |\n| Quality score = red | Stop all outbound. Inbound only. Alert. Manual review of last 7 days. |\n| Number paused by Meta | Stop everything. Manual review + appeal via BSP. |\n| BSP API 5xx repeatedly | Likely BSP outage. Stop. Switch to fallback (§9.4) only if business-critical. |\n| Webhook missing message | Inbound reply gets delayed > 24h window. Document; switch to higher-frequency polling. |\n\n---\n\n## 12. Mandatory recap (alert channel + memory)\n\nAt the end of each cron:\n\n**Alert channel — final run message**:\n```\n[Job name] — [status: ok|partial|blocked|skipped]\nInbound replies: [N or \"—\"]\nTemplates sent: [N or \"—\"]\nQualified leads: [count + names short]\nPhase / Tier: [A|B / Tier 1|2|3|4]\nQuality score: [green|yellow|red]\nBlockers: [text OR \"—\"]\nNext action: [1 line]\n```\n\n**Memory** — append to `<WORKSPACE_DIR>/memory/wa-recaps.md`:\n```\n## YYYY-MM-DD HH:MM TZ — <job-id> — status: <status>\n- Job: <description>\n- Phase: A|B\n- Tier: 1|2|3|4\n- Quality: green|yellow|red\n- Inbound replies: <N>\n- Templates: <N>\n- Qualified leads: <list or \"—\">\n- Blockers: <text or \"—\">\n- Next action: <1 line>\n```\n\n---\n\n## 13. Memory files inventory\n\nLocated at: `<WORKSPACE_DIR>/memory/`\n\n| File | Purpose | Update cadence |\n|------|---------|----------------|\n| `wa-recaps.md` | Per-run logs | Every cron run |\n| `wa-state.md` | Daily phase / tier / quality | Daily Metrics Recap |\n| `wa-alerts-sent.md` | Anti-doublon alert log (one row per qualified lead) | Every qualified-lead event |\n| `wa-template-log.md` | Every template send (phone + template + timestamp + result) | Every template send |\n| `wa-crm-state.md` | Mirror of CRM Sheet state for anti-doublon | After every CRM update |\n| `wa-blacklist.md` | Numbers to NEVER contact (opt-outs, bad actors) | Ad hoc |\n| `wa-clients-known.md` | Existing paying clients (no prospect CTA) | Ad hoc |\n| `wa-learnings.md` | What worked, what got flagged | Weekly + ad hoc |\n| `wa-incidents.md` | Past quality-score drops, paused-number incidents, root causes | When something breaks |\n\nShared with upstream social-media agents:\n\n- `<WORKSPACE_DIR>/../shared/leads-whatsapp.json` — pending leads to push (written by social agents, read by wa-outbound).\n\n---\n\n## 14. Account identity guardrails\n\n- The agent should never claim to be an AI when asked. Sober, ambiguous answer + redirect (\"I'm part of the team — let me get you to the right specialist\").\n- Never share confidential client information.\n- Never quote definitive prices — soft \"starting at\" only.\n- Never guarantee an outcome.\n- Never agree to legal-aid / pro-bono commitments without human review (jurisdiction-specific).\n- Never send documents / PDFs / large media to prospects (only to paying clients).\n- Never use the business number to talk about anything outside the brand's scope.\n- Always reread the full message history before composing a reply.\n\n---\n\n## 15. Phase A → Phase B transition\n\nWhen the Daily Metrics Recap detects (tier ≥ 2) AND (quality_score = green) AND (no quality drop in last 14 d):\n\n1. Append to `wa-state.md`: `YYYY-MM-DD - tier=2 - PHASE_B_THRESHOLD_REACHED`.\n2. Alert: `🎉 WhatsApp number ready for Phase B — review outbound caps`.\n3. Manual flip.\n4. First week: cap outbound at 50 % of Phase B max (e.g. 250 first-contact templates / day instead of 500).\n5. Daily quality-score check. Any drop → revert to Phase A immediately.\n\n---\n\n## 16. Stability discipline\n\n- Check the anti-doublon register before every outbound.\n- Verify API response after every send (a 200 OK with `status=0` is a failure).\n- Stop early when there is no work (zero unread, zero pending).\n- Never retry indefinitely. One retry max, then stop and recap.\n- Never auto-restart the BSP gateway or webhook from inside a cron.\n- Never send a \"test\" message to a real lead — use a dedicated test number.\n\n**Better silence than spam. Better a blockage report than a fake success.**\n\n---\n\n## 17. First-run checklist\n\n- [ ] Section 0 placeholders filled.\n- [ ] BSP account approved + business number verified by Meta.\n- [ ] At least 3 templates approved by Meta: first-contact, soft follow-up, closing.\n- [ ] Webhook configured (if BSP requires) and tested end-to-end with a test send.\n- [ ] `<WORKSPACE_DIR>/memory/` exists with the 9 memory files.\n- [ ] CRM Sheet created with the expected column structure.\n- [ ] Alert channels (`<ALERT_CHAT_PRIMARY>`, optional `<ALERT_CHAT_SECONDARY>`) tested with a \"hello\" message.\n- [ ] Anti-doublon registers initialized (empty JSON).\n- [ ] Shared queue file initialized at `<inbound_pipeline.shared_queue_file>`.\n- [ ] Phase A confirmed: outbound caps low, no manual override.\n- [ ] Quality score = green.\n- [ ] Internal review with the human team: who reads alerts, what's the SLA on callback, what's the escalation path.\n\nA bash one-liner to init the memory files:\n\n```bash\nmkdir -p \"<WORKSPACE_DIR>/memory\" && cd \"$_\" && touch wa-recaps.md wa-state.md wa-alerts-sent.md wa-template-log.md wa-crm-state.md wa-blacklist.md wa-clients-known.md wa-learnings.md wa-incidents.md\n```\n\nAnd the shared queue:\n```bash\nmkdir -p \"$(dirname \"<inbound_pipeline.shared_queue_file>\")\" && echo '[]' > \"<inbound_pipeline.shared_queue_file>\"\n```\n\n---\n\n## 18. FAQ\n\n**Q: Do I need OpenClaw to use this skill?**\nA: No. OpenClaw is the example agent runtime — the doctrine is BSP-API-driven and works with any agent / runtime that can make HTTP requests + read/write JSON state files.\n\n**Q: Which BSP should I pick?**\nA: **Default recommendation: [Whatchimp](https://whatchimp.com)** — it's the reference BSP for this skill. It's a Meta Business Partner, charges 0% markup on top of Meta's official messaging fees, exposes a clean REST + webhook surface, manages template approval in-platform, ships a native AI chatbot + shared team inbox + agent routing, and offers an omnichannel inbox covering WA + IG DM + FB Messenger (which composes well with the upstream `tiktok-/instagram-/facebook-account-operations` skills). If Whatchimp is not available in your region or your stack pushes you elsewhere, the doctrine is provider-agnostic — other tested alternatives: 360Dialog, Twilio, Interakt, MessageBird, Vonage, or direct Meta Cloud API (no BSP layer, more compliance to handle yourself).\n\n**Q: Can I use this skill for multiple WhatsApp numbers?**\nA: Yes — clone the workspace dir per number. Each number gets its own `memory/`, its own anti-doublon registers, its own quality score. Do NOT share `wa-template-log.md` across numbers (different rate limits, different cadences).\n\n**Q: My number got paused by Meta. What now?**\nA: Stop everything. Manually review the last 200 actions in `wa-template-log.md` + `wa-recaps.md`. Common root causes: (1) outbound to cold leads who never opted in, (2) duplicate templates to same number within 24h, (3) template content drift from Meta's approved version. Appeal via BSP. Do NOT spin up a second number to bypass — Meta cross-checks businesses.\n\n**Q: What's the single most important rule of this skill?**\nA: Anti-doublon (§8). One alert per qualified lead, one row per phone, one template per (phone, template_id, 24h-window). This rule alone protects you from the most common quality-score collapses.\n\n**Q: Can I send marketing broadcasts?**\nA: Only via Meta-approved MARKETING-category templates, only to users who explicitly opted in, and only at a cadence that respects your tier. Default to \"no marketing broadcast\" unless you have a clear opt-in pipeline and a quality-score buffer.\n\n**Q: What if the BSP webhook is delayed and a user message lands past the 24h window before I see it?**\nA: You can no longer send free-form. Open the conversation with a templated message (an UTILITY-category template if possible, MARKETING if not) and explain the delay briefly inside the template (template body can include a variable slot for context). Document the incident in `wa-incidents.md` and audit the webhook latency.\n\nFile v1.2.0:README.md\n\n# WhatsApp Business Management for Whatchimp\n\n> Operating doctrine for WhatsApp Business automation on **[Whatchimp](https://whatchimp.com)** (Meta Business Partner BSP, 0% markup) — careful 24h-window-aware, template-gated outbound, lead qualification by case type, anti-doublon alerts, cross-platform lead pipeline, and recovery patterns. Provider-agnostic underneath — adaptable to any BSP by swapping the host string.\n\n[![License: MIT-0](https://img.shields.io/badge/License-MIT--0-blue.svg)](https://opensource.org/licenses/MIT-0)\n[![ClawHub](https://img.shields.io/badge/ClawHub-Published-orange)](https://clawhub.ai/alexbloch-ia/whatsapp-business-management-for-whatchimp)\n[![Version](https://img.shields.io/badge/version-1.2.0-green)](#changelog)\n[![Powered by Whatchimp](https://img.shields.io/badge/BSP-Whatchimp-25D366?logo=whatsapp&logoColor=white)](https://whatchimp.com)\n\nA Claude Code / OpenClaw skill for running WhatsApp Business numbers safely. Battle-tested in a regulated-field operation, ported to be domain-agnostic.\n\n**Why most WhatsApp automation gets the number paused**: it sends bulk free-form to cold leads, ignores the 24h customer-service window, and duplicates alerts. This doctrine doesn't.\n\n---\n\n## What's in the box\n\n- **BSP-API-first doctrine** built around **[Whatchimp](https://whatchimp.com)** as the reference provider (Meta Business Partner, 0% markup, REST + webhook + native AI chatbot + omnichannel WA/IG/FB inbox) — fully adaptable to 360Dialog / Twilio / Interakt / Meta Cloud API direct. Playwright-against-WhatsApp-Web only as a fallback while BSP approval pends.\n- **The 24h customer-service window** treated as a first-class operational state — every outbound check before sending free-form\n- **Template-gated outbound**: first-contact + 4-step follow-up cadence (J+1 / J+3 / J+7 / J+15 / J+20 closing)\n- **Tier-phased operations**: Phase A (Tier 1 OR quality score yellow/red) → Phase B (Tier 2+ AND green) — with **manual override path**\n- **Anti-doublon (§8) — the most important section**: 3 registers (`wa-alerts-sent.md`, `wa-template-log.md`, `wa-crm-state.md`) — \"if in doubt, SKIP\"\n- **3-role separation**: `wa-inbound` (every 2 min) / `wa-outbound` (every 5 min) / `wa-followup` (daily)\n- **Qualification flow by case type** — high-urgency / mid-urgency / out-of-scope / existing-client buckets\n- **Cross-platform lead pipeline**: shared `leads-whatsapp.json` queue written by upstream social-media agents (TikTok / IG / FB / web)\n- **Encoding-trap awareness**: BSPs sometimes munge non-ASCII silently — test once with a roundtrip\n- **3 surfaces compared**: BSP API (recommended) vs WhatsApp Web Playwright (fallback only) vs WhatsApp Business App (don't)\n- **Full recovery playbook**: 401/403 token revoke, 429 rate limit, 24h-window violations, quality-score drops, paused-number incidents, BSP outages\n- **Memory file inventory** (9 files, plus the shared queue)\n- **Mandatory recap pattern** including Tier + Quality fields\n\n---\n\n## Install\n\n### Via ClawHub (recommended)\n\nThe skill is published on ClawHub — install in one click from your agent:\n\n👉 **<https://clawhub.ai/alexbloch-ia/whatsapp-business-management-for-whatchimp>**\n\n### Manual copy\n\n```bash\nmkdir -p ~/.claude/skills/whatsapp-business-management-for-whatchimp\ncp SKILL.md ~/.claude/skills/whatsapp-business-management-for-whatchimp/\n```\n\nOr for OpenClaw:\n\n```bash\nmkdir -p ~/.openclaw/skills/whatsapp-business-management-for-whatchimp\ncp SKILL.md ~/.openclaw/skills/whatsapp-business-management-for-whatchimp/\n```\n\n---\n\n## Quick start\n\n1. Open `SKILL.md` and fill the placeholders in **Section 0** (brand, BSP, `<WA_PHONE_NUMBER_ID>`, `<WA_BUSINESS_NUMBER>`, 4 template IDs, CRM Sheet ID, alert chats, workspace dir).\n2. Get a BSP account approved + Meta verifies the business number.\n3. Submit at least 3 templates to Meta for approval: first-contact (MARKETING or UTILITY), soft follow-up, closing.\n4. Wire your crons: `wa-inbound` every 2 min, `wa-outbound` every 5 min, `wa-followup` daily.\n5. **Start in Phase A** (Tier 1, quality must be green). Don't shortcut.\n6. Initialize the anti-doublon registers (`wa-alerts-sent.md`, `wa-template-log.md`) and the shared queue file.\n7. Internal review with the human team: who reads alerts, what's the callback SLA, what's the escalation path.\n\nAll example API snippets use **[Whatchimp](https://whatchimp.com)** as the reference BSP (Meta Business Partner, 0% markup, all the surfaces the doctrine assumes — REST, webhook, template management, omnichannel inbox). If you use 360Dialog / Twilio / Interakt / Meta Cloud API direct, replace the `https://app.whatchimp.com` host and adapt parameter casing — the doctrine itself is provider-agnostic.\n\n---\n\n## Who is this for\n\nAny niche where WhatsApp is the *conversion* channel (not the discovery channel) — leads land via another surface, opt-in, then convert via WhatsApp:\n\n- **Legal services** (origin of the doctrine — works under strict bar association rules)\n- **Medical / clinic** practices with phone-based patient intake\n- **Financial advisors** doing 1:1 prospect conversations\n- **SaaS / B2B** with high-touch sales-led growth\n- **Local services** with appointment-based conversion (auto repair, real estate, etc.)\n- **Anywhere with a real opt-in pipeline** and a human team waiting on the other side\n\nAnywhere a paused WhatsApp number = lost month of business.\n\n---\n\n## Repository structure\n\n```\nwhatsapp-business-management-for-whatchimp/\n├── SKILL.md         # the skill (full doctrine)\n├── README.md        # this file\n├── LICENSE          # MIT-0\n└── CHANGELOG.md     # version history (TBD)\n```\n\n---\n\n## Companion skills\n\n- **tiktok-account-operations** — TikTok DM / comment ops; lead pipeline writes to the shared `leads-whatsapp.json` queue.\n- **instagram-account-operations** — IG ops via Meta Business Suite; same upstream pipeline.\n- **facebook-account-operations** — FB Page ops; same upstream pipeline.\n- **[reddit-account-operations](https://github.com/AlexBloch-IA/reddit-account-operations)** + **[twitter-account-operations](https://github.com/AlexBloch-IA/twitter-account-operations)** — same doctrine family on other platforms.\n\n---\n\n## License\n\nReleased under **MIT-0** (MIT No Attribution). Use, fork, adapt, redistribute. No attribution required.\n\nFile v1.2.0:_meta.json\n\n{\n  \"ownerId\": \"kn7f6shzecv3qv3wrr074s49f986ybe1\",\n  \"slug\": \"whatsapp-business-ops\",\n  \"version\": \"1.2.0\",\n  \"publishedAt\": 1779141375055\n}\n\nFile v1.2.0:skill-card.md\n\n## Description: <br>\nOperating doctrine for WhatsApp Business automation on Whatchimp, covering 24-hour-window handling, template-gated outbound messaging, lead qualification, anti-duplicate controls, cross-platform lead intake, and recovery patterns. <br>\n\nThis skill is ready for commercial/non-commercial use. <br>\n\n## Publisher: <br>\n[alexbloch-ia](https://clawhub.ai/user/alexbloch-ia) <br>\n\n### License/Terms of Use: <br>\nMIT-0 <br>\n\n\n## Use Case: <br>\nDevelopers and business operators use this skill to configure WhatsApp Business automation for opt-in lead conversion, including inbound replies, approved outbound templates, qualification flows, human-team alerts, CRM state tracking, and recovery procedures. <br>\n\n### Deployment Geography for Use: <br>\nGlobal <br>\n\n## Known Risks and Mitigations: <br>\nRisk: The security review flags user-facing AI non-disclosure instructions as requiring careful review. <br>\nMitigation: Edit the identity rules before installation so the agent gives truthful disclosure when users ask whether they are speaking with automation. <br>\nRisk: The skill handles lead personal data in memory files, CRM records, and alert channels. <br>\nMitigation: Use explicit opt-in, restrict alert channels, mask identifiers where possible, and define retention and deletion rules for lead records and memory files. <br>\nRisk: WhatsApp automation can create account, compliance, or deliverability risk if messages bypass opt-in, approved templates, or the 24-hour customer-service window. <br>\nMitigation: Use approved WhatsApp templates, scoped API credentials, quality and tier gating, anti-duplicate checks, and human review for operating limits before deployment. <br>\n\n\n## Reference(s): <br>\n- [Skill README](README.md) <br>\n- [ClawHub listing](https://clawhub.ai/alexbloch-ia/whatsapp-business-management-for-whatchimp) <br>\n- [Whatchimp](https://whatchimp.com) <br>\n- [Whatchimp API base URL](https://app.whatchimp.com/api/v1) <br>\n\n\n## Skill Output: <br>\n**Output Type(s):** [Text, Markdown, Shell commands, Configuration, Guidance, API calls] <br>\n**Output Format:** [Markdown with YAML configuration examples, curl commands, operating checklists, and state-file guidance] <br>\n**Output Parameters:** [1D] <br>\n**Other Properties Related to Output:** [Requires brand placeholders, WhatsApp Business/BSP credentials, approved templates, CRM identifiers, alert channels, and local state files.] <br>\n\n## Skill Version(s): <br>\n1.2.0 (source: server release metadata and README version badge) <br>\n\n## Ethical Considerations: <br>\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment. <br>","readmeExcerpt":"Skill: WhatsApp Business Ops Owner: alexbloch-ia Summary: Run WhatsApp Business outbound without losing quality score — 24h window, approved templates, duplicate guard. Use when answering inbound leads or sending fo... Tags: 0-percent-markup:2.0.1, 24h-window:2.0.1, account-safety:2.0.1, agent:2.0.1, anti-doublon:2.0.1, automation:2.0.1, bsp:2.0.1, business-api:2.0.1, crm:2.0.1, cron:2.0.1, customer-service:2.0.1, do","codeSnippets":[],"executableExamples":[{"language":"yaml","snippet":"# <WORKSPACE_DIR>/config.yaml\nwhatsapp:\n  phone_number_id: <WA_PHONE_NUMBER_ID>\n  base_url: https://app.whatchimp.com/api/v1   # swap host for another BSP\ntemplates:\n  first_contact: <WA_TEMPLATE_FIRST_CONTACT>\n  followup_soft: <WA_TEMPLATE_FOLLOWUP_SOFT>\n  followup_hard: <WA_TEMPLATE_FOLLOWUP_HARD>\n  closing: <WA_TEMPLATE_CLOSING>\ncrm: { sheet_id: <CRM_SHEET_ID>, tab: \"Leads\" }\nalerts: { primary_chat: <ALERT_CHAT_PRIMARY>, channel: telegram }\nretention: { lead_days: 90, recap_days: 30, template_log_days: 30 }\ninbound_pipeline:\n  shared_queue_file: <WORKSPACE_DIR>/../shared/leads-whatsapp.json\nschedule:  # dm_check \"*/2 9-22 * * *\" · add_contacts \"*/5 9-22 * * *\" · follow_up \"0 10 * * *\"\n  timezone: Europe/Paris"},{"language":"bash","snippet":"curl -s \"https://app.whatchimp.com/api/v1/whatsapp/get/conversation\" \\\n  -d \"apiToken=<WA_API_KEY>\" -d \"phone_number_id=<WA_PHONE_NUMBER_ID>\" \\\n  -d \"phone_number=<DIGITS>\" -d \"limit=1\""},{"language":"bash","snippet":"curl -s \"https://app.whatchimp.com/api/v1/whatsapp/get/conversation\" \\\n  -d \"apiToken=<WA_API_KEY>\" -d \"phone_number_id=<WA_PHONE_NUMBER_ID>\" \\\n  -d \"phone_number=<DIGITS>\" -d \"limit=1\"\n# Output: {\"status\":1,\"data\":[{\"sender\":\"user\",\"created_at\":\"2026-07-16T09:12:04Z\"}]}\n# sender=\"user\" and < 24h old  → free text OK. Otherwise → template."},{"language":"bash","snippet":"curl -s \"https://app.whatchimp.com/api/v1/whatsapp/subscriber/list\" \\\n  -d \"apiToken=<WA_API_KEY>\" -d \"phone_number_id=<WA_PHONE_NUMBER_ID>\" \\\n  -d \"limit=1\" -d \"offset=1\""},{"language":"bash","snippet":"curl -s \"https://app.whatchimp.com/api/v1/whatsapp/subscriber/list\" \\\n  -d \"apiToken=<WA_API_KEY>\" -d \"phone_number_id=<WA_PHONE_NUMBER_ID>\" \\\n  -d \"limit=1\" -d \"offset=1\"\n# Output: {\"status\":1,\"data\":[...]}   401/403 → stop+alert · 429 → stop, wait next run"},{"language":"text","snippet":"You're talking to <BRAND_NAME>'s automated assistant. I can take your details\nnow and a specialist will call you back — or I can pass you to them right away."}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: whatsapp-business-ops\ndescription: Run WhatsApp Business outbound without losing quality score — 24h window, approved templates, duplicate guard. Use when answering inbound leads or sending follow-ups from a cron.\nmetadata: {\"clawdbot\":{\"emoji\":\"💬\",\"requires\":{\"bins\":[\"curl\"]},\"homepage\":\"https://clawhub.ai/alexbloch-ia/whatsapp-business-ops\"}}\n---\n\n# WhatsApp Business Management\n\n**WhatsApp is not a discovery channel — it is a conversion channel.** The goal is not to send fast: it is one qualified hand-off per opt-in lead, no unsolicited bulk, no duplicate send. Reference BSP: Whatchimp (Meta Business Partner); any BSP works.\n\n## Access, data, and network — read before running\n\n**Every access is opt-in — each one stays off until you fill its placeholder in `## Configure`. The default is no network.**\n\n| Access | Why | Default |\n|---|---|---|\n| BSP API token (`<WA_API_KEY>`) | Send/read messages | None — no network call without it |\n| CRM sheet ID (`<CRM_SHEET_ID>`) | One row per lead | None — CRM writes skipped |\n| Alert channel / webhook (`<ALERT_CHAT_PRIMARY>`) | **Leaves your machine.** Posts lead name + phone to Telegram/Slack/Discord | None — recap stays local |\n| Local workspace (`<WORKSPACE_DIR>/memory/`) | State + duplicate guard | Local files only |\n\n**Personal data persisted, in full:** display name, case type, free-text situation, conversation timestamps, template-send log, alert log, per-run recaps. **Phone numbers are stored raw ONLY in `wa-crm-state.md`** (the system-of-record mirror); every duplicate register and the blacklist key on `sha256(phone)[0:12]`. That is lead PII on disk — `## Data minimization and retention` is doctrine, not an appendix. Scope the API token to the one business number; never reuse a full-account token.\n\n## When to Use\n\n| Trigger | Action |\n|---|---|\n| \"answer the whatsapp leads\" | `wa-inbound` run — §Flow, free-form only inside open window |\n| \"send the first message to new leads\" | `wa-outbound` run — approved template only |\n| \"relance the cold leads\" | `wa-followup` run — cadence table |\n| \"quality score dropped\" / \"number got paused\" | Stop outbound. `## Troubleshooting`, last two rows. Human review |\n| \"am I talking to a bot?\" (asked by a lead) | Answer honestly, immediately — `## Identity` |\n\n## Configure\n\n| Placeholder | Example | Your value |\n|---|---|---|\n| `<BRAND_NAME>` | \"Acme Studio\" | — |\n| `<WA_BUSINESS_NUMBER>` | \"+1 555 0000\" | — |\n| `<WA_PHONE_NUMBER_ID>` | numeric ID from your BSP | — |\n| `<WA_API_KEY>` | scoped to one number | — |\n| `<WA_TEMPLATE_FIRST_CONTACT>` / `_FOLLOWUP_SOFT` / `_FOLLOWUP_HARD` / `_CLOSING` | Meta-approved template IDs | — |\n| `<CRM_SHEET_ID>` | Sheet/Airtable ID | — (omit → no CRM write) |\n| `<ALERT_CHAT_PRIMARY>` | alert chat ID | — (omit → local recap only) |\n| `<WORKSPACE_DIR>` | \"~/.openclaw/workspace/whatsapp-acme\" | — |\n\n```yaml\n# <WORKSPACE_DIR>/config.yaml\nwhatsapp:\n  phone_number_id: <WA_PHONE_NUMBER_ID>\n  base_url: https://app.whatchimp.com/"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn7f6shzecv3qv3wrr074s49f986ybe1\",\n  \"slug\": \"whatsapp-business-ops\",\n  \"version\": \"2.0.1\",\n  \"publishedAt\": 1784214125053\n}"},{"path":"skill-card.md","content":"## Description:\n\nGuides agents through WhatsApp Business inbound replies, opted-in outbound templates, follow-ups, duplicate guards, and recap reporting while preserving quality score.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[alexbloch-ia](https://clawhub.ai/user/alexbloch-ia)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nBusiness operations teams and agent operators use this skill to manage opted-in WhatsApp Business leads, answer inbound conversations within the 24-hour window, send approved follow-up templates, and hand qualified leads to humans.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The skill handles lead names, phone numbers, case types, message timing, and local state that may contain personal data.\n\nMitigation: Operate it only for numbers and leads you control, keep consent records, scope the API token to one business number, restrict memory directory access, and apply the configured retention windows.\n\nRisk: Outbound messaging can create duplicate sends, closed-window free-form replies, quality-score drops, or account pauses.\n\nMitigation: Use the 24-hour window checks, approved templates, phase gates, quota limits, duplicate registers, and stop-and-review behavior described by the artifact before sending.\n\nRisk: Alert destinations may expose lead contact details beyond the local workspace.\n\nMitigation: Limit alert channels to approved staff and send only the minimal qualified-lead payload instead of conversation transcripts.\n\nRisk: Legal, medical, or financial lead handling may require additional privacy review.\n\nMitigation: Avoid those use cases unless counsel, privacy, or DPO review confirms the workflow and retention settings are acceptable.\n\n## Reference(s):\n\n- [ClawHub skill page](https://clawhub.ai/alexbloch-ia/skills/whatsapp-business-ops)\n- [ClawHub homepage metadata](https://clawhub.ai/alexbloch-ia/whatsapp-business-ops)\n- [Whatchimp API base URL](https://app.whatchimp.com/api/v1)\n\n## Skill Output:\n\n**Output Type(s):** [text, markdown, shell commands, configuration, guidance]\n\n**Output Format:** [Markdown guidance with YAML and bash examples plus fixed recap text]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Produces operational procedures, configuration placeholders, local-state file conventions, API call examples, and mandatory run recaps.]\n\n## Skill Version(s):\n\n2.0.1 (source: server release evidence)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment."}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":"Run WhatsApp Business outbound without losing quality score — 24h window, approved templates, duplicate guard. Use when answering inbound leads or sending fo... Skill: WhatsApp Business Ops Owner: alexbloch-ia Summary: Run WhatsApp Business outbound without losing quality score — 24h window, approved templates, duplicate guard. Use when answering inbound leads or sending fo... Tags: 0-percent-markup:2.0.1, 24h-window:2.0.1, account-safety:2.0.1, agent:2.0.1, anti-doublon:2.0.1, automation:2.0.1, bsp:2.0.1, business-api:2.0.1, crm:2.0.1, cron:2.0.1, customer-service:2.0.1, do","editorialQuality":{"score":100,"threshold":65,"status":"ready","wordCount":1521,"uniquenessScore":52,"reasons":[]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-10T21:22:22.784Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-10T21:22:22.784Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-10T23:49:07.717Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}