Skip to content

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 .env

Edit .env with your credentials. See Configuration for all variables.

Start Infrastructure

bash
docker compose up -d postgres redis

Database Setup

bash
source .venv/bin/activate
alembic upgrade head
python scripts/seed.py

The seed script creates default agents, tools, and flow nodes.

Run the Backend

bash
source .venv/bin/activate
python main.py

Or with uvicorn directly:

bash
uvicorn api.app:app --host 127.0.0.1 --port 8000 --log-level info

The 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 dev

The 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:8000

Then set in .env:

env
PUBLIC_BASE_URL=https://your-tunnel-url.com

Provider-Specific Setup

Twilio

Point your Twilio phone number's Voice webhook to:

POST https://your-tunnel-url.com/telephony/twilio/inbound/{agent_name}

Exotel

  1. Create a Voicebot applet in Exotel App Bazaar
  2. Set the webhook URL to:
    POST https://your-tunnel-url.com/telephony/exotel/inbound/{agent_name}
  3. 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.py

Run syntax checks

bash
python3 -m compileall agent api config workers main.py scripts

Build dashboard for production

bash
cd dashboard
npm run build

The 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:6379

Minimum 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_URL matches 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_id in the request
  • Invalid PUBLIC_BASE_URL (WebSocket URL can't be built)

Dashboard loads but shows empty data

  • Check VITE_API_URL if using the dev server
  • Check backend CORS settings
  • Verify database has seeded data