# Vapi Voice Assistant Setup - Rivet

## Overview
Rivet is an AI voice assistant powered by Vapi that allows Michael to call a phone number, speak tasks naturally, hang up, and get notified when tasks are complete.

## Architecture

```
┌──────────────┐
│ Michael calls│
│ +61238205443 │
└──────┬───────┘
       │
       ▼
┌──────────────────┐
│  Vapi Assistant  │  ← Handles conversation, STT, NLU
│  (Rachel voice)  │
│  ID: 430ea486... │
└──────┬───────────┘
       │ POST webhook on call end
       │ (includes full transcript)
       ▼
┌───────────────────────────────┐
│ /api/vapi/webhook             │
│ - Extract task from transcript│
│ - Queue for async execution   │
│ - Respond with confirmation   │
└───────┬───────────────────────┘
        │
        ▼
┌───────────────────────────────┐
│ Background Task Processor     │
│ - Execute task (API call, etc)│
│ - Track completion            │
└───────┬───────────────────────┘
        │
        ▼
┌───────────────────────────────┐
│ Notification System           │
│ - SMS: "Task XYZ is done"     │
│ - Or call back with results   │
└───────────────────────────────┘
```

## Setup Instructions

### 1. Database Migration

The `vapi_tasks` table needs to be created in Supabase.

**Run this SQL in Supabase Dashboard → SQL Editor:**

```sql
-- Located at: supabase/migrations/20260131124216_vapi_tasks.sql
-- Copy/paste the full contents of that file
```

**Verify migration:**
```sql
SELECT * FROM vapi_tasks LIMIT 1;
-- Should return empty result (no errors)
```

### 2. Environment Variables

Add to Railway environment variables:

```bash
# From ~/.env.rateright-phone
VAPI_API_KEY=5158a9b5-8415-4927-bd99-3ae14235de90
VAPI_PUBLIC_KEY=904af378-1d7a-40b2-aa02-cfbafb39fe9a

# Assistant and phone IDs
VAPI_ASSISTANT_ID=430ea486-efd5-44f6-b418-f58fbbcc360b
VAPI_PHONE_NUMBER_ID=e595dd71-4918-4411-bebd-cfd529c66216

# Notification recipient
MICHAEL_PHONE=+61... # Michael's mobile for task notifications
```

**Verify in Railway:**
1. Go to Railway dashboard → rateright-growth-production
2. Settings → Variables
3. Add all VAPI_* and MICHAEL_PHONE variables
4. Deploy

### 3. Configure Vapi Assistant

Log in to Vapi Dashboard: https://dashboard.vapi.ai

**A. Set Webhook URL**
1. Navigate to Assistants → Select assistant ID `430ea486-efd5-44f6-b418-f58fbbcc360b`
2. Go to "Server Messages" or "Webhooks" section
3. Set webhook URL: `https://rateright-growth-production.up.railway.app/api/vapi/webhook`
4. Enable events: `end-of-call-report`
5. Save

**B. Update System Prompt**
```
You are Rivet, Michael's AI assistant for RateRight Growth.

Your job:
1. Listen to Michael's task request
2. Confirm you understand the task
3. End the call politely

Be brief, professional, and efficient. Don't ask follow-up questions unless critical information is missing.

Examples:
- "Call John at ABC Company" → "Got it, I'll create a callback for John at ABC Company."
- "Text Sarah about the quote" → "Understood, I'll send a message to Sarah about the quote."
- "Mark lead XYZ as hot" → "I'll mark XYZ as a hot lead right away."
```

**C. Voice Settings**
- Voice: Rachel (already configured)
- Speed: 1.0
- Language: en-AU (Australian English)

**D. Phone Number**
- Should already be configured: +61238205443
- Verify in Phone Numbers section

### 4. Test End-to-End

**Local Testing with ngrok:**
```bash
# On VPS
ngrok http 3000

# Copy ngrok URL (e.g., https://abc123.ngrok.io)
# Update Vapi webhook temporarily to: https://abc123.ngrok.io/api/vapi/webhook
# Call +61238205443 and test
# Check logs: tail -f logs/app.log | grep Vapi
```

**Production Testing:**
1. Ensure Railway deployment is complete
2. Call +61238205443
3. Say: "Call John Smith at ABC Company"
4. Hang up
5. Check database: `SELECT * FROM vapi_tasks ORDER BY created_at DESC LIMIT 1;`
6. Verify SMS notification received
7. Check task execution: `SELECT status, result FROM vapi_tasks WHERE id = '...'`

### 5. Monitor & Debug

**Check Vapi Dashboard:**
- Logs → Recent calls
- View transcript
- Check webhook delivery

**Check Railway Logs:**
```bash
# Look for:
[Vapi Webhook] Received event: end-of-call-report
[TaskParser] Parsed task: call_lead
[TaskExecutor] Starting task ...
[TaskExecutor] Task ... completed
[Notifications] SMS sent to +61...
```

**Check Database:**
```sql
-- Recent tasks
SELECT id, task_type, task_description, status, created_at
FROM vapi_tasks
ORDER BY created_at DESC
LIMIT 10;

-- Failed tasks
SELECT id, task_description, error_message, created_at
FROM vapi_tasks
WHERE status = 'failed'
ORDER BY created_at DESC;

-- Pending tasks (stuck?)
SELECT id, task_description, created_at
FROM vapi_tasks
WHERE status = 'pending'
AND created_at < NOW() - INTERVAL '5 minutes'
ORDER BY created_at DESC;
```

