Skip to content

Commit 0888e90

Browse files
authored
Merge pull request #369 from pipecat-ai/mb/exotel-guide
Add Exotel guide
2 parents a3c30e6 + 2b41c09 commit 0888e90

File tree

3 files changed

+375
-1
lines changed

3 files changed

+375
-1
lines changed

deployment/pipecat-cloud/guides/telephony/exotel-websocket.mdx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,18 @@ To connect your Pipecat Cloud bot to Exotel's voice network:
102102

103103
To test your integration, simply dial your Exotel phone number from any phone. The call will connect to your Pipecat Cloud bot, which will respond according to your bot's configuration.
104104

105+
### Making Outbound Calls
106+
107+
To initiate outbound calls, refer to the [Exotel WebSocket Integration guide](/guides/telephony/exotel-websockets#dial-out) for complete dial-out implementation details and examples.
108+
109+
## Custom Data Requirements
110+
111+
<Warning>
112+
Currently, there are limitations with passing custom data through query
113+
parameters in Exotel's WebSocket URLs. While the platform theoretically
114+
supports query parameters, they may be stripped during call processing.
115+
</Warning>
116+
105117
## Advanced Call Control
106118

107119
Your bot can control the active call by leveraging Exotel's REST API with the `CallSid` that's automatically provided to your bot. This enables capabilities such as:

docs.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,8 @@
7979
"guides/telephony/twilio-daily-sip",
8080
"guides/telephony/twilio-websockets",
8181
"guides/telephony/telnyx-websockets",
82-
"guides/telephony/plivo-websockets"
82+
"guides/telephony/plivo-websockets",
83+
"guides/telephony/exotel-websockets"
8384
]
8485
}
8586
]
Lines changed: 361 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,361 @@
1+
---
2+
title: "Exotel WebSocket Integration"
3+
sidebarTitle: "Exotel WebSocket"
4+
description: "Complete guide to using Exotel Voice Streaming with Pipecat for dial-in and dial-out functionality"
5+
---
6+
7+
## Things you'll need
8+
9+
- An active [Exotel](https://exotel.com) account with voice streaming enabled
10+
- One or more Exotel provisioned phone numbers
11+
- A public-facing server or tunneling service like [ngrok](https://ngrok.com/) (for dial-out only)
12+
- API keys for speech-to-text, text-to-speech, and LLM services
13+
14+
<CardGroup cols={2}>
15+
<Card
16+
title="Exotel Dial-in Example"
17+
icon="phone-arrow-down-left"
18+
href="https://github.com/pipecat-ai/pipecat-examples/tree/main/exotel-chatbot/inbound"
19+
>
20+
Complete dial-in implementation using Exotel Voice Streaming over WebSocket
21+
</Card>
22+
23+
<Card
24+
title="Exotel Dial-out Example"
25+
icon="phone-arrow-up-right"
26+
href="https://github.com/pipecat-ai/pipecat-examples/tree/main/exotel-chatbot/outbound"
27+
>
28+
Outbound calling using Exotel Voice Streaming with WebSocket transport
29+
</Card>
30+
</CardGroup>
31+
32+
## Phone Number Setup
33+
34+
You'll need Exotel phone numbers for both dial-in and dial-out functionality:
35+
36+
- Visit [exotel.com](https://exotel.com) and purchase phone numbers
37+
- Complete KYC verification if required
38+
- Ensure voice streaming is enabled on your account (contact Exotel support if needed)
39+
40+
## Environment Setup
41+
42+
Configure your environment variables for Exotel and AI services:
43+
44+
```shell .env
45+
EXOTEL_ACCOUNT_SID=...
46+
EXOTEL_API_KEY=...
47+
EXOTEL_API_TOKEN=...
48+
OPENAI_API_KEY=...
49+
DEEPGRAM_API_KEY=...
50+
CARTESIA_API_KEY=...
51+
```
52+
53+
## Dial-in
54+
55+
Dial-in allows users to call your Exotel number and connect to your Pipecat bot via WebSocket Voice Streaming. Unlike other providers, Exotel automatically provides caller information (to/from numbers) in the WebSocket messages, so no custom server is needed for basic dial-in functionality.
56+
57+
### How It Works
58+
59+
Here's the sequence of events when someone calls your Exotel number:
60+
61+
1. **Exotel receives an incoming call** to your phone number
62+
2. **Exotel executes your App Bazaar flow** which includes a Voicebot applet
63+
3. **Exotel opens a WebSocket** to your server with real-time audio and call metadata
64+
4. **Your bot processes the audio** using the Pipecat pipeline
65+
5. **The bot responds with audio** sent back to Exotel over WebSocket
66+
6. **Exotel plays the audio** to the caller in real-time
67+
68+
### Set up your App Bazaar flow
69+
70+
Exotel uses App Bazaar to configure call flows. For dial-in, you create an app with a Voicebot applet that establishes a WebSocket connection directly to your bot:
71+
72+
1. **Navigate to App Bazaar** in your Exotel dashboard
73+
2. **Create a new app** or edit an existing one
74+
3. **Add a Voicebot applet** (not "Stream" or "Passthru")
75+
4. **Configure the WebSocket URL**: `wss://your-server.com/ws`
76+
5. **Add a Hangup applet** at the end to properly terminate calls
77+
78+
Your flow should look like: `Call Start → [Voicebot Applet] → [Hangup Applet]`
79+
80+
### Custom Data Limitations
81+
82+
<Warning>
83+
Currently, there are limitations with passing custom data through query
84+
parameters in Exotel's WebSocket URLs. While the platform theoretically
85+
supports query parameters, they may be stripped during call processing. This
86+
is an ongoing limitation that may be addressed in future Exotel updates.
87+
</Warning>
88+
89+
If you need to pass custom data, consider these alternatives:
90+
91+
- Use different WebSocket endpoints for different call types
92+
- Configure multiple App Bazaar flows for different scenarios
93+
- Handle customization based on the called number (available in WebSocket messages)
94+
95+
### Configure your Pipecat bot for dial-in
96+
97+
Your bot receives the WebSocket connection and automatically gets call information from Exotel's WebSocket messages. The key components are:
98+
99+
**WebSocket Parsing**: Pipecat's built-in parser extracts call data from Exotel's WebSocket messages:
100+
101+
```python bot.py
102+
from pipecat.runner.utils import parse_telephony_websocket
103+
104+
async def run_bot(websocket: WebSocket):
105+
# Parse Exotel WebSocket data
106+
transport_type, call_data = await parse_telephony_websocket(websocket)
107+
108+
# Extract call information (automatically provided by Exotel)
109+
stream_id = call_data["stream_id"]
110+
call_id = call_data["call_id"] # Exotel's CallSid
111+
account_sid = call_data["account_sid"]
112+
from_number = call_data["from"] # Caller's number
113+
to_number = call_data["to"] # Your Exotel number
114+
```
115+
116+
**Transport Creation**: Configure the WebSocket transport with Exotel serialization:
117+
118+
```python bot.py
119+
# Create Exotel serializer with call details
120+
serializer = ExotelFrameSerializer(
121+
stream_id=stream_id,
122+
call_id=call_id,
123+
account_sid=account_sid,
124+
api_key=os.getenv("EXOTEL_API_KEY"),
125+
api_token=os.getenv("EXOTEL_API_TOKEN"),
126+
)
127+
128+
# Configure WebSocket transport
129+
transport = FastAPIWebsocketTransport(
130+
websocket=websocket,
131+
params=FastAPIWebsocketParams(
132+
audio_in_enabled=True,
133+
audio_out_enabled=True,
134+
add_wav_header=False,
135+
vad_analyzer=SileroVADAnalyzer(),
136+
serializer=serializer,
137+
),
138+
)
139+
140+
# Your bot pipeline setup here...
141+
```
142+
143+
**Call Information Usage**: Use the extracted call information to personalize your bot's behavior:
144+
145+
```python bot.py
146+
# Customize bot behavior based on call information
147+
greeting = f"Hello! I see you're calling from {from_number}. How can I help you today?"
148+
149+
# Use call information for logging or routing
150+
logger.info(f"Incoming call from {from_number} to {to_number}")
151+
```
152+
153+
<Card
154+
title="Complete Bot Implementation"
155+
icon="code"
156+
href="https://github.com/pipecat-ai/pipecat-examples/blob/main/exotel-chatbot/inbound/bot.py"
157+
>
158+
See the full bot.py with WebSocket parsing, transport setup, and pipeline
159+
configuration
160+
</Card>
161+
162+
### Set up Exotel phone number
163+
164+
Configure your Exotel phone number to use your App Bazaar flow:
165+
166+
1. Go to the [Exotel Dashboard](https://my.exotel.com)
167+
2. Navigate to ExoPhones
168+
3. Find your phone number and click the edit icon
169+
4. Under "App", select your App Bazaar flow
170+
5. Save the configuration
171+
172+
### Run the Example
173+
174+
For dial-in, you can run your bot directly without a separate server:
175+
176+
```shell
177+
# Start your bot directly
178+
python bot.py
179+
180+
# For local development, use ngrok to expose your WebSocket
181+
ngrok http 8000
182+
# Use the ngrok WebSocket URL (wss://abc123.ngrok.io/ws) in your App Bazaar flow
183+
```
184+
185+
<Card
186+
title="Complete Setup Instructions"
187+
icon="book-open"
188+
href="https://github.com/pipecat-ai/pipecat-examples/tree/main/exotel-chatbot/inbound"
189+
>
190+
See the full README with step-by-step setup, App Bazaar configuration, and
191+
testing
192+
</Card>
193+
194+
## Dial-out
195+
196+
Dial-out allows your bot to initiate calls to phone numbers using Exotel's outbound calling capabilities with WebSocket Voice Streaming.
197+
198+
### How It Works
199+
200+
Here's the sequence of events for dial-out calls:
201+
202+
1. **Your application triggers a dial-out** (via API call or user action)
203+
2. **Server initiates an Exotel call** using the Voice API
204+
3. **Exotel establishes the call** and opens a WebSocket connection
205+
4. **Your bot joins the WebSocket** and sets up the pipeline
206+
5. **The recipient answers** and is connected to your bot
207+
6. **The bot handles the conversation** with real-time audio streaming
208+
209+
### Set up your server for dial-out
210+
211+
The dial-out server creates outbound calls and manages WebSocket connections. When you trigger a dial-out call, your server:
212+
213+
1. **Receives the dial-out request** with target phone number and parameters
214+
2. **Creates an Exotel call** using the Voice API with a callback URL
215+
3. **Accepts the WebSocket** connection from Exotel
216+
4. **Parses call data** from the WebSocket messages
217+
5. **Runs the Pipecat bot** with the call information
218+
219+
<Card
220+
title="Complete Server Implementation"
221+
icon="code"
222+
href="https://github.com/pipecat-ai/pipecat-examples/blob/main/exotel-chatbot/outbound/server.py"
223+
>
224+
See the full FastAPI server code with outbound call creation and WebSocket
225+
handling
226+
</Card>
227+
228+
### Configure your Pipecat bot for dial-out
229+
230+
The dial-out bot configuration is similar to dial-in, with Exotel automatically providing call information. Note the [Custom Data Limitations](#custom-data-limitations) section above.
231+
232+
**Call Information**: Extract call details from Exotel's WebSocket messages:
233+
234+
```python bot.py
235+
# Parse WebSocket data (same as dial-in)
236+
transport_type, call_data = await parse_telephony_websocket(websocket)
237+
238+
# Extract call information
239+
stream_id = call_data["stream_id"]
240+
call_id = call_data["call_id"]
241+
account_sid = call_data["account_sid"]
242+
from_number = call_data["from"] # Your Exotel number
243+
to_number = call_data["to"] # Target number you're calling
244+
245+
# Customize bot behavior for outbound calls
246+
greeting = f"Hi! This is an automated call from {from_number}. How are you today?"
247+
```
248+
249+
**Transport Configuration**: Same transport setup as dial-in:
250+
251+
```python bot.py
252+
# Create Exotel serializer
253+
serializer = ExotelFrameSerializer(
254+
stream_id=stream_id,
255+
call_id=call_id,
256+
account_sid=account_sid,
257+
api_key=os.getenv("EXOTEL_API_KEY"),
258+
api_token=os.getenv("EXOTEL_API_TOKEN"),
259+
)
260+
261+
# Configure transport
262+
transport = FastAPIWebsocketTransport(
263+
websocket=websocket,
264+
params=FastAPIWebsocketParams(
265+
audio_in_enabled=True,
266+
audio_out_enabled=True,
267+
add_wav_header=False,
268+
vad_analyzer=SileroVADAnalyzer(),
269+
serializer=serializer,
270+
),
271+
)
272+
```
273+
274+
<Card
275+
title="Complete Bot Implementation"
276+
icon="code"
277+
href="https://github.com/pipecat-ai/pipecat-examples/blob/main/exotel-chatbot/outbound/bot.py"
278+
>
279+
See the full bot.py with outbound call handling and call information usage
280+
</Card>
281+
282+
### Run the Example
283+
284+
To test dial-out functionality:
285+
286+
1. **Start your server**: Run your FastAPI server
287+
2. **Trigger a call**: Make an API request to start an outbound call
288+
3. **Answer your phone**: The bot will call the specified number
289+
4. **Talk to your bot**: Have a conversation with your AI agent
290+
291+
<Card
292+
title="Complete Setup Instructions"
293+
icon="book-open"
294+
href="https://github.com/pipecat-ai/pipecat-examples/tree/main/exotel-chatbot/outbound"
295+
>
296+
See the full README with step-by-step setup, API usage, and outbound call
297+
configuration
298+
</Card>
299+
300+
## Key Features
301+
302+
### Audio Format and Sample Rate
303+
304+
Exotel Voice Streaming uses 8kHz mono audio with 16-bit PCM encoding. Configure your pipeline accordingly:
305+
306+
```python
307+
task = PipelineTask(
308+
pipeline,
309+
params=PipelineParams(
310+
audio_in_sample_rate=8000,
311+
audio_out_sample_rate=8000,
312+
allow_interruptions=True,
313+
),
314+
)
315+
```
316+
317+
### Built-in Call Information
318+
319+
Like Telnyx, Exotel automatically includes comprehensive call information (to/from numbers, account details) in the WebSocket messages, eliminating the need for custom webhook servers in basic dial-in scenarios.
320+
321+
## Deployment
322+
323+
### Local Development
324+
325+
Use [ngrok](https://ngrok.com/) to expose your local server for testing:
326+
327+
```shell
328+
python server.py # For dial-out
329+
# OR
330+
python bot.py # For dial-in
331+
332+
ngrok http 8000
333+
# Use the ngrok URL in your App Bazaar Voicebot applet
334+
```
335+
336+
### Pipecat Cloud Deployment
337+
338+
For production deployment without managing your own infrastructure, use Pipecat Cloud:
339+
340+
<Card
341+
title="Exotel WebSocket on Pipecat Cloud"
342+
icon="cloud"
343+
href="/deployment/pipecat-cloud/guides/telephony/exotel-websocket"
344+
>
345+
Deploy Exotel WebSocket bots with automatic scaling and managed infrastructure
346+
</Card>
347+
348+
### Self-Hosted Production Deployment
349+
350+
For fully self-hosted production deployment, ensure your servers are:
351+
352+
- Publicly accessible with HTTPS
353+
- Able to handle concurrent WebSocket connections
354+
- Properly configured with Exotel API credentials
355+
- Implementing proper error handling and logging
356+
357+
## Next Steps
358+
359+
- Explore the [complete examples](https://github.com/pipecat-ai/pipecat-examples/tree/main/exotel-chatbot) for full implementations
360+
- Learn about [Daily + Twilio SIP integration](./twilio-daily-sip) for advanced telephony scenarios
361+
- Check out [Daily PSTN integration](./daily-pstn) for direct phone number provisioning

0 commit comments

Comments
 (0)