@kapso/openclaw-whatsapp when an OpenClaw agent needs to send and receive WhatsApp messages through Kapso.
Use @kapso/whatsapp-cloud-api directly when you are building your own app and do not need OpenClaw channel routing.
Installation
Requires OpenClaw >= 2026.5.27.plugins.allow already has entries, keep them and add kapso-whatsapp.
OpenClaw resolves the plugin from ClawHub and installs runtime dependencies, including @kapso/whatsapp-cloud-api and @kapso/cli. No separate npm install is needed.
The Kapso CLI is bundled with the plugin:
Setup
Requires:| Requirement | Use |
|---|---|
| Kapso API key | Sends messages, resolves numbers, and registers webhooks. |
| WhatsApp sender number | The Kapso-connected number your agent sends from. |
| Public HTTPS gateway URL | Receives Kapso webhooks. |
| Webhook secret | Verifies inbound webhook signatures. |
phone_number_id, use --phone-number-id:
| Flag | Use |
|---|---|
--default-to | Default outbound WhatsApp recipient. |
--allow-from | Comma-separated inbound allowlist. |
--dm-security | allowlist, open, or disabled. |
--dry-run | Print actions without writing config or registering webhooks. |
--json | Print machine-readable setup output. |
--write-config to print the openclaw config set commands without applying them.
Agent setup
The plugin ships an OpenClaw skill namedkapso-whatsapp-setup.
Check that OpenClaw sees it:
openclaw tui and send:
openclaw kapso-whatsapp cli login in your terminal. It should not run interactive login for you.
Public gateway
Kapso Cloud must reach your OpenClaw webhook over the public internet. A private tailnet URL is not enough. For Tailscale, use Funnel:--password-file instead of passing a password directly in process arguments.
The Kapso webhook URL should use your Funnel hostname plus /kapso/webhook:
Configure manually
phoneNumberId and defaultTo values, but JSON strings avoid precision loss for large IDs.
Optional settings:
+. Current plugin versions compare both forms as the same sender. Including both is harmless for older installs or raw config edits.
You can also use environment variables:
Kapso webhook
Create a phone-number scoped Kapso webhook, not a project webhook.| Setting | Value |
|---|---|
| Method | POST |
| URL | https://your-openclaw-host.example.com/kapso/webhook |
| Events | whatsapp.message.received |
| Secret | Same value as channels["kapso-whatsapp"].webhookSecret or KAPSO_WEBHOOK_SECRET |
| Payload version | v2 recommended |
--register-webhook.
You can also run the bundled Kapso CLI through OpenClaw:
Channel targets
The plugin accepts WhatsApp phone-number targets with these prefixes:Diagnostics
Check config and webhook registration:Media
Images, videos, and documents can be forwarded when Kapso includes a downloadable media URL, such asmediaUrl, media_data.url, media_data.downloadUrl, or a direct media link or url.
The selected OpenClaw model/runtime must support that media type.
If Kapso sends only a media ID and no URL, the plugin records that media exists but cannot pass the file bytes to the model. Logs warn about id but no URL.
Voice notes and audio messages need a transcription provider. Without one, the agent may only receive audio metadata. Hosted options include OpenAI gpt-4o-transcribe, gpt-4o-mini-transcribe, or whisper-1. Self-hosted ASR can work if your OpenClaw deployment exposes a compatible transcription provider.
Troubleshooting
Config values rejected as “must be string”
Use strict JSON strings:Webhook returns 401
The Kapso webhook secret andchannels["kapso-whatsapp"].webhookSecret do not match, or the request is missing the Kapso signature header.
Webhook is reachable but no messages arrive
Confirm the webhook is phone-number scoped and subscribed towhatsapp.message.received. Project webhooks do not receive WhatsApp message events.
Webhook dispatches but no agent session or reply
CheckallowFrom. Kapso commonly sends inbound sender IDs without a leading +, even if your allowlist was configured with E.164 values.
Current plugin versions compare those forms as the same sender. On older installs, include both variants and restart the gateway:
Images sometimes work and sometimes do not
Check logs formedia=image/url=yes. If logs say url=no or warn that the event had an ID but no URL, the model did not receive the actual image bytes.
Source
GitHub repository
Source code, setup skill, and issue tracker for
@kapso/openclaw-whatsapp.
