WhatsApp Channel Runbook
Operational procedures for the Norns WhatsApp channel.
Service Overview
| Component | Location | Purpose |
|---|---|---|
| WhatsApp Module | services/norns/agent/whatsapp/ | Message handling |
| Twilio API | External SaaS | WhatsApp gateway |
| PostgreSQL | whatsapp_sessions table | Session tracking |
| Redis | Cache layer | Session window cache |
Health Checks
Quick Status Check
# Check Norns container status
ssh ravenhelm@100.115.101.81 "docker ps | grep norns"
# Check WhatsApp-related logs
ssh ravenhelm@100.115.101.81 "docker logs norns-agent 2>&1 | grep -i whatsapp | tail -10"
# Verify webhook endpoint is responding
curl -I https://norns-pm.ravenhelm.dev/whatsapp/webhook
Verify Template Configuration
# Check templates are loaded in container
ssh ravenhelm@100.115.101.81 "docker exec norns-agent env | grep WA_TEMPLATE"
# List templates via API
curl -s "https://norns-pm.ravenhelm.dev/api/whatsapp/templates" \
-H "X-API-Key: $NORNS_API_KEY" | jq
Verify Session Tracking
# Check session table
ssh ravenhelm@100.115.101.81 "docker exec -i postgres psql -U ravenhelm -d ravenmaskos -c 'SELECT phone_number, window_expires_at, last_inbound_at FROM whatsapp_sessions ORDER BY last_inbound_at DESC LIMIT 5;'"
# Check Redis connectivity
ssh ravenhelm@100.115.101.81 "docker exec redis redis-cli ping"
Common Operations
Add User Phone Number
# Find user
ssh ravenhelm@100.115.101.81 "docker exec -i postgres psql -U ravenhelm -d ravenmaskos -c \"SELECT user_id, display_name, email FROM users;\""
# Add phone number (E.164 format)
ssh ravenhelm@100.115.101.81 "docker exec -i postgres psql -U ravenhelm -d ravenmaskos -c \"UPDATE users SET phone_number = '+1XXXXXXXXXX' WHERE user_id = 'uuid-here';\""
Send Test Template Message
curl -X POST "https://norns-pm.ravenhelm.dev/api/whatsapp/send" \
-H "X-API-Key: $NORNS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"user_id": "701973d2-57e4-4c84-a2ec-ded996dcf676",
"template_name": "task_reminder",
"variables": {
"task_name": "Test reminder",
"due_time": "now"
}
}'
Check Session Window Status
# Via API
curl "https://norns-pm.ravenhelm.dev/api/whatsapp/session/+1234567890" \
-H "X-API-Key: $NORNS_API_KEY" | jq
# Via database
ssh ravenhelm@100.115.101.81 "docker exec -i postgres psql -U ravenhelm -d ravenmaskos -c \"SELECT *, CASE WHEN window_expires_at > NOW() THEN 'IN_WINDOW' ELSE 'OUTSIDE_WINDOW' END as status FROM whatsapp_sessions WHERE phone_number = '+1234567890';\""
View Twilio Message Logs
# Recent messages (via Twilio CLI)
twilio api:messaging:v1:messages:list --limit 10
# Messages to/from specific number
twilio api:messaging:v1:messages:list --to "whatsapp:+1234567890" --limit 5
Troubleshooting
Issue: Messages Not Being Received
Symptoms: User sends WhatsApp message, no response from Norns
Diagnosis:
-
Check if webhook is receiving requests:
ssh ravenhelm@100.115.101.81 "docker logs norns-agent 2>&1 | grep 'whatsapp/webhook' | tail -10" -
Check Twilio webhook configuration:
- Go to Twilio Console → Messaging → WhatsApp Sandbox
- Verify webhook URL:
https://norns-pm.ravenhelm.dev/whatsapp/webhook
-
Verify sandbox membership:
- User must send
join <code>to sandbox number - Check Twilio Console for sandbox participants
- User must send
Resolution:
- If webhook not configured: Update Twilio sandbox settings
- If user not in sandbox: Have user rejoin with
join <code> - If webhook errors: Check Norns container logs for stack traces
Issue: Template Messages Failing
Symptoms: Proactive messages not delivered, API returns error
Diagnosis:
-
Check template SID is configured:
ssh ravenhelm@100.115.101.81 "docker exec norns-agent env | grep WA_TEMPLATE_TASK_REMINDER" -
Verify template exists in Twilio:
twilio api:content:v1:content:fetch --sid HX685da4c35863ed1180fb46bb8e99004b -
Check variable mapping:
- API uses named variables:
{"task_name": "...", "due_time": "..."} - Template uses positional:
{"1": "...", "2": "..."}
- API uses named variables:
Resolution:
- If SID missing: Add to
secrets/.envand restart container - If template doesn't exist: Create new template via Twilio API
- If variable mismatch: Update
template_manager.pyvariable mapping
Issue: Session Window Not Tracking
Symptoms: All messages require templates, window never opens
Diagnosis:
-
Check Redis is running:
ssh ravenhelm@100.115.101.81 "docker exec redis redis-cli ping" -
Check session table:
ssh ravenhelm@100.115.101.81 "docker exec -i postgres psql -U ravenhelm -d ravenmaskos -c 'SELECT * FROM whatsapp_sessions;'" -
Check session tracker logs:
ssh ravenhelm@100.115.101.81 "docker logs norns-agent 2>&1 | grep -i session | tail -20"
Resolution:
- If Redis down: Restart Redis container
- If no sessions: Verify
record_inbound()is being called in webhook handler - If expired immediately: Check server time sync
Issue: User Not Found by Phone
Symptoms: Webhook receives message but can't resolve user
Diagnosis:
-
Check phone format (must be E.164):
ssh ravenhelm@100.115.101.81 "docker logs norns-agent 2>&1 | grep 'resolve_user' | tail -5" -
Check user has phone number:
ssh ravenhelm@100.115.101.81 "docker exec -i postgres psql -U ravenhelm -d ravenmaskos -c \"SELECT user_id, phone_number FROM users WHERE phone_number IS NOT NULL;\""
Resolution:
- Add phone number to user record with correct E.164 format
Restart Procedures
Restart Norns Container
ssh ravenhelm@100.115.101.81 "cd ~/ravenhelm/docs/AI-ML-Platform/norns-agent && docker compose restart norns"
# Verify restart
ssh ravenhelm@100.115.101.81 "docker logs norns-agent 2>&1 | tail -20"
Full Stack Restart
ssh ravenhelm@100.115.101.81 "cd ~/ravenhelm/docs/AI-ML-Platform/norns-agent && docker compose down && docker compose up -d"
Twilio Sandbox Management
View Sandbox Settings
- Go to Twilio Console
- Navigate to: Messaging → Try it out → Send a WhatsApp message
- Note sandbox code and webhook URLs
Update Sandbox Webhooks
- When a message comes in:
https://norns-pm.ravenhelm.dev/whatsapp/webhook - Status callback URL:
https://norns-pm.ravenhelm.dev/whatsapp/status
Add New Sandbox Participant
- Share sandbox join code with user
- User sends
join <code>to +1 415 523 8886 - User receives confirmation
- Add phone number to their user record in database
Template Management
List All Templates
twilio api:content:v1:content:list
Create New Template
curl -X POST "https://content.twilio.com/v1/Content" \
-u "$TWILIO_ACCOUNT_SID:$TWILIO_AUTH_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"friendly_name": "new_template_name",
"language": "en",
"variables": {"1": "variable_name"},
"types": {
"twilio/text": {
"body": "Your message with {{1}}"
}
}
}'
After creating, add the returned SID to:
secrets/.envasWA_TEMPLATE_NEW_NAME=HXXXXXXXXXXXdocker-compose.ymlenvironment sectiontemplate_manager.pytemplate registry- Restart Norns container
Delete Template
twilio api:content:v1:content:remove --sid HXXXXXXXXXXX
Monitoring
Key Metrics to Watch
- Webhook Response Time - Should be < 1s
- Message Delivery Rate - Check Twilio dashboard
- Session Window Coverage - % of messages sent in-window vs template
Log Locations
| Log | Command |
|---|---|
| Norns WhatsApp | docker logs norns-agent 2>&1 | grep -i whatsapp |
| Twilio webhooks | Twilio Console → Monitor → Logs |
| Database queries | docker logs postgres 2>&1 |
Related Documentation
- [[AI-ML-Platform/Norns-WhatsApp-Channel|WhatsApp Channel Overview]]
- [[AI-ML-Platform/Norns-Agent|Norns Agent]]
- [[AI-ML-Platform/Norns-Telephony|Norns Telephony]]