Files
alfred-mobile/AGENT_TOOLS.md
jknapp 6d4ae2e5c3 Initial commit: Alfred Mobile - AI Assistant Android App
- OAuth authentication via Authentik
- WebSocket connection to OpenClaw gateway
- Configurable gateway URL with first-run setup
- User preferences sync across devices
- Multi-user support with custom assistant names
- ElevenLabs TTS integration (local + remote)
- FCM push notifications for alarms
- Voice input via Google Speech API
- No hardcoded secrets or internal IPs in tracked files
2026-02-09 11:12:51 -08:00

12 KiB

Agent Tools - Mobile Notifications & Alarms

Alfred can send notifications, alerts, and alarms directly to your mobile device using FCM!

Overview

The Alfred mobile app supports receiving notifications even when the app is closed, screen is locked, or device is asleep. This enables:

  • Alarms - High-priority notifications that wake the device
  • Instant alerts - Get notified when tasks complete
  • Timers - Set countdown notifications
  • Reminders - Schedule notifications for specific times
  • Background work - Alfred can notify you when long-running tasks finish

Key Features:

  • FCM Push Notifications - Delivery guaranteed even when app is closed
  • Token Persistence - Works after proxy restarts
  • Dual Delivery - WebSocket (if connected) + FCM (always)
  • Wake on Alarm - Device wakes for high-priority alarms

Features

What's Working

  1. Instant Notifications - Alfred can send alerts immediately
  2. System Notifications - Show even when app is backgrounded
  3. In-App Display - Notifications appear in chat when app is open
  4. Multiple Notification Types - Alert (⚠️), Timer (), Reminder (🔔)
  5. Optional TTS - Speak notifications when TTS is enabled (foreground only)
  6. WebSocket Broadcast - All connected mobile devices receive notifications

📱 Mobile App Features

  • Background Notifications - Receive notifications even when app is closed
  • Notification Icons - Visual indicators for different notification types
  • System Tray - Notifications appear in Android notification shade
  • Tap to Open - Tapping notification opens the app
  • Auto-dismiss - Notifications clear when tapped

Usage from Alfred

Send Alarms

Use alfred-notify for all notifications and alarms.

# High-priority alarm (wakes device)
alfred-notify --alarm "Wake up!"

# Alarm with custom title
alfred-notify --alarm --title "⏰ Morning Alarm" "Time to get up!"

# Silent alarm (vibrate only)
alfred-notify --alarm --no-sound "Silent wake-up"

Send Notifications

# Basic notification
alfred-notify "Task completed successfully"

# Notification with custom title
alfred-notify --title "Build System" "Compilation finished"

# Silent notification
alfred-notify --no-sound --no-vibrate "Background update complete"

Schedule via Cron

For scheduled alarms/reminders, use the cron tool:

// Set alarm for 5 minutes from now
{
  "name": "5 minute alarm",
  "schedule": {
    "kind": "at",
    "atMs": Date.now() + (5 * 60 * 1000)
  },
  "payload": {
    "kind": "agentTurn",
    "message": "Run: alfred-notify --alarm '⏰ 5 minute alarm!'",
    "deliver": false
  },
  "sessionTarget": "isolated"
}

Important: Always use sessionTarget: "isolated" + agentTurn for alarms, never systemEvent.

Alfred Integration

Alfred uses alfred-notify from cron jobs or via exec tool:

Example conversation:

You: "Set an alarm for 5 minutes"
Alfred: *schedules cron job* "I'll send an alarm in 5 minutes!"

Behind the scenes, Alfred creates a cron job:

cron.add({
  schedule: { kind: "at", atMs: Date.now() + 300000 },
  payload: { 
    kind: "agentTurn",
    message: "Run: alfred-notify --alarm '⏰ 5 minute alarm!'"
  },
  sessionTarget: "isolated"
})

Another example:

You: "Let me know when the build finishes"
Alfred: "Sure, I'll notify you when it completes"

Alfred monitors the build and executes:

exec(['alfred-notify', '--title', 'Build System', 'Build completed! ✅'])

Technical Details

Architecture

┌─────────────────┐
│     Alfred      │ (OpenClaw agent)
│    exec/cron    │
└────────┬────────┘
         │ executes
         ▼
┌─────────────────┐
│ alfred-notify   │ (CLI wrapper)
│   bash script   │
└────────┬────────┘
         │ HTTP POST
         ▼
┌─────────────────┐
│  Alfred Proxy   │ (port 18790)
│   + Firebase    │
│   Admin SDK     │
└────────┬────────┘
         │
         ├──────────────────────┬─────────────────────┐
         │ WebSocket            │ FCM Push            │
         │ (if connected)       │ (always)            │
         ▼                      ▼                     ▼
┌─────────────────┐   ┌─────────────────┐   ┌─────────────────┐
│  Mobile App(s)  │   │ Firebase Cloud  │   │  fcm-tokens     │
│  GatewayClient  │   │   Messaging     │   │  .json (disk)   │
└────────┬────────┘   └────────┬────────┘   └─────────────────┘
         │                     │
         │                     ▼
         │            ┌─────────────────┐
         │            │  Mobile Device  │
         │            │  (even asleep)  │
         │            └────────┬────────┘
         │                     │
         └─────────────────────┘
                      │
                      ▼
            ┌─────────────────┐
            │   Android OS    │ (system notifications)
            └─────────────────┘

Key Features:

  • Dual Delivery: WebSocket (instant if connected) + FCM (guaranteed)
  • Token Persistence: FCM tokens saved to fcm-tokens.json, survive restarts
  • Wake Device: FCM can wake locked/sleeping devices for alarms
  • Firebase Admin SDK: Uses cloudmessaging.messages.create permission

