Appearance
Local Development
Prerequisites
- Python 3.12+
- Node.js 20+
- Docker and Docker Compose
Initial Setup
bash
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .envEdit .env with your credentials. See Configuration for all variables.
Start Infrastructure
bash
docker compose up -d postgres redisDatabase Setup
bash
source .venv/bin/activate
alembic upgrade head
python scripts/seed.pyThe seed script creates default agents, tools, and flow nodes.
Run the Backend
bash
source .venv/bin/activate
python main.pyOr with uvicorn directly:
bash
uvicorn api.app:app --host 127.0.0.1 --port 8000 --log-level infoThe API will be available at http://localhost:8000. Interactive docs at http://localhost:8000/docs.
Run the Dashboard
bash
cd dashboard
npm install
npm run devThe dashboard uses VITE_API_URL (defaults to http://localhost:8000/api).
Public URL for Telephony
All telephony providers need a public HTTPS URL. For local development, use a tunnel:
bash
# ngrok
ngrok http 8000
# cloudflared
cloudflared tunnel --url http://localhost:8000Then set in .env:
env
PUBLIC_BASE_URL=https://your-tunnel-url.comProvider-Specific Setup
Twilio
Point your Twilio phone number's Voice webhook to:
POST https://your-tunnel-url.com/telephony/twilio/inbound/{agent_name}Exotel
- Create a Voicebot applet in Exotel App Bazaar
- Set the webhook URL to:
POST https://your-tunnel-url.com/telephony/exotel/inbound/{agent_name} - Assign the applet to your virtual number
Vobiz
Configure your Vobiz number's inbound webhook to:
POST https://your-tunnel-url.com/telephony/vobiz/inbound/{agent_name}See Telephony for full provider details.
Smoke Tests
bash
# Health check
curl http://127.0.0.1:8000/api/health
# List agents
curl http://127.0.0.1:8000/api/agents
# List calls
curl http://127.0.0.1:8000/api/calls
# Test outbound call
curl -X POST http://127.0.0.1:8000/api/calls/outbound \
-H "Content-Type: application/json" \
-d '{
"phone_number": "+1234567890",
"agent_name": "sales-agent"
}'Common Commands
Reset database
bash
docker compose exec postgres psql -U postgres -d voiceagent \
-c "DROP SCHEMA public CASCADE; CREATE SCHEMA public;"
alembic upgrade head
python scripts/seed.pyRun syntax checks
bash
python3 -m compileall agent api config workers main.py scriptsBuild dashboard for production
bash
cd dashboard
npm run buildThe built files in dashboard/dist/ are served by the FastAPI app at /.
Environment Variables
Minimum for backend startup
env
DATABASE_URL=postgresql+asyncpg://postgres:postgres@localhost:5432/voiceagent
REDIS_URL=redis://localhost:6379Minimum for live calls (add one telephony provider + AI services)
env
PUBLIC_BASE_URL=https://your-tunnel-url.com
# Telephony (pick one)
TELEPHONY_PROVIDER=twilio
TWILIO_ACCOUNT_SID=AC...
TWILIO_AUTH_TOKEN=...
TWILIO_PHONE_NUMBER=+1...
# STT
DEEPGRAM_API_KEY=...
# LLM
OPENAI_API_KEY=...
# TTS
CARTESIA_API_KEY=...See Configuration for the complete list.
Troubleshooting
Cannot connect to the Docker daemon
Start Docker Desktop or your local Docker daemon, then rerun docker compose up -d postgres redis.
No module named 'greenlet'
Reinstall dependencies: pip install -r requirements.txt
Telephony provider cannot reach the webhook
- Verify the tunnel is running
- Verify
PUBLIC_BASE_URLmatches the tunnel URL - Check the provider is configured to use
POST - Check the agent name in the URL exists in the database
Outbound call API returns 500
Common causes:
- Missing provider credentials (SID, auth token, etc.)
- Missing phone number and no
caller_idin the request - Invalid
PUBLIC_BASE_URL(WebSocket URL can't be built)
Dashboard loads but shows empty data
- Check
VITE_API_URLif using the dev server - Check backend CORS settings
- Verify database has seeded data