Skip to content

WhatsApp Integration

WhatsApp provides two-way mobile command and control via Vonage Messages API (WABA - WhatsApp Business API).

Configuration

WABA Number: +44 7441 443388 (447441443388 without +) Authorized Users: - 447490195079 (Personal) - 447816246275 (Work) - 447713861128 (Girlfriend)

Webhook Endpoints (aegis.rbnk.uk): - Inbound: /api/vonage/whatsapp/inbound - Status: /api/vonage/whatsapp/status

Environment Variables

Configured in aegis.config.settings:

VONAGE_API_KEY = settings.vonage_api_key
VONAGE_API_SECRET = settings.vonage_api_secret
VONAGE_APPLICATION_ID = settings.vonage_application_id
VONAGE_WHATSAPP_NUMBER = settings.vonage_whatsapp_number
VONAGE_PRIVATE_KEY_B64 = settings.vonage_private_key_b64  # Base64-encoded private key
VONAGE_SIGNATURE_SECRET = settings.vonage_signature_secret  # For webhook verification

Code Structure

Core Module: /home/agent/projects/aegis-core/aegis/whatsapp/__init__.py Webhook Routes: /home/agent/projects/aegis-core/aegis/dashboard/routes/vonage.py

Available Commands

Claude Sessions (Power Feature)

Start and manage Claude Code sessions from your phone:

task: Deploy nginx to production

Starts a new Claude Code session with the task description.

c: Now add SSL certificates
continue: Add health checks too

Resume the current session with additional instructions.

sessions

List your active Claude sessions.

session wa-1234-123456

View details of a specific session.

stop session

Terminate the running session.

MCP Tasks Input

Provide input to tasks awaiting clarification:

input: yes, proceed with option A

Check tasks waiting for input:

pending
awaiting
waiting

Knowledge Graph

recall nginx deployment

Search knowledge graph for entities and facts (brief).

recall full nginx deployment

Verbose knowledge graph search with full details.

Twitter Analysis

analyze @username
analyze @pipelineabuser --max 500

Analyze Twitter profile and extract tools, tactics, and insights.

3D Generation

3d: kitchen roll holder
print: phone stand with cable slot
meshy cute dragon figurine

Generate 3D models via Meshy.ai (for 3D printing).

System Commands

status
s

Get system health (containers, memory, disk, tasks).

tasks

Show pending Beads tasks.

calendar

Show today's schedule from Google Calendar.

email

Email triage status (unread count, recent activity).

journal
journal yesterday

Show today's journal entry (or specific date).

morning

Comprehensive morning briefing (system health, tasks, calendar, emails).

evening

Day summary (sessions completed, tasks closed, git activity, tomorrow preview).

Operations

deploy <service>
deploy nginx restart
deploy nginx logs

Deploy services, restart containers, view logs.

stop <service>

Stop a Docker container.

logs <service>
logs <service> errors

View container logs (optionally filter for errors only).

help

Show all available commands.

Intent Recognition

WhatsApp commands are parsed using pattern matching:

Location: aegis.whatsapp.parse_intent()

Pattern Examples

# Claude session commands
r"^task:\s*(.+)"                    # task: <description>
r"^c:\s*(.*)$"                      # c: <prompt>
r"^continue:\s*(.*)$"               # continue: <prompt>
r"^sessions?$"                      # sessions
r"^session\s+([a-zA-Z0-9-]+)"       # session <id>
r"^stop\s+session"                  # stop session

# MCP Tasks input
r"^input:\s*(.+)"                   # input: <response>
r"^pending$|^awaiting$|^waiting$"   # pending/awaiting/waiting

# Knowledge graph
r"^(?:recall|remember)\s+full\s+(.+)"  # recall full <query>
r"^(?:recall|remember)\s+(.+)"         # recall <query>

# Status
r"^/status$|^status$|^s$"           # status / s

Sending Messages

Via Python Code

from aegis.whatsapp import send_whatsapp_message

result = await send_whatsapp_message(
    to_number="447490195079",
    text="Your task is complete!"
)

Via MCP Tool

mcp__vonage__whatsapp_send_text(
    to="447490195079",
    text="Deployment successful"
)

Send Files

from aegis.whatsapp import send_whatsapp_file

result = await send_whatsapp_file(
    to_number="447490195079",
    file_url="https://aegisagent.ai/reports/analysis.pdf",
    caption="Analysis complete",
    filename="analysis.pdf"
)

Send Images

from aegis.whatsapp import send_whatsapp_image

result = await send_whatsapp_image(
    to_number="447490195079",
    image_url="https://aegisagent.ai/charts/metrics.png",
    caption="Latest metrics"
)

Webhook Handling

Inbound Messages

POST requests from Vonage arrive at /api/vonage/whatsapp/inbound:

{
  "message_uuid": "abc-123",
  "from": "447490195079",
  "to": "447441443388",
  "timestamp": "2026-01-25T12:34:56Z",
  "message_type": "text",
  "text": "status",
  "channel": "whatsapp"
}

Processed by aegis.whatsapp.process_inbound_message(): 1. Verify sender is authorized 2. Parse intent from message text 3. Route to appropriate handler 4. Send response

Status Updates

POST requests from Vonage arrive at /api/vonage/whatsapp/status:

{
  "message_uuid": "abc-123",
  "to": "447490195079",
  "from": "447441443388",
  "timestamp": "2026-01-25T12:34:56Z",
  "status": "delivered",  // or "read", "failed"
  "channel": "whatsapp"
}

Updates are logged to whatsapp_messages table.

Database Schema

whatsapp_sessions

CREATE TABLE whatsapp_sessions (
    id SERIAL PRIMARY KEY,
    phone_number TEXT NOT NULL UNIQUE,
    last_intent TEXT,
    last_target TEXT,
    context JSONB DEFAULT '{}',
    preferences JSONB DEFAULT '{"notifications": true}',
    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW()
);

whatsapp_messages

CREATE TABLE whatsapp_messages (
    id SERIAL PRIMARY KEY,
    message_uuid TEXT UNIQUE,
    phone_number TEXT NOT NULL,
    direction TEXT NOT NULL,  -- 'inbound' or 'outbound'
    text TEXT,
    intent TEXT,
    status TEXT DEFAULT 'received',  -- received, sent, delivered, read, failed
    processed BOOLEAN DEFAULT false,
    created_at TIMESTAMPTZ DEFAULT NOW()
);

Authentication

WhatsApp uses JWT authentication with Vonage:

from aegis.whatsapp import _create_vonage_jwt

token = _create_vonage_jwt("whatsapp")  # Creates JWT valid for 1 hour

The private key is base64-encoded in environment variable VONAGE_PRIVATE_KEY_B64.

Webhook Signature Verification

Vonage signs webhooks with HMAC-SHA256:

def verify_vonage_signature(payload: bytes, signature: str) -> bool:
    secret = settings.vonage_signature_secret
    expected = hmac.new(
        secret.encode('utf-8'),
        payload,
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, signature)

Set VONAGE_SIGNATURE_SECRET to enable verification.

Command Suggestions

Unknown commands trigger fuzzy matching:

User: "satus"
Bot: 🤔 Unknown command: "satus"

Did you mean: status or tasks?

Type 'help' for all commands

Uses Levenshtein distance for suggestions.

Best Practices

  1. Brevity: WhatsApp is mobile-first, keep responses concise
  2. Formatting: Use WhatsApp markdown (*bold*, _italic_, ` code `)
  3. Context: Sessions maintain context, use c: for follow-ups
  4. Security: Only authorized numbers can send commands
  5. Error Handling: Always provide clear error messages with suggestions
  6. Rate Limits: Vonage enforces rate limits on message sending

Troubleshooting

Message Not Sent

Check Vonage application configuration:

curl -X GET "https://api.nexmo.com/v2/applications/$VONAGE_APPLICATION_ID" \
  -H "Authorization: Bearer $JWT_TOKEN"

Webhook Not Received

Verify webhook URLs in Vonage dashboard:

# POST to /api/vonage/configure-webhooks
{
  "inbound_url": "https://aegis.rbnk.uk/api/vonage/whatsapp/inbound",
  "status_url": "https://aegis.rbnk.uk/api/vonage/whatsapp/status"
}

Unauthorized User

Add phone number to AUTHORIZED_NUMBERS in aegis/whatsapp/__init__.py:

AUTHORIZED_NUMBERS = {
    "447490195079",  # Personal
    "447816246275",  # Work
    "447713861128",  # Girlfriend
}

Example Workflow

  1. User sends: task: Fix bug in auth.py
  2. System creates Claude Code session
  3. System responds: "🤖 Task started: Fix bug in auth.py (Session: wa-1234-567890)"
  4. Claude works on the task
  5. System sends updates: "✅ Bug fixed in auth.py. Added validation for email field."
  6. User sends: c: Now write tests for it
  7. Claude continues in same session
  8. System responds: "✅ Added tests in test_auth.py. Coverage: 95%"