OpenClaw setup, Arrio deployment, WhatsApp MCP server, DNS/Traefik entries, communication style prompts (v1+v2), WhatsApp monitoring system plan, and OpenClaw upgrade protection strategy. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
227 lines
9.9 KiB
Markdown
227 lines
9.9 KiB
Markdown
# OpenClaw Upgrade Protection Strategy
|
|
|
|
**Date:** 2026-02-16 22:30
|
|
**Context:** Protecting our WhatsApp monitoring system when OpenClaw gets updated via `docker compose pull` or version bumps
|
|
|
|
## Risk Map
|
|
|
|
| Component | Location | Survives Update? | Risk |
|
|
|-----------|----------|-----------------|------|
|
|
| **handler.ts** (logger hook) | `~/.openclaw/hooks/whatsapp-logger/` | Yes — host volume mount | LOW: OpenClaw may change hook API |
|
|
| **handler.ts** (context hook) | `~/.openclaw/hooks/whatsapp-context/` | Yes — host volume mount | LOW: same |
|
|
| **wa-query.js** | `~/.openclaw/workspace/tools/` | Yes — host volume mount | NONE: pure Node.js, no OpenClaw deps |
|
|
| **TOOLS.md** | `~/.openclaw/workspace/TOOLS.md` | Yes — host volume mount | NONE: documentation only |
|
|
| **sidecar.py** | `~/.openclaw/whatsapp-monitor/` | Yes — runs on host, not in container | NONE: completely independent |
|
|
| **PostgreSQL** | Coolify-managed container `akwgskos0woc4w0coc8ssks4` | Yes — separate container + volume | NONE: independent of OpenClaw |
|
|
| **contacts.json** | `~/.openclaw/whatsapp-monitor/` | Yes — host filesystem | NONE |
|
|
| **JSONL files** | `~/.openclaw/whatsapp-monitor/` | Yes — host filesystem | NONE |
|
|
| **openclaw.json** | `~/.openclaw/openclaw.json` | Yes — host volume | MEDIUM: OpenClaw may add/remove keys on update |
|
|
| **wa-policy.py** | `~/openclaw/wa-policy.py` | Yes — host filesystem | LOW: may need openclaw.json schema update |
|
|
| **Cron jobs** | Stored in OpenClaw gateway internal DB | **MAYBE NOT** — depends on data persistence | HIGH: may be wiped on container recreation |
|
|
| **systemd service** | `/etc/systemd/system/whatsapp-monitor.service` | Yes — system-level | NONE |
|
|
| **Hook type imports** | `PluginHookMessageReceivedEvent` | Depends on API stability | HIGH: type may be renamed/restructured |
|
|
|
|
## What Can Break
|
|
|
|
### 1. Hook API Changes (HIGH risk)
|
|
OpenClaw hooks import types from `openclaw/plugins`. If a new version:
|
|
- Renames `PluginHookMessageReceivedEvent` → something else
|
|
- Changes the event shape (e.g., `event.from` → `event.sender.id`)
|
|
- Changes hook resolution (different events, different return types)
|
|
|
|
**Mitigation:**
|
|
```typescript
|
|
// Defensive handler.ts — no type import dependency
|
|
export default function handler(event: any) {
|
|
// Extract fields with fallbacks
|
|
const from = event.from || event.sender?.id || event.sender || "unknown";
|
|
const content = event.content || event.body || event.message?.text || "";
|
|
const channel = event.channelId || event.channel || "unknown";
|
|
const senderName = event.metadata?.senderName || event.senderName || event.pushName || "";
|
|
// ...
|
|
}
|
|
```
|
|
|
|
### 2. Cron Jobs Lost on Recreate (HIGH risk)
|
|
OpenClaw stores cron jobs in its internal state. If the container is recreated (not just restarted), crons may vanish.
|
|
|
|
**Mitigation:**
|
|
- Keep a cron recreation script on the host
|
|
- Run it after every `docker compose up -d` or update
|
|
|
|
### 3. openclaw.json Schema Changes (MEDIUM risk)
|
|
A new version might:
|
|
- Reject unknown keys we added
|
|
- Restructure `hooks.internal.entries`
|
|
- Change `channels.whatsapp` shape
|
|
|
|
**Mitigation:**
|
|
- Keep a backup of our config additions separately
|
|
- After update, run `openclaw doctor --fix` then re-apply our keys
|
|
|
|
### 4. Workspace Tool Execution (LOW risk)
|
|
OpenClaw might change how workspace tools are discovered or executed. Currently `exec` runs commands in the workspace dir.
|
|
|
|
**Mitigation:**
|
|
- wa-query.js is self-contained Node.js — worst case, it's called by absolute path
|
|
- The sidecar + index.json work regardless (host-side)
|
|
|
|
## Protection Artifacts
|
|
|
|
### Backup Script: `~/.openclaw/whatsapp-monitor/backup-config.sh`
|
|
|
|
Run before any OpenClaw update:
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
# Backup all WhatsApp monitoring config before OpenClaw update
|
|
BACKUP_DIR="$HOME/.openclaw/whatsapp-monitor/backups/$(date +%Y%m%d-%H%M%S)"
|
|
mkdir -p "$BACKUP_DIR"
|
|
|
|
# Hooks
|
|
cp -r ~/.openclaw/hooks/whatsapp-logger/ "$BACKUP_DIR/hook-logger/"
|
|
cp -r ~/.openclaw/hooks/whatsapp-context/ "$BACKUP_DIR/hook-context/"
|
|
|
|
# Config
|
|
cp ~/.openclaw/openclaw.json "$BACKUP_DIR/openclaw.json"
|
|
cp ~/.openclaw/whatsapp-monitor/contacts.json "$BACKUP_DIR/contacts.json"
|
|
|
|
# Workspace tools
|
|
cp ~/.openclaw/workspace/tools/wa-query.js "$BACKUP_DIR/wa-query.js"
|
|
cp ~/.openclaw/workspace/TOOLS.md "$BACKUP_DIR/TOOLS.md"
|
|
|
|
# Policy
|
|
cp ~/openclaw/wa-policy.py "$BACKUP_DIR/wa-policy.py"
|
|
|
|
# Cron snapshot
|
|
docker exec openclaw-openclaw-gateway-1 node dist/index.js cron list \
|
|
--token 3547c3f2b7b4a33eb077cf804bcca446057f81ba1578b2045dbb3aa4e04346ee \
|
|
--url ws://127.0.0.1:18789 2>/dev/null > "$BACKUP_DIR/cron-jobs.txt"
|
|
|
|
echo "Backed up to $BACKUP_DIR"
|
|
ls -la "$BACKUP_DIR"
|
|
```
|
|
|
|
### Restore Script: `~/.openclaw/whatsapp-monitor/restore-after-update.sh`
|
|
|
|
Run after any OpenClaw update:
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
# Restore WhatsApp monitoring after OpenClaw update
|
|
TOKEN="3547c3f2b7b4a33eb077cf804bcca446057f81ba1578b2045dbb3aa4e04346ee"
|
|
URL="ws://127.0.0.1:18789"
|
|
|
|
echo "=== Verifying hooks ==="
|
|
ls -la ~/.openclaw/hooks/whatsapp-logger/handler.ts
|
|
ls -la ~/.openclaw/hooks/whatsapp-context/handler.ts
|
|
|
|
echo "=== Verifying workspace tools ==="
|
|
ls -la ~/.openclaw/workspace/tools/wa-query.js
|
|
|
|
echo "=== Re-registering hooks in config ==="
|
|
python3 -c "
|
|
import json
|
|
with open('$HOME/.openclaw/openclaw.json') as f:
|
|
config = json.load(f)
|
|
hooks = config.setdefault('hooks', {}).setdefault('internal', {})
|
|
hooks['enabled'] = True
|
|
entries = hooks.setdefault('entries', {})
|
|
entries['WhatsApp Message Logger'] = {'enabled': True}
|
|
entries['WhatsApp Context Injector'] = {'enabled': True}
|
|
with open('$HOME/.openclaw/openclaw.json', 'w') as f:
|
|
json.dump(config, f, indent=2)
|
|
print('Hooks re-registered in config')
|
|
"
|
|
|
|
echo "=== Re-creating cron jobs ==="
|
|
docker exec openclaw-openclaw-gateway-1 node dist/index.js cron add \
|
|
--name "WhatsApp Morning Digest" \
|
|
--schedule "cron 0 9 * * * @ UTC" \
|
|
--prompt 'Run node tools/wa-query.js summary 12 and node tools/wa-query.js unread. Create a digest. Send to +34678000075 via openclaw message send --channel whatsapp. Then mark-read all.' \
|
|
--target isolated --agent main \
|
|
--token "$TOKEN" --url "$URL" 2>/dev/null && echo "Morning digest cron added"
|
|
|
|
docker exec openclaw-openclaw-gateway-1 node dist/index.js cron add \
|
|
--name "WhatsApp Evening Digest" \
|
|
--schedule "cron 0 21 * * * @ UTC" \
|
|
--prompt 'Run node tools/wa-query.js summary 12 and node tools/wa-query.js unread. Create a digest. Send to +34678000075 via openclaw message send --channel whatsapp. Then mark-read all.' \
|
|
--target isolated --agent main \
|
|
--token "$TOKEN" --url "$URL" 2>/dev/null && echo "Evening digest cron added"
|
|
|
|
echo "=== Verifying sidecar ==="
|
|
systemctl status whatsapp-monitor.service --no-pager | head -5
|
|
|
|
echo "=== Verifying PostgreSQL ==="
|
|
docker exec akwgskos0woc4w0coc8ssks4 psql -U openclaw -d whatsapp_monitor -c "SELECT count(*) as messages FROM messages; SELECT count(*) as contacts FROM contacts;"
|
|
|
|
echo "=== Restarting gateway ==="
|
|
cd ~/openclaw && docker compose restart openclaw-gateway
|
|
|
|
echo "=== Done ==="
|
|
```
|
|
|
|
## Pre-Update Checklist
|
|
|
|
Before running `docker compose pull` or updating OpenClaw:
|
|
|
|
1. **[ ]** Run backup script: `bash ~/.openclaw/whatsapp-monitor/backup-config.sh`
|
|
2. **[ ]** Note current cron job count: `docker exec openclaw-openclaw-gateway-1 node dist/index.js cron list --token TOKEN --url URL | grep -c WhatsApp`
|
|
3. **[ ]** Stop sidecar (optional, prevents stale writes): `sudo systemctl stop whatsapp-monitor`
|
|
4. **[ ]** Pull/update OpenClaw: `cd ~/openclaw && docker compose pull && docker compose up -d`
|
|
5. **[ ]** Wait for gateway to start: `docker logs -f openclaw-openclaw-gateway-1`
|
|
6. **[ ]** Run restore script: `bash ~/.openclaw/whatsapp-monitor/restore-after-update.sh`
|
|
7. **[ ]** Re-start sidecar: `sudo systemctl start whatsapp-monitor`
|
|
8. **[ ]** Verify everything: check hooks, crons, sidecar status, PG connection
|
|
|
|
## Why PostgreSQL Protects Us
|
|
|
|
| SQLite (old) | PostgreSQL (new) |
|
|
|---|---|
|
|
| File inside `~/.openclaw/whatsapp-monitor/` — could be corrupted by concurrent access | Separate container, proper ACID transactions |
|
|
| Gone if someone deletes the directory | Lives in Coolify-managed Docker volume — survives everything |
|
|
| Not queryable from CloudBeaver | Visible in CloudBeaver at `127.0.0.1:5450` |
|
|
| No backups | Can add Coolify backup schedule |
|
|
| Single writer (file locking) | Concurrent readers + writers |
|
|
|
|
## PostgreSQL Connection Details
|
|
|
|
| Property | Value |
|
|
|----------|-------|
|
|
| **Container** | `akwgskos0woc4w0coc8ssks4` |
|
|
| **Image** | `postgres:16-alpine` |
|
|
| **Host port** | `5450` |
|
|
| **User** | `openclaw` |
|
|
| **Password** | `OpenClaw2026!` |
|
|
| **Database** | `whatsapp_monitor` |
|
|
| **Coolify UUID** | `akwgskos0woc4w0coc8ssks4` |
|
|
| **Internal URL** | `postgres://openclaw:OpenClaw2026%21@akwgskos0woc4w0coc8ssks4:5432/whatsapp_monitor` |
|
|
| **Host URL** | `postgres://openclaw:OpenClaw2026!@127.0.0.1:5450/whatsapp_monitor` |
|
|
|
|
## Architecture After Migration
|
|
|
|
```
|
|
WhatsApp message → OpenClaw gateway (container)
|
|
│
|
|
├── Hook: whatsapp-logger/handler.ts
|
|
│ └── writes JSONL to ~/.openclaw/whatsapp-monitor/
|
|
│
|
|
├── Hook: whatsapp-context/handler.ts
|
|
│ └── reads index.json → injects into agent context
|
|
│
|
|
└── wa-query.js (reads JSONL + contacts.json)
|
|
└── for quick queries inside the agent
|
|
|
|
NUC Host:
|
|
sidecar.py (systemd) ─── reads JSONL ──→ PostgreSQL (Coolify container :5450)
|
|
│ │
|
|
└── writes ──→ index.json (summary for hooks + agent)
|
|
│
|
|
CloudBeaver can query it
|
|
```
|
|
|
|
## Related
|
|
- Plan: `.artifacts/2026-02-16_22-00_whatsapp-monitoring-system-plan.md`
|
|
- WhatsApp MCP: `.artifacts/2026-02-12_22-50_whatsapp-mcp-setup.md`
|
|
- OpenClaw setup: `.artifacts/2026-02-12_02-30_openclaw-setup.md`
|