← Back to Plugins
Channels

Ai Agent Whatsapp Official

dearken10 By dearken10 ⭐ 1 stars 👁 18 views ▲ 0 votes

openclaw-whatsapp-plugin

GitHub

Install

openclaw plugins install -l

README

# OpenClaw Official WhatsApp Plugin

> **Looking to install the OpenClaw plugin?** See [`openclaw-plugin/README.md`](./openclaw-plugin/README.md) for end-user installation, FAQ, and plan details.
>
> **Want to forward WhatsApp into a Claude Code session?** See [`claude-plugin/README.md`](./claude-plugin/README.md).

This repo contains the backend routing server plus one or more agent plugins that bridge WhatsApp (via imBee) to a locally-running AI agent. The backend is agent-agnostic — it speaks a small WebSocket + HTTP contract that any plugin can consume.

**Repo layout:**

| Path | Description |
|:---|:---|
| `backend/` | Go routing server — pairing, webhook verification, WebSocket hub, media proxy (agent-agnostic) |
| `openclaw-plugin/` | OpenClaw channel plugin — runs inside the OpenClaw gateway |
| `claude-plugin/` | Claude Code bridge — forwards each paired WhatsApp user to their own Claude Code session |
| `docs/` | PRD and technical design |
| `scripts/` | Dev, ngrok, deploy, and publish helpers |

---

## Quick start (local dev)

### Prerequisites

- Docker + Docker Compose
- Go ≥ 1.21 (for the dev CLI and building)
- An ngrok account (free tier is fine) for a public HTTPS URL
- A 360dialog or Meta WhatsApp Cloud API key

### 1. Configure environment

```bash
cp .env.example .env
# Edit .env — set WA_PROVIDER, D360_API_KEY (or WABA_TOKEN), SHARED_WA_NUMBER
```

### 2. Start the backend

```bash
make up
# Backend: http://localhost:28080
```

Uses `STORE_DRIVER=file` by default (data saved to `./data/store.json`). No Postgres needed for local dev.

### 3. Expose to the internet (required for Meta webhooks)

```bash
make ngrok
# Prints a public HTTPS URL and registers it as the 360dialog webhook
# Copy the URL into .env as ROUTING_BASE_URL, then: make up
```

### 4. Pair your WhatsApp number

```bash
make pair
# Prints a pairing code e.g. CLAW-A3F9-Z7KL and a wa.me link
# Send the code from your WhatsApp to the shared number
```

Watch for the pairing confirmation:

```bash
make ws API_KEY=imbee_xxx
# Prints PAIRING_COMPLETE once you send the code
```

### 5. Install the plugin into OpenClaw

```bash
openclaw plugins install -l ./openclaw-plugin    # dev link (no copy)
openclaw gateway restart
```

Add channel config to your OpenClaw config file:

```json5
{
  channels: {
    "whatsapp-official": {
      routingBaseUrl: "https://<your-ngrok-url>",
      instanceId: "your-openclaw-instance-id",
      apiKey: "imbee_…from_pair_response…",
      dmPolicy: "open"
    }
  }
}
```

### 6. Test

Send a WhatsApp message to the shared number — your OpenClaw agent should reply.

Simulate an inbound webhook locally:

```bash
TEXT="hello from test user" ./scripts/replay-webhook.sh
```

### 7. Stop

```bash
make down
```

---

## Cloud deployment (AWS)

Deploys the backend to a single EC2 t4g.nano (~$4/month). No database needed — uses the file store driver.

### Prerequisites

- AWS CLI installed (`brew install awscli`)
- AWS SSO access to your AWS organisation (set `AWS_PROD_PROFILE`, `AWS_DEV_PROFILE`, `AWS_SSO_START_URL`, `AWS_SSO_REGION` in `.env` — see `.env.example`)
- A domain name with DNS you can edit (required for HTTPS / Meta webhooks)

### 1. Authenticate with AWS SSO

```bash
eval "$(./scripts/aws-login.sh)"          # uses $AWS_PROD_PROFILE
eval "$(./scripts/aws-login.sh --dev)"    # uses $AWS_DEV_PROFILE
```

Or pass `PROFILE=` directly to deploy commands (no `eval` needed — see step 2).

### 2. Deploy

```bash
make deploy DOMAIN=api.example.com PROFILE=<account-id>_AdministratorAccess
```

This will:
- Cross-compile the Go binary for linux/arm64
- Create a key pair (default name `openclaw-wa`, saved as `~/.ssh/openclaw-wa.pem`), security group, and t4g.nano instance if they don't exist
- Upload the binary and `.env`
- Install Caddy (auto-HTTPS via Let's Encrypt) and set up systemd services

### 3. Point DNS

After deploy, add an **A record** in your DNS:

```
api.example.com  →  <Public IP printed by deploy>
```

Once DNS propagates, Caddy obtains a TLS certificate automatically. Verify:

```bash
curl https://api.example.com/healthz
```

### 4. Register the webhook

In your 360dialog Hub (or Meta App Dashboard):

```
Webhook URL:   https://api.example.com/webhooks/whatsapp
Verify token:  (value of WEBHOOK_VERIFY_TOKEN in .env)
```

### 5. Update config and redeploy

```bash
# In .env, set:
# ROUTING_BASE_URL=https://api.example.com

make deploy-update DOMAIN=api.example.com PROFILE=<account-id>_AdministratorAccess
```

### Subsequent deploys

| Command | Effect |
|:---|:---|
| `make deploy DOMAIN=... PROFILE=...` | Full deploy — creates infra if missing, updates binary + config |
| `make deploy-update DOMAIN=... PROFILE=...` | Push new binary/config only — skips infra |

### SSH access and logs

```bash
ssh -i ~/.ssh/openclaw-wa.pem ec2-user@<Public IP>
ssh -i ~/.ssh/openclaw-wa.pem ec2-user@<Public IP> 'journalctl -u wa-server -f'
```

---

## Store drivers

| `STORE_DRIVER` | Persistence | Use case |
|:---|:---|:---|
| `file` | JSON file on disk (default) | Local dev, single-VM cloud deploy |
| `memory` | In-process only, lost on restart | Unit tests, throwaway dev |
| `postgres` | PostgreSQL | Multi-replica production |

Configure in `.env`:

```bash
# File store (default)
STORE_DRIVER=file
STORE_FILE_PATH=./data/store.json

# Postgres
STORE_DRIVER=postgres
POSTGRES_DSN=postgres://postgres:postgres@localhost:5432/whatsapp_plugin?sslmode=disable
```

---

## Backend API

| Endpoint | Method | Auth | Description |
|:---|:---|:---|:---|
| `/healthz` | GET | — | Health check |
| `/api/v1/pair/request` | POST | — | Generate pairing code + API key |
| `/api/v1/pair/status` | GET | Bearer | Check pairing status |
| `/api/v1/send` | POST | Bearer | Send outbound text or media |
| `/api/v1/typing` | POST | Bearer | Mark message read + show typing indicator |
| `/api/v1/media/{mediaId}` | GET | Bearer | Download inbound media (proxied from provider) |
| `/webhooks/whatsapp` | GET | — | Meta webhook registration challenge |
| `/webhooks/whatsapp` | POST | HMAC/Header | Receive inbound events from Meta / 360dialog |
| `/ws` | WSS | Bearer | WebSocket — inbound event stream to plugin |

---

## WhatsApp providers

Set `WA_PROVIDER` in `.env`:

| Value | Provider | Required vars |
|:---|:---|:---|
| `360dialog` | 360dialog Cloud API | `D360_API_KEY` |
| `meta` | Meta WhatsApp Cloud API | `WABA_TOKEN`, `WABA_PHONE_NUMBER_ID` |
| `` (empty) | Stub / dev mode | — |

---

## OpenClaw plugin

### Install

```bash
# Dev link (no copy)
openclaw plugins install -l ./openclaw-plugin
openclaw gateway restart

# From npm / ClawHub (after publishing)
openclaw plugins install openclaw-channel-whatsapp-official
```

### Supported message types

| Type | Agent receives |
|:---|:---|
| Text | Plain text |
| Image | Base64 data URI (`data:image/jpeg;base64,...`) — readable by vision models |
| Video / Audio / Sticker | `[type] · filename · mime · N KB` |
| Document | `[document] · filename · mime · N KB` |

### Publishing (npm + ClawHub)

Bump `version` in **both** `openclaw-plugin/package.json` and `openclaw-plugin/openclaw.plugin.json`, then:

```bash
./scripts/publish-plugin-npm-clawhub.sh
```

---

## Make targets

```
make up                    Start local backend (Docker)
make down                  Stop local backend
make smoke                 Run smoke tests
make pair                  Request a pairing code
make ws API_KEY=imbee_xxx  Open WebSocket listener
make send API_KEY=imbee_xxx TEXT="hello"  Send outbound message
make test                  Run Go tests
make ngrok                 Start ngrok + register 360dialog webhook

make publish-plugin-local                   Patch ROUTING_BASE_URL into plugin for local dev (no publish)
make publish-plugin-local BAKE_ENV_FILE=.env.dev  Same, with explicit env file
make publish-plugin-npm-clawhub             Publish plugin to npm + ClawHub
make publish-plugin-npm-clawhub ENV_FILE=.env.prod  Publish using prod env

make aws-login             Authenticate with imBee AWS SSO (prod)
make aws-login DEV=1       Authenticate with imBee AWS SSO (dev)
make deploy DOMAIN=...     Full deploy to EC2
make deploy-update DOMAIN=...  Push binary/config to existing instance
```
channels

Comments

Sign in to leave a comment

Loading comments...