Channels
Waxum Openclaw
OpenClaw channel plugin backed by waxum โ real WhatsApp buttons/lists/CTA-url
Install
openclaw plugins install @imtaqin/openclaw-waxum
Configuration Example
{
"channels": {
"waxum": {
"baseUrl": "http://127.0.0.1:3451",
"token": "<waxum bearer token>",
"sessionId": "<waxum session id>",
"dmPolicy": "allowlist",
"allowFrom": ["6281234567890"]
}
}
}
README
# waxum-openclaw-plugin
An [OpenClaw](https://github.com/openclaw/openclaw) channel plugin backed by
[waxum](https://github.com/imtaqin/waxum) โ self-hosted WhatsApp with real
interactive messages (buttons, list menus, CTA-url) instead of OpenClaw's
default plain-text-only bridges.
Structured as a native OpenClaw channel plugin per
[docs.openclaw.ai/plugins/sdk-channel-plugins](https://docs.openclaw.ai/plugins/sdk-channel-plugins):
`createChatChannelPlugin` + `defineChannelMessageAdapter` for outbound,
`defineChannelPluginEntry` for registration, `defineSetupPluginEntry` for
the `openclaw setup` wizard.
```
waxum-openclaw-plugin/
โโโ package.json # openclaw.channel manifest block
โโโ openclaw.plugin.json # config schema (baseUrl/token/sessionId/dmPolicy)
โโโ index.ts # defineChannelPluginEntry
โโโ setup-entry.ts # `openclaw setup` wizard step, validates the session live
โโโ src/
โโโ channel.ts # createChatChannelPlugin: account resolution, DM security, outbound
โโโ client.ts # waxum HTTP + SSE client โ retries, backoff, typed errors
โโโ client.test.ts # unit tests (no openclaw/network dependency)
โโโ inbound.ts # SSE event tail -> dispatchInbound bridge
```
## Install
```bash
openclaw plugins install @imtaqin/openclaw-waxum
# or, from a local checkout:
openclaw plugins install ./waxum-openclaw-plugin
```
Then `openclaw setup` and pick the `waxum` channel โ it prompts for
`baseUrl` / `token` / `sessionId` and verifies the waxum session is
actually connected before writing config. The waxum session itself must
already be paired (QR/pair code done once via waxum directly); this plugin
never does first-time pairing.
Or configure `openclaw.json` directly:
```json
{
"channels": {
"waxum": {
"baseUrl": "http://127.0.0.1:3451",
"token": "<waxum bearer token>",
"sessionId": "<waxum session id>",
"dmPolicy": "allowlist",
"allowFrom": ["6281234567890"]
}
}
}
```
## Sending interactive messages
Core's shared `message` tool only does plain text. This plugin's
`extraActions` add real WhatsApp interactivity, callable from the agent's
tool loop:
```ts
await channel.actions.waxum.sendButtons({
account, to: "[email protected]",
body: "Pick one", buttons: [{ id: "yes", text: "Yes" }, { id: "no", text: "No" }],
});
await channel.actions.waxum.sendList({ account, to, body: "Menu", buttonText: "Open", sections: [...] });
await channel.actions.waxum.sendCtaUrl({ account, to, body: "...", buttonText: "Open", url: "https://..." });
```
Button/list taps come back through the normal inbound path as a message
with `metadata.waxumMessageType` set (e.g. `buttons_response`,
`list_response`).
## Reliability
- `src/client.ts` retries 5xx/transport errors with capped exponential
backoff + jitter; 401/503 fail fast (matching waxum's own status codes โ
503 means "session not connected", not "try again").
- The inbound SSE bridge (`src/inbound.ts`) reconnects indefinitely on any
drop and drops duplicate deliveries across reconnects via a bounded
in-memory id set.
## Testing
```bash
npm test
```
`src/client.test.ts` stubs `fetch` directly โ no live waxum instance or
`openclaw` package needed to run it.
## Compatibility
Targets the `createChatChannelPlugin` / `defineChannelMessageAdapter` /
`defineChannelPluginEntry` API as documented publicly by OpenClaw. Only
`index.ts`, `setup-entry.ts`, and `src/channel.ts` import from `openclaw`;
`src/client.ts` and `src/inbound.ts` are plain TypeScript you can reuse or
test standalone.
channels
Comments
Sign in to leave a comment