Files
nuc/.artifacts/2026-02-16_22-30_openclaw-upgrade-protection.md
Alejandro Gutiérrez 1aa7ebcde3 Add AI gateway and WhatsApp integration artifacts (Feb 12-17)
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>
2026-02-18 15:17:11 +01:00

9.9 KiB

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.fromevent.sender.id)
  • Changes hook resolution (different events, different return types)

Mitigation:

// 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:

#!/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:

#!/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
  • 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