Pitch - AI-Powered Voice Trading Assistant
## Inspiration Trading crypto shouldn't require staring at screens 24/7. We wanted to make trading as simple as having a conversation—ask about your portfolio, place orders, check positions, all through voice.
## What We Built A VAPI-powered voice assistant that connects to Liquid's trading API, enabling users to:
- Place crypto trades via voice commands
- Check account balances and positions
- Manage open orders
- All secured with user-specific API credentials stored in Supabase
(NOT SHOWN, BUT THE AGENT CAN DO SMS PHONE CALLS TO THE USER AS WELL)
Tech Stack:
- Backend: Flask (Python) with VAPI webhook integration
- Database: Supabase (PostgreSQL)
- Trading API: Liquid (liquidtrading SDK)
- Voice AI: VAPI with GPT-4o-mini
- Deployment: Ngrok for development, designed for production deployment
## How We Built It
### Architecture User Voice → VAPI → Flask Server (/vapi/*) → Supabase (auth) → Liquid API → Response
### Key Implementation Details
VAPI Integration
- Created custom tool endpoints matching VAPI's specification
- Request format:
message.toolCallList[0].function.arguments - Response format:
{"results": [{"toolCallId": "...", "result": ...}]} - Always return HTTP 200 (errors use
"error"field)
Authentication Flow
# Dual authentication: # 1. Server API key (X-API-Key header) # 2. User phone number → Supabase lookup → Liquid credentials
- Error Handling
- Comprehensive logging at every layer
- Graceful degradation for API failures
- User-friendly error messages via voice
Challenges We Faced
- VAPI Request Format Parsing
Problem: VAPI sends arguments as both JSON strings and objects depending on context # Sometimes: "arguments": "{\"phone_number\": \"+15305747238\"}" # Sometimes: "arguments": {"phone_number": "+15305747238"}
Solution: Created parser to handle both formats def parse_vapi_arguments(args_raw): if isinstance(args_raw, str): return json.loads(args_raw) return args_raw
- Liquid API Authentication
Problem: Intermittent 401 errors due to timestamp-based request signing
- Clock drift between server and API
- Signature generation timing issues
Solution:
- Enhanced logging to track authentication flow
- Validated credentials storage in Supabase
- Added error handling with specific error types
- Rate Limiting
Problem: Hit VAPI's rate limits during development when repeatedly updating tools
Solution:
- Reuse existing tools instead of recreating
- Manual URL updates via VAPI dashboard
- Implemented tool versioning strategy
What We Learned
- Voice AI != Text AI - Speech transcription introduces errors text interfaces don't have. Design around voice limitations.
- Webhook Reliability - External APIs (VAPI, Liquid) can fail. Always:
- Log everything
- Return graceful errors
- Design for retry logic
- Time-based Auth is Hard - Signed requests with timestamps require:
- Synchronized clocks
- Proper request serialization
- Short tolerance windows ($t_{server} - t_{client} < \epsilon$)
- Dual API Design - Maintaining both standard REST (/api/v1/) and VAPI-compliant (/vapi/) endpoints allowed us to:
- Keep existing web client working
- Add voice interface without breaking changes
- Test both interfaces independently
Future Improvements
- Multi-user support with proper phone verification
- Advanced order types (stop-loss, take-profit)
- Portfolio analytics via voice
- Real-time price alerts
- Multi-exchange support
Built with ❤️ for voice-first crypto trading
Built With
- fastapi
- javascript
- next
- python
- render
- twilio
- vapi

Log in or sign up for Devpost to join the conversation.