# Rivet Voice Assistant

Real-time AI phone system using Pipecat. Connects phone calls to Claude (Anthropic) with ElevenLabs voice.

## Architecture

```
Twilio Phone Call
    ↓
Twilio Media Streams (websocket)
    ↓
Deepgram STT (speech-to-text)
    ↓
Claude Opus 4.5 (LLM brain)
    ↓
ElevenLabs TTS (text-to-speech, voice: Charlie)
    ↓
Twilio (back to caller)
```

## Components

- **Pipecat**: Real-time voice pipeline framework
- **Twilio**: Phone system (+61238205443)
- **Deepgram**: Speech-to-text (Australian English)
- **Claude Opus 4.5**: Conversation AI (Anthropic)
- **ElevenLabs**: Text-to-speech (voice ID: IKne3meq5aSn9XLyUdCD - "Charlie")

## Setup

### 1. Install Dependencies

Already done via setup script. Venv at: `/home/ccuser/rateright-growth/voice-assistant/venv`

### 2. Configuration

Credentials are in `.env` (not committed to git):

```bash
# See .env file for full configuration
ANTHROPIC_API_KEY=...
ELEVENLABS_API_KEY=...
TWILIO_ACCOUNT_SID=...
DEEPGRAM_API_KEY=...
```

### 3. Run the Server

**Manual start:**
```bash
cd /home/ccuser/rateright-growth/voice-assistant
source venv/bin/activate
python voice_assistant.py
```

**As systemd service:**
```bash
# Install service
sudo cp rivet-voice.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable rivet-voice
sudo systemctl start rivet-voice

# Check status
sudo systemctl status rivet-voice

# View logs
sudo journalctl -u rivet-voice -f
```

### 4. Configure Twilio Webhook

The voice assistant runs a websocket server on port 8765. Twilio connects to it via Media Streams.

**Webhook URL:** `ws://134.199.153.159:8765/media-stream`

**To configure in Twilio:**

1. Go to: https://console.twilio.com/us1/develop/voice/manage/phone-numbers
2. Select phone number: +61238205443
3. Under "Voice Configuration":
   - **A call comes in:** Webhook
   - **URL:** `http://134.199.153.159:8765/call-webhook`
   - **HTTP Method:** POST
   - Or use TwiML Bin with Stream verb (see below)

**TwiML for Media Streams:**
```xml
<?xml version="1.0" encoding="UTF-8"?>
<Response>
    <Say voice="alice">Connecting to Rivet</Say>
    <Connect>
        <Stream url="ws://134.199.153.159:8765/media-stream"/>
    </Connect>
</Response>
```

### 5. Make an Outbound Call

```bash
cd /home/ccuser/rateright-growth/voice-assistant
source venv/bin/activate
python make_call.py +61426246472
```

This will:
1. Call Michael at +61426246472
2. Connect the call to the voice assistant
3. Start the conversation with Rivet

## System Prompt

Rivet's personality is defined in `voice_assistant.py`:

```
You are Rivet, the COO system for RateRight — a construction hiring marketplace in Australia. 
You're talking on the phone with Michael, the founder.

Be direct, no waffle. Keep responses SHORT (1-2 sentences). 
You're his right hand — you know the business, you push back when needed, you're honest.

RateRight: $50 flat fee per hire. Workers pay nothing. 
Connects contractors with construction workers.

You're not a customer service bot. You're Rivet — Michael's AI COO. Talk like it.
```

## Logs

Logs are written to:
- **Console:** INFO level
- **File:** `logs/YYYY-MM-DD.log` (DEBUG level, 7-day retention)
- **Systemd journal:** `journalctl -u rivet-voice -f`

## Troubleshooting

### Service won't start
```bash
# Check service status
sudo systemctl status rivet-voice

# View recent logs
sudo journalctl -u rivet-voice -n 50

# Test manually
cd /home/ccuser/rateright-growth/voice-assistant
source venv/bin/activate
python voice_assistant.py
```

### No audio / call not connecting
1. Check websocket server is running: `netstat -tlnp | grep 8765`
2. Check Twilio webhook is configured correctly
3. Check firewall allows incoming on port 8765: `sudo ufw status`
4. Test websocket: `wscat -c ws://134.199.153.159:8765/media-stream`

### API errors
- Check `.env` has all required keys
- Verify Anthropic API key is valid: https://console.anthropic.com
- Verify ElevenLabs key: https://elevenlabs.io/app/settings
- Check Deepgram key: https://console.deepgram.com

### Port already in use
```bash
# Find process using port 8765
sudo lsof -i :8765

# Kill if needed
sudo kill <PID>
```

## Testing

### 1. Test inbound call
1. Ensure service is running
2. Call +61238205443 from your phone
3. Should hear "Connecting to Rivet" then connect to voice assistant

### 2. Test outbound call
```bash
python make_call.py +61426246472
```

### 3. Test websocket connection
```bash
# Install wscat if needed
npm install -g wscat

# Connect to websocket
wscat -c ws://localhost:8765/media-stream
```

## Monitoring

### Check service health
```bash
# Service status
sudo systemctl is-active rivet-voice

# Recent logs
sudo journalctl -u rivet-voice --since "5 minutes ago"

# Live log stream
sudo journalctl -u rivet-voice -f
```

### Metrics
Pipecat includes built-in metrics. Enable in code:
```python
params=PipelineParams(
    enable_metrics=True,
    enable_usage_metrics=True,
)
```

## Security

- API keys stored in `.env` (not in git)
- Websocket server only accessible via VPS IP
- Consider adding SSL/TLS for production
- Consider firewall rules to restrict access

## Production Checklist

- [ ] Service running: `systemctl is-active rivet-voice`
- [ ] Twilio webhook configured
- [ ] Firewall allows port 8765
- [ ] SSL certificate (optional but recommended)
- [ ] Log rotation configured
- [ ] Monitoring alerts set up
- [ ] Backup of configuration

## Architecture Decisions

### Why Pipecat?
- Built for real-time voice AI
- Direct integration with Twilio Media Streams
- Handles complex audio pipeline (STT → LLM → TTS)
- Supports interruptions and natural conversation flow

### Why Deepgram over OpenAI Whisper?
- Lower latency for real-time STT
- Better Australian English support
- More cost-effective for continuous streaming

### Why ElevenLabs over alternatives?
- Best voice quality
- "Charlie" voice matches Rivet's personality
- Good Australian accent support

## Future Enhancements

- [ ] Add conversation memory/context
- [ ] Integrate with Growth Engine CRM
- [ ] Add call recording
- [ ] Add analytics dashboard
- [ ] Support multiple simultaneous calls
- [ ] Add voice authentication
- [ ] SMS fallback for failed calls

## Support

For issues or questions:
- Check logs: `sudo journalctl -u rivet-voice -f`
- Review Pipecat docs: https://docs.pipecat.ai
- Twilio Media Streams docs: https://www.twilio.com/docs/voice/twiml/stream

---

**Built with:** Pipecat, Twilio, Claude (Anthropic), ElevenLabs, Deepgram
**Last updated:** 2026-02-04