**Admin Endpoints:**
```bash
# List recent tasks
GET /api/vapi/tasks?status=completed&limit=10

# Retry a failed task
POST /api/vapi/tasks/{task_id}/retry

# Check Vapi configuration status
GET /api/vapi/status
```

## Task Types Supported

| Type | Example Command | What It Does |
|------|-----------------|--------------|
| `call_lead` | "Call John at ABC Company" | Creates high-priority callback |
| `send_message` | "Text Sarah about the quote" | Sends SMS to lead |
| `update_lead` | "Mark John as hot" | Updates lead status/score |
| `create_callback` | "Callback with Tim tomorrow" | Schedules callback |
| `get_report` | "Get today's call stats" | Fetches and reports stats |
| `add_note` | "Note: Follow up on pricing" | Saves note to dev_queue |
| `custom` | Anything else | Queues for manual review |

## Task Parser Logic

1. **Pattern Matching** - Fast keyword matching for common commands
2. **AI Fallback** - GPT-4o-mini parses complex/ambiguous requests
3. **Entity Extraction** - Pulls out names, phone numbers, dates, topics

## Notification Strategy

| Priority | Method | Timing |
|----------|--------|--------|
| `urgent` | SMS (call TBD) | Immediate |
| `normal` | SMS | After task completion |
| `low` | None | Silent (check admin) |

Priority is set based on:
- `urgent`: "mark hot" commands
- `normal`: Most tasks (call, text, callback)
- `low`: Reports, notes

## Error Handling

**Failed Tasks:**
1. Status set to `failed`
2. `error_message` column populated
3. Notification sent if priority = `urgent`
4. Manual retry available via `/api/vapi/tasks/{id}/retry`

**Unknown Commands:**
1. Saved as `task_type: custom`
2. Added to `dev_queue` for manual review
3. Full transcript preserved

## Future Enhancements

- [ ] Vapi outbound calls for urgent notifications
- [ ] Multi-user support (different callers)
- [ ] Task priority override via voice command
- [ ] Integration with Notion task tracker
- [ ] Voice confirmation before executing critical tasks
- [ ] Task history review via voice command

## Troubleshooting

**Issue: Webhook not receiving events**
- Check Vapi dashboard → Logs → Webhook delivery
- Verify webhook URL is correct
- Test with ngrok for local debugging

**Issue: Task parser not understanding commands**
- Check transcript in vapi_tasks table
- Review pattern matching in `src/services/taskParser.js`
- Add custom patterns or improve AI prompt

**Issue: Task execution failing**
- Check `error_message` in vapi_tasks table
- Review logs for specific error
- Verify database permissions (RLS)
- Check that required data exists (leads, phone numbers)

**Issue: Notifications not sending**
- Verify MICHAEL_PHONE environment variable
- Check Twilio SMS limits/balance
- Review notification logs in Railway

## API Reference

### POST /api/vapi/webhook
Receives Vapi webhook events. Handles `end-of-call-report`.

**Request:** (From Vapi)
```json
{
  "type": "end-of-call-report",
  "call": {
    "id": "...",
    "customer": { "number": "+61...", "name": "Michael" },
    "duration": 45,
    "endedReason": "customer-ended-call"
  },
  "transcript": "Call John at ABC Company",
  "recordingUrl": "https://..."
}
```

**Response:**
```json
{ "received": true }
```

### GET /api/vapi/tasks
List recent tasks (admin).

**Query Params:**
- `status` - Filter by status (pending/executing/completed/failed)
- `limit` - Max results (default: 50)

**Response:**
```json
{
  "tasks": [
    {
      "id": "...",
      "task_type": "call_lead",
      "task_description": "Call John at ABC Company",
      "status": "completed",
      "result": { "success": true, "summary": "..." },
      "created_at": "2026-01-31T12:00:00Z"
    }
  ]
}
```

### POST /api/vapi/tasks/:id/retry
Retry a failed task.

**Response:**
```json
{ "success": true, "message": "Task queued for retry" }
```

### GET /api/vapi/status
Check Vapi configuration.

**Response:**
```json
{
  "configured": true,
  "hasApiKey": true,
  "hasPublicKey": true,
  "hasAssistantId": true,
  "hasPhoneNumberId": true
}
```

## Files Reference

| File | Purpose |
|------|---------|
| `src/routes/vapi.js` | Webhook endpoint + admin API |
| `src/services/taskParser.js` | Parse transcript → structured task |
| `src/services/taskExecutor.js` | Execute tasks (call, SMS, etc) |
| `src/services/notifications.js` | Send completion notifications |
| `supabase/migrations/20260131124216_vapi_tasks.sql` | Database schema |

## Support

For issues or questions:
1. Check Railway logs
2. Check Vapi dashboard logs
3. Query `vapi_tasks` table in Supabase
4. Review this documentation
5. Contact dev team with logs

---

**Last Updated:** 2026-01-31
**Status:** ✅ Built, pending testing
