A voice-based AI assistant that helps friend groups plan festival trips together. Users call in via phone, and the AI helps them form groups, pick festivals, track members, and coordinate plans — all through natural conversation.
The system is split into three services:
The core of the product. A real-time voice pipeline built with Pipecat that handles phone calls end-to-end:
- Telephony via Twilio — receives inbound calls, identifies callers by phone number
- Speech-to-Text / Text-to-Speech via Cartesia
- Conversation via Anthropic Claude (Haiku 4.5) — the LLM drives the dialogue and calls tools to save groups, members, festivals, and artists to the database
- Smart turn detection using Pipecat's
LocalSmartTurnAnalyzerV3+ Silero VAD to know when the user has finished speaking - Local dev via Daily WebRTC transport for browser-based testing without a phone
On disconnect, the bot summarizes the full transcript via a separate Claude API call and persists it.
A FastAPI server exposing CRUD endpoints over the database. Serves as the data layer for the frontend.
- Group-scoped endpoints:
/groups/{id}/members,/groups/{id}/festivals - Festival catalog:
/festival-catalogfor browsing available festivals - Standard CRUD for groups, members, festivals, artists, and calls
A React + TypeScript single-page app for managing groups and festivals visually.
- Vite for builds and dev server
- Tailwind CSS v4 + shadcn/ui for styling
- Home page with a group grid and a multi-step wizard to create new groups (name, members, festival selection)
- Group detail page showing members and festivals
| Layer | Technology |
|---|---|
| Voice pipeline | Pipecat |
| Telephony | Twilio |
| LLM | Anthropic Claude (Haiku 4.5) |
| Speech-to-Text / Text-to-Speech | Cartesia |
| Database | Supabase (Postgres) |
| Observability | Langfuse via OpenTelemetry (OTLP) |
| Backend API | FastAPI |
| Frontend | React + TypeScript + Vite |
| UI components | shadcn/ui + Tailwind CSS v4 |
| Python tooling | uv (package manager), ruff (linter), pyright (type checker) |
- Python >= 3.12
- Node.js >= 18
- uv package manager
Copy the example env file and fill in your keys:
cp .env.example .envSee .env.example for the full list of variables. At minimum you need:
ANTHROPIC_API_KEY— Claude API keyCARTESIA_API_KEY— Cartesia STT/TTS keySUPABASE_URL/SUPABASE_API_KEY— Supabase project credentials
Optional variables for telephony (Twilio) and observability (Langfuse) are documented in the example file.
Local dev (Daily WebRTC — no phone needed):
uv sync
uv run python bot.pyTwilio telephony (receive real phone calls):
- Set
TWILIO_ACCOUNT_SIDandTWILIO_AUTH_TOKENin your.env. - Expose your local server with ngrok:
ngrok http 7860
- In the Twilio Console, create a TwiML Bin with:
Then assign the bin to your Twilio phone number under Voice Configuration.
<?xml version="1.0" encoding="UTF-8"?> <Response> <Connect> <Stream url="wss://<your-ngrok-url>/ws" /> </Connect> </Response>
- Start the bot with the Twilio transport:
uv run python bot.py -t twilio
uv run fastapi dev backend/main.pyRuns at http://localhost:8000.
cd frontend
npm install
npm run devRuns at http://localhost:5173.
Schema is defined in schema.sql. Incremental changes live in migrations/, numbered sequentially. Seed data for development is in seed.sql.
Tables: groups, members, calls, festivals, artists, festival_catalog.
The voice pipeline supports tracing via Langfuse using the OpenTelemetry (OTLP) protocol. When ENABLE_TRACING=true, Pipecat spans (LLM calls, STT/TTS latency, tool invocations) are exported to Langfuse so you can inspect conversations, debug latency, and monitor costs.
To enable tracing, set the following in your .env:
ENABLE_TRACING=true
LANGFUSE_SECRET_KEY=sk-lf-...
LANGFUSE_PUBLIC_KEY=pk-lf-...
LANGFUSE_BASE_URL=https://us.cloud.langfuse.com
OTEL_EXPORTER_OTLP_ENDPOINT=https://us.cloud.langfuse.com/api/public/otel
OTEL_EXPORTER_OTLP_HEADERS=Authorization=Basic <base64-encoded public:secret>
Sign up at langfuse.com and create a project to get your keys. The base64 header value is base64(public_key:secret_key).
The browserbase-client/ directory contains a Node.js scraper built with Stagehand (Browserbase) that extracts festival lineups from official websites. It uses an AI agent to navigate lineup pages and extract artist/stage/time data into CSV and JSON.
See browserbase-client/my-stagehand-app/README.md for setup and usage.