This project is a Pipecat-based chatbot that integrates with Twilio to make outbound calls with personalized call information. The project includes FastAPI endpoints for initiating outbound calls and handling WebSocket connections with call context.
When you want to make an outbound call:
- Send POST request:
POST /dialoutwith a phone number to call - Server initiates call: Uses Twilio's REST API to make the outbound call
- Call answered: When answered, Twilio fetches TwiML from your server's
/twimlendpoint - Server returns TwiML: Tells Twilio to start a WebSocket stream to your bot
- WebSocket connection: Audio streams between the called person and your bot
- Call information: Phone numbers are passed via TwiML Parameters to your bot
curl request → /dialout endpoint → Twilio REST API → Call initiated →
TwiML fetched → WebSocket connection → Bot conversation
- A Twilio account with:
- Account SID and Auth Token
- A purchased phone number that supports voice calls
- Google API key for the LLM inference
- Deepgram API key for speech-to-text
- Cartesia API key for text-to-speech
- Python 3.10+
uvpackage manager- ngrok (for local development)
- Docker (for production deployment)
- Set up a virtual environment and install dependencies:
cd outbound
uv sync- Get your Twilio credentials:
- Account SID & Auth Token: Found in your Twilio Console Dashboard
- Phone Number: Purchase a phone number that supports voice calls
- Set up environment variables:
cp env.example .env
# Edit .env with your API keysThe bot supports two deployment modes controlled by the ENV variable:
- Uses your local server or ngrok URL for WebSocket connections
- Default configuration for development and testing
- WebSocket connections go directly to your running server
- Uses Pipecat Cloud WebSocket URLs automatically
- Requires
AGENT_NAMEandORGANIZATION_NAMEfrom your Pipecat Cloud deployment - Set these when deploying to production environments
- WebSocket connections route through Pipecat Cloud infrastructure
-
Start the outbound bot server:
uv run server.py
The server will start on port 7860.
-
Using a new terminal, expose your server to the internet (for development)
ngrok http 7860
Tip: Use the
--subdomainflag for a reusable ngrok URL.Copy the ngrok URL (e.g.,
https://abc123.ngrok.io) and updateLOCAL_SERVER_URLin your.envfile. -
No additional Twilio configuration needed
Unlike inbound calling, outbound calls don't require webhook configuration in the Twilio console. The server will make direct API calls to Twilio to initiate calls.
With the server running and exposed via ngrok, you can initiate outbound calls:
curl -X POST https://your-ngrok-url.ngrok.io/dialout \
-H "Content-Type: application/json" \
-d '{
"to_number": "+15551234567",
"from_number": "+15559876543"
}'Replace:
your-ngrok-url.ngrok.iowith your actual ngrok URL+15551234567with the phone number to call (E.164 format)+15559876543with your Twilio phone number (E.164 format)
Note: the
from_numbermust be a phone number owned by your Twilio account
Follow the quickstart instructions to deploy your bot to Pipecat Cloud.
Update your production .env file with the Pipecat Cloud details:
# Set to production mode
ENV=production
# Your Pipecat Cloud deployment details
AGENT_NAME=your-agent-name
ORGANIZATION_NAME=your-org-name
# Keep your existing Twilio and AI service keysThe server.py handles outbound call initiation and should be deployed separately from your bot:
- Bot: Runs on Pipecat Cloud (handles the conversation)
- Server: Runs on your infrastructure (initiates calls, serves TwiML responses)
When ENV=production, the server automatically routes WebSocket connections to your Pipecat Cloud bot.
Alternatively, you can test your Pipecat Cloud deployment by running your server locally.
As you did before, initiate a call via curl command to trigger your bot to dial a number.
Your bot automatically receives call information through Twilio Stream Parameters. In this example, the phone numbers (to_number and from_number) are passed as parameters and extracted by the parse_telephony_websocket function.
You can extend the DialoutRequest model in server_utils.py to include additional custom data (customer info, campaign data, etc.) and pass it through as stream parameters for personalized conversations. See bot.py for implementation details.