docs: add WhatsApp channel configuration guide
Complete setup and troubleshooting guide for the WhatsApp channel, written from end-to-end hands-on testing. Covers native mode build requirements (whatsapp_native tag, go generate step), QR pairing, absolute path requirements, local LLM setup with Ollama (GPU vs CPU pitfall), HEARTBEAT.md hallucination warning, systemd deployment, and a troubleshooting table with 10 real issues discovered during testing. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
f2addff099
commit
4d074bcdb1
1 changed files with 324 additions and 0 deletions
324
docs/channels/whatsapp/README.md
Normal file
324
docs/channels/whatsapp/README.md
Normal file
|
|
@ -0,0 +1,324 @@
|
|||
# WhatsApp Channel Configuration Guide
|
||||
|
||||
WhatsApp support in PicoClaw uses [whatsmeow](https://github.com/tulir/whatsmeow) (native mode) or an external WebSocket bridge (bridge mode). Native mode is recommended for most deployments.
|
||||
|
||||
> **Note:** WhatsApp native support requires a custom build. The default prebuilt binaries do not include it. See [Build Requirements](#build-requirements) below.
|
||||
|
||||
---
|
||||
|
||||
## 1. Build Requirements
|
||||
|
||||
The standard release binary does not include WhatsApp support. You must build from source with the `whatsapp_native` build tag.
|
||||
|
||||
**Prerequisites:**
|
||||
- Go 1.21 or later ([install guide](https://go.dev/doc/install))
|
||||
- Git
|
||||
|
||||
**Build steps:**
|
||||
|
||||
```bash
|
||||
# Clone the repository
|
||||
git clone https://github.com/sipeed/picoclaw
|
||||
cd picoclaw
|
||||
|
||||
# Generate embedded assets (required before building)
|
||||
go generate ./...
|
||||
|
||||
# Build with WhatsApp native support (Linux x86_64)
|
||||
go build -tags whatsapp_native -ldflags "-s -w" -o picoclaw-whatsapp ./cmd/picoclaw
|
||||
|
||||
# Verify the binary
|
||||
./picoclaw-whatsapp version
|
||||
```
|
||||
|
||||
For other architectures:
|
||||
|
||||
```bash
|
||||
# ARM64 (Raspberry Pi 4, etc.)
|
||||
GOOS=linux GOARCH=arm64 go build -tags whatsapp_native -ldflags "-s -w" -o picoclaw-whatsapp-arm64 ./cmd/picoclaw
|
||||
|
||||
# ARMv7 (Raspberry Pi 3, etc.)
|
||||
GOOS=linux GOARCH=arm GOARM=7 go build -tags whatsapp_native -ldflags "-s -w" -o picoclaw-whatsapp-armv7 ./cmd/picoclaw
|
||||
```
|
||||
|
||||
> **Binary size:** The WhatsApp-enabled binary is approximately 60 MB (vs 20 MB for the standard binary) due to the whatsmeow library and SQLite dependency.
|
||||
|
||||
---
|
||||
|
||||
## 2. Example Configuration
|
||||
|
||||
> **Important:** Use absolute paths for `session_store_path` and `workspace`. Tilde (`~`) expansion is not supported in these fields — using `~` will cause PicoClaw to create a literal `~/` directory in your current working directory instead of your home directory.
|
||||
|
||||
Add the following to `~/.picoclaw/config.json`:
|
||||
|
||||
### Native Mode (recommended)
|
||||
|
||||
```json
|
||||
{
|
||||
"channels": {
|
||||
"whatsapp": {
|
||||
"enabled": true,
|
||||
"use_native": true,
|
||||
"session_store_path": "/home/YOUR_USERNAME/.picoclaw/whatsapp-session/",
|
||||
"allow_from": []
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Bridge Mode
|
||||
|
||||
Bridge mode connects to an external WhatsApp bridge over WebSocket (for example [whatsapp-bridge](https://github.com/example/whatsapp-bridge)):
|
||||
|
||||
```json
|
||||
{
|
||||
"channels": {
|
||||
"whatsapp": {
|
||||
"enabled": true,
|
||||
"use_native": false,
|
||||
"bridge_url": "ws://localhost:3001",
|
||||
"allow_from": []
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Full Config Example (native mode with all options)
|
||||
|
||||
```json
|
||||
{
|
||||
"agents": {
|
||||
"defaults": {
|
||||
"workspace": "/home/YOUR_USERNAME/.picoclaw/workspace",
|
||||
"model_name": "my-model",
|
||||
"max_tokens": 2048,
|
||||
"temperature": 0.7,
|
||||
"max_tool_iterations": 50
|
||||
}
|
||||
},
|
||||
"model_list": [
|
||||
{
|
||||
"model_name": "my-model",
|
||||
"model": "anthropic/claude-haiku-4-5-20251001",
|
||||
"api_key": "YOUR_ANTHROPIC_API_KEY"
|
||||
}
|
||||
],
|
||||
"channels": {
|
||||
"whatsapp": {
|
||||
"enabled": true,
|
||||
"use_native": true,
|
||||
"session_store_path": "/home/YOUR_USERNAME/.picoclaw/whatsapp-session/",
|
||||
"allow_from": ["+1234567890"],
|
||||
"reasoning_channel_id": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Field Reference
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|---|---|---|---|
|
||||
| `enabled` | bool | Yes | Enable or disable the WhatsApp channel |
|
||||
| `use_native` | bool | Yes | `true` for native mode (whatsmeow); `false` for bridge mode |
|
||||
| `session_store_path` | string | No (native) | Absolute path to store the WhatsApp session database. Session persists across restarts — no re-scan needed. Must be an absolute path (see note above). |
|
||||
| `bridge_url` | string | Yes (bridge) | WebSocket URL of the external WhatsApp bridge (for example `ws://localhost:3001`). Only used when `use_native` is `false`. |
|
||||
| `allow_from` | []string | No | Phone number whitelist in E.164 format (for example `["+919876543210"]`). Leave empty `[]` to accept messages from all numbers. |
|
||||
| `reasoning_channel_id` | string | No | Route reasoning/thinking output to a separate channel ID. Leave empty to disable. |
|
||||
|
||||
---
|
||||
|
||||
## 4. First Run — QR Code Pairing
|
||||
|
||||
On first run, PicoClaw displays a QR code in the terminal:
|
||||
|
||||
```bash
|
||||
picoclaw-whatsapp gateway
|
||||
```
|
||||
|
||||
Expected output:
|
||||
|
||||
```
|
||||
✓ Channels enabled: [whatsapp_native]
|
||||
✓ Gateway started on 127.0.0.1:18790
|
||||
|
||||
Scan this QR code with WhatsApp (Linked Devices):
|
||||
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄...
|
||||
█ ▄▄▄▄▄ █...
|
||||
...
|
||||
```
|
||||
|
||||
**To pair your phone:**
|
||||
1. Open WhatsApp on your phone
|
||||
2. Tap **⋮ (three dots)** → **Linked Devices**
|
||||
3. Tap **Link a Device**
|
||||
4. Scan the QR code displayed in the terminal
|
||||
|
||||
After scanning, you will see:
|
||||
```
|
||||
WhatsApp login event event=success
|
||||
WhatsApp native channel connected
|
||||
```
|
||||
|
||||
The session is saved to `session_store_path`. Subsequent restarts connect automatically without re-scanning.
|
||||
|
||||
> **Note:** If the QR code expires before you scan it (roughly 60 seconds), restart the gateway to generate a new one.
|
||||
|
||||
---
|
||||
|
||||
## 5. Using a Local LLM (Ollama)
|
||||
|
||||
PicoClaw works with any OpenAI-compatible API, including a local [Ollama](https://ollama.com) server. This keeps all inference on-device — nothing leaves the machine.
|
||||
|
||||
### Install Ollama
|
||||
|
||||
```bash
|
||||
# Download and extract (requires zstd)
|
||||
curl -L -o /tmp/ollama-linux-amd64.tar.zst \
|
||||
https://github.com/ollama/ollama/releases/latest/download/ollama-linux-amd64.tar.zst
|
||||
zstd -d /tmp/ollama-linux-amd64.tar.zst -o /tmp/ollama-linux-amd64.tar
|
||||
tar -xf /tmp/ollama-linux-amd64.tar -C ~/.local # extracts bin/ollama AND lib/ollama/
|
||||
```
|
||||
|
||||
> **Important:** You must extract the full tar, not just the binary. The `lib/ollama/` directory contains the CUDA runtime libraries (`libcublas`, `libcudart`, `libggml-cuda.so`) required for GPU inference. Extracting only the `bin/ollama` binary causes Ollama to silently fall back to CPU-only mode, resulting in 2-minute timeouts on every request.
|
||||
|
||||
Pull a model and start the server:
|
||||
|
||||
```bash
|
||||
export PATH="$HOME/.local/bin:$PATH"
|
||||
ollama pull llama3.2:3b # ~2 GB
|
||||
ollama serve &
|
||||
```
|
||||
|
||||
### Config for Ollama
|
||||
|
||||
```json
|
||||
{
|
||||
"model_list": [
|
||||
{
|
||||
"model_name": "llama-local",
|
||||
"model": "openai/llama3.2:3b",
|
||||
"api_base": "http://localhost:11434/v1",
|
||||
"api_key": "ollama",
|
||||
"request_timeout": 120
|
||||
}
|
||||
],
|
||||
"agents": {
|
||||
"defaults": {
|
||||
"model_name": "llama-local"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> **`request_timeout` note:** The first inference request after starting Ollama loads the model into VRAM (30–60 seconds on a laptop GPU). Set `request_timeout` to at least `120` to avoid a premature timeout on cold start. Subsequent requests are fast once the model is resident in memory.
|
||||
|
||||
---
|
||||
|
||||
## 6. Running as a Background Service
|
||||
|
||||
### Using systemd (recommended for servers)
|
||||
|
||||
Create `/etc/systemd/system/picoclaw.service`:
|
||||
|
||||
```ini
|
||||
[Unit]
|
||||
Description=PicoClaw WhatsApp Gateway
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=YOUR_USERNAME
|
||||
ExecStart=/usr/local/bin/picoclaw-whatsapp gateway
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
Environment=PICOCLAW_CONFIG=/home/YOUR_USERNAME/.picoclaw/config.json
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
```bash
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable picoclaw
|
||||
sudo systemctl start picoclaw
|
||||
sudo systemctl status picoclaw
|
||||
```
|
||||
|
||||
### Using nohup (quick testing)
|
||||
|
||||
```bash
|
||||
nohup picoclaw-whatsapp gateway > /home/YOUR_USERNAME/.picoclaw/gateway.log 2>&1 &
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. HEARTBEAT.md Warning
|
||||
|
||||
PicoClaw runs a heartbeat every 30 minutes and executes tasks listed in `HEARTBEAT.md` in your workspace. The default file ships with example tasks:
|
||||
|
||||
```
|
||||
- Check for unread messages
|
||||
- Review upcoming calendar events
|
||||
- Check device status (e.g., MaixCam)
|
||||
```
|
||||
|
||||
> **Warning:** The agent will attempt to execute every task in this file. If the model has no actual tools to fulfil a task (for example calendar access or device APIs), it will **hallucinate results** — inventing fake meeting schedules, device readings, and API responses — and send them to your WhatsApp.
|
||||
|
||||
**Before going to production, either:**
|
||||
- Remove all example tasks and add only tasks the agent can genuinely fulfil with its available tools, or
|
||||
- Delete the section below the `---` divider to disable heartbeat tasks entirely
|
||||
|
||||
Safe example:
|
||||
```
|
||||
## Heartbeat Tasks
|
||||
- Report current time and confirm gateway is running
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. Currently Supported
|
||||
|
||||
- Text message send and receive
|
||||
- QR code pairing via terminal
|
||||
- Persistent session (no re-scan after restart)
|
||||
- Per-number allow-list (`allow_from`)
|
||||
- Individual (DM) message handling
|
||||
- Reasoning output routing (`reasoning_channel_id`)
|
||||
- Bridge mode via external WebSocket
|
||||
|
||||
---
|
||||
|
||||
## 9. Troubleshooting
|
||||
|
||||
| Problem | Cause | Fix |
|
||||
|---|---|---|
|
||||
| Gateway starts but shows no QR code | Previous session exists | Delete `session_store_path` directory and restart |
|
||||
| `failed to read frame header: EOF` after restart | WhatsApp session was logged out from phone | Delete session directory and restart to re-scan QR |
|
||||
| Session created in wrong directory (literal `~/` folder) | Tilde not expanded in `session_store_path` | Use absolute path: `/home/username/.picoclaw/whatsapp-session/` |
|
||||
| `build tag whatsapp_native not found` | Building without required tag | Use `go build -tags whatsapp_native` |
|
||||
| QR code not rendering correctly | Terminal does not support Unicode block characters | Switch to a terminal that supports Unicode (for example GNOME Terminal, iTerm2) |
|
||||
| `can't link new devices at this time` | WhatsApp rate limiting | Wait 10 minutes and restart gateway |
|
||||
| Bot not responding to messages | `allow_from` set incorrectly | Check number format is E.164 (for example `+919876543210`), or set `allow_from: []` to allow all |
|
||||
| Agent sends hallucinated calendar/device data | HEARTBEAT.md contains tasks with no real tools | Remove example tasks from HEARTBEAT.md (see [HEARTBEAT.md Warning](#heartbeatmd-warning)) |
|
||||
| `go generate` step fails | Missing dependencies | Run `go mod download` first, then retry `go generate ./...` |
|
||||
| Ollama times out on every request (CPU only, 2-minute hang) | Ollama tar.zst was partially extracted — only the binary, not `lib/ollama/` | Re-extract the full `ollama-linux-amd64.tar.zst`; it must unpack both `bin/ollama` **and** `lib/ollama/cuda_v12/` (cuBLAS, CUDA runtime, GGML CUDA kernel). Without these the runner silently falls back to CPU and hits the `request_timeout`. |
|
||||
|
||||
**To reconnect after logging out from your phone:**
|
||||
```bash
|
||||
rm -rf /home/YOUR_USERNAME/.picoclaw/whatsapp-session/
|
||||
# then restart the gateway — a new QR code will appear
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. TODO
|
||||
|
||||
- Group message support
|
||||
- Media message send/receive (images, audio, documents)
|
||||
- Typing indicator
|
||||
- Read receipts
|
||||
- Placeholder message while agent is processing
|
||||
- Status message support
|
||||
Loading…
Add table
Reference in a new issue