Event Format

{
  "type": "event",
  "event": "mobile.notification",
  "payload": {
    "notificationType": "alert|timer|reminder",
    "title": "Alfred",
    "message": "Notification text",
    "priority": "default",
    "sound": true,
    "vibrate": true,
    "timestamp": 1706918400000,
    "action": null
  }
}

Mobile App Handling

  1. GatewayClient receives mobile.notification event via WebSocket
  2. MainScreen onNotification() callback processes the event
  3. Notification icons added based on type ( ⚠️ 🔔 📢)
  4. System notification shown if timer/reminder OR if app is backgrounded
  5. Chat message added if app is in foreground
  6. Optional TTS speaks the notification if enabled (foreground only)

Testing

Test Instant Notification

From terminal:

cd ~/.openclaw/workspace/alfred-proxy
./alfred-notify "Test notification!"

Test Alarm

./alfred-notify --alarm "Test alarm!"

Test with Custom Title

./alfred-notify --title "Kitchen Timer" "Oven is ready!"

Test Silent Notification

./alfred-notify --no-sound --no-vibrate "Silent test"

Test via Alfred

Ask Alfred:

"Send me a test alarm"
"Set an alarm for 1 minute"
"Notify me when this finishes"

Monitoring

Check Proxy Status

# Service status
systemctl --user status alfred-proxy.service

# Watch logs
tail -f /tmp/alfred-proxy.log

# Check for FCM token registration
grep "fcm.*Registering" /tmp/alfred-proxy.log

# Check for successful sends
grep "fcm.*Successfully" /tmp/alfred-proxy.log

Check Connected Clients & Tokens

When app connects, you'll see:

[proxy] New connection from ::ffff:192.168.1.20
[auth] Token validated for user: shadow@dao-mail.com
[fcm] Registering token for user a2b49b91...: ewqRvIsOTuiWJk...
[fcm] Saved tokens to disk

Check Token Persistence

# View persisted FCM tokens
cat ~/.openclaw/workspace/alfred-proxy/fcm-tokens.json

# Should show:
{
  "user-id-hash": [
    "fcm-token-string"
  ]
}

Test Notification Delivery

# Via CLI (recommended)
alfred-notify --alarm "Test"

# Via HTTP API
curl -X POST http://localhost:18790/api/notify \
  -H "Content-Type: application/json" \
  -d '{
    "notificationType": "alarm",
    "title": "Test",
    "message": "Hello!",
    "priority": "high",
    "sound": true,
    "vibrate": true
  }'

Expected response:

{"success":true,"clients":0,"fcm":1}
  • clients: WebSocket connections (0 if app closed)
  • fcm: FCM devices notified (should be 1+)

Troubleshooting

No notifications appearing

  1. Check FCM tokens persisted:

    cat alfred-proxy/fcm-tokens.json
    # Should show registered tokens
    
  2. Check proxy logs for FCM success:

    tail -f /tmp/alfred-proxy.log | grep fcm
    # Should show: [fcm] Successfully sent X message(s)
    
  3. If seeing "Permission denied" error:

    [fcm] Error: Permission 'cloudmessaging.messages.create' denied
    
    • Check service account has correct role: Firebase Admin SDK Administrator Service Agent
    • Verify FCM API is enabled in Google Cloud Console
    • Regenerate service account key if needed
  4. If "No FCM tokens registered":

    • Open Alfred app to trigger token registration
    • Check logs for [fcm] Registering token
    • Verify app sends token on connect (should happen automatically)
  5. Test directly:

    alfred-notify --alarm "Test"
    

WebSocket vs FCM

  • WebSocket: Instant delivery when app is open and connected
  • FCM: Always works, even when app is closed or device is asleep
  • Both should show in response: {"clients":1,"fcm":1}

If clients:0, fcm:1 → App closed but FCM working (normal)
If clients:0, fcm:0 → No tokens registered (open app to fix)

Cron alarms not firing

  1. Verify cron job uses correct format:

    // ✅ CORRECT
    {
      "sessionTarget": "isolated",
      "payload": {
        "kind": "agentTurn",
        "message": "Run: alfred-notify --alarm 'Message'"
      }
    }
    
    // ❌ WRONG
    {
      "sessionTarget": "main",
      "payload": {
        "kind": "systemEvent",
        "text": "Alarm message"
      }
    }
    
  2. Check cron job exists:

    # Ask Alfred in chat
    /cron list
    
  3. Check cron execution logs:

    tail -f /tmp/alfred-proxy.log
    # Look for cron execution and alfred-notify calls
    

Firebase Permission Errors

Error: Permission 'cloudmessaging.messages.create' denied

Solution:

  1. Verify service account role: Firebase Admin SDK Administrator Service Agent (NOT "Firebase Cloud Messaging Admin")
  2. Enable FCM API: https://console.cloud.google.com/apis/library/fcm.googleapis.com
  3. Download fresh service account key
  4. Place at: alfred-proxy/service-account.json
  5. Restart proxy: systemctl --user restart alfred-proxy.service

See FCM_SETUP.md for full setup instructions.

Future Enhancements

Potential additions:

  • Custom sounds - Per-notification sound selection
  • Action buttons - "Snooze", "Mark as done", etc.
  • Deep links - Open specific app screens from notification
  • Rich content - Images, progress bars, etc.
  • Notification groups - Collapse similar notifications
  • Do Not Disturb - Respect user quiet hours
  • Multi-device sync - Mark as read across devices

Version

1.0.0 - Initial release with alert/timer/reminder support