Documentation Index
Fetch the complete documentation index at: https://daily-docs-cli-pr-89.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
Overview
The Pipecat development runner provides a unified way to run voice AI bots across multiple transport types. It handles infrastructure setup - creating Daily rooms, managing WebRTC connections, and routing telephony calls.Installation
What is a Runner?
A runner in Pipecat refers to a “bot runner”, an HTTP service that provides a gateway for spawning bots on-demand. It’s the component that enables your bot to run by providing it with server infrastructure and connection details like rooms and tokens. A bot runner typically creates transport sessions (like Daily WebRTC rooms), generates authentication tokens for both bots and users, spawns new bot processes when users request sessions, and manages bot lifecycle and cleanup. Think of it as the bridge between incoming user connections and your bot logic.How the Development Runner Works
The development runner operates as a FastAPI web server that automatically discovers and executes your bot code. By default it starts a single server that supports all transports simultaneously — WebRTC, Daily, telephony (Twilio, Telnyx, Plivo, Exotel), and plain WebSocket. Clients choose which transport they want per-request by sending a"transport" field in the POST /start body; you no longer restart the server to switch transports.
- WebRTC connections: It serves a built-in web interface where users can connect directly as well as an endpoint to create new WebRTC sessions
- Daily integration: It provides endpoints that create new rooms and tokens and redirect users to join them
- Telephony providers: For Twilio, Telnyx, and Plivo, it sets up webhook endpoints that handle incoming calls and establish WebSocket connections for audio streaming
- Plain WebSocket: It exposes a
/ws-clientendpoint for non-telephony WebSocket clients (e.g. browser apps using protobuf framing)
Pipecat Cloud Ready
The bot runner is designed to be cloud-ready, meaning that you can run the same bot code locally and deployed to Pipecat Cloud without any modifications. It automatically handles the differences in transport setup, providing you with the flexibility to test locally using an open source transport, like SmallWebRTCTransport, but run in production using Daily or telephony transports.Building with the Runner
Now let’s build a practical example to see how this works. The key insight is that your bot code is structured into two parts: the core bot logic that works with any transport, and the entry point that creates the appropriate transport based on the runner arguments. Here’s the basic structure:run_bot() function contains your actual bot logic and is transport-agnostic. The bot() function is the entry point that the runner calls - it creates the appropriate transport and passes it to your bot logic. This separation allows the same bot code to work across different transports.
When you run this with python bot.py, the development runner starts a web server and opens a browser interface at http://localhost:7860/client. Each time someone connects, the runner calls your bot() function with WebRTC runner arguments.
Supporting Multiple Transports
To make your bot work across different platforms, you can detect the transport type from the runner arguments and create the appropriate transport. Here’s how to support both Daily and WebRTC:/start), pass -t/--transport:
Understanding Runner Arguments
Runner arguments are how the runner communicates transport-specific information to your bot. The runner determines which transport to use based on the command-line arguments, then creates the appropriate runner arguments:DailyRunnerArguments: Containsroom_url,token(Optional),body(Optional) for joining Daily roomsSmallWebRTCRunnerArguments: Containswebrtc_connectionfor local WebRTC sessionsWebSocketRunnerArguments: Containswebsocketfor both telephony and plain WebSocket connections. Thetransport_typefield distinguishes them —"websocket"for plain (non-telephony) clients connecting via/ws-client, or a telephony provider value for connections via/ws.
handle_sigint: Whether the bot should handle SIGINT (Ctrl+C) signals (managed automatically)handle_sigterm: Whether the bot should handle SIGTERM signals (managed automatically)
from pipecat.transports.daily.transport import ...) inside the conditional blocks. This ensures that transport-specific dependencies are only required when that transport is actually used, making your bot more portable.
RunnerArguments is the base class for all runner arguments. It provides a
common interface for the runner to pass transport-specific information to your
bot.Environment Detection
When building bots that work both locally and in production, you often need to detect the execution environment to enable different features. The development runner sets theENV environment variable to help with this:
Environment Values
The development runner automatically sets environment variables based on how your bot is running:- Local development:
ENV=local(set by the development runner) - Production/Cloud deployment:
ENVis not set or has a different value
All Supported Transports
The development runner supports seven transport types, each designed for different use cases. By default all are available from one server; the client selects one per session via the"transport" field in the /start request. The -t <transport> form below is the optional way to restrict the server to a single transport.
WebRTC ("transport": "webrtc")
Local WebRTC connections with a built-in browser interface. Perfect for development and testing. This is the default transport when a /start request omits the "transport" field.
SmallWebRTCRunnerArguments
webrtc_connection: Pre-configured WebRTC peer connection
Daily ("transport": "daily")
Integration with Daily for production video conferencing with rooms, participant management, and Pipecat client compatibility.
DailyRunnerArguments
room_url: Daily room URL to jointoken: Authentication token for the roombody: Request data from /start endpoint (dict) or dial-in webhook data
GET /daily: Browser redirect that creates a room and joins itPOST /start: RTVI-compatible endpoint for programmatic access (send"transport": "daily")POST /daily-dialin-webhook: PSTN dial-in webhook handler (requires--dialinflag)
GET / redirects to the prebuilt client UI at /client/ for all transports.
The Daily browser redirect moved to GET /daily in Pipecat 1.3.0.Telephony ("transport": "twilio" | "telnyx" | "plivo" | "exotel")
Phone call integration through telephony providers. Requires a public webhook endpoint and provider credentials.
POST /) is only registered when you select a single telephony transport with -t (the XML template needs the --proxy hostname). The media WebSocket at /ws is always available.
Environment Variables:
- Twilio:
TWILIO_ACCOUNT_SID,TWILIO_AUTH_TOKEN - Telnyx:
TELNYX_API_KEY - Plivo:
PLIVO_AUTH_ID,PLIVO_AUTH_TOKEN - Exotel: None required (no hang-up functionality available)
WebSocketRunnerArguments
websocket: WebSocket connection for audio streaming
WebSocket ("transport": "websocket")
Plain (non-telephony) WebSocket connections, for clients such as browser apps that speak protobuf framing directly. Selecting this transport on /start returns a wsUrl pointing at the /ws-client endpoint, which the client then connects to.
WebSocketRunnerArguments
websocket: WebSocket connection for audio streamingtransport_type:"websocket"for plain clients (distinguishes them from telephony connections, which arrive on/ws)
transport_type field to branch your bot’s setup — plain WebSocket clients typically use a ProtobufFrameSerializer, whereas telephony clients use a provider-specific serializer.
Command Line Options
The development runner accepts several command-line arguments to customize its behavior:Key Arguments
--transport / -t: Optional. When omitted, the server supports all transports at once and the client chooses one per /start request. When provided, it restricts the server to a single transport and makes it the default for /start; requests for any other transport are rejected with HTTP 400. Valid values:
webrtc: Local WebRTC with browser interfacedaily: Daily.co integration with room managementtwilio,telnyx,plivo,exotel: Telephony provider integration
--proxy / -x: Required for most telephony transports (Twilio, Telnyx, Plivo). This should be a publicly accessible hostname (like yourbot.ngrok.io) that can receive webhooks from telephony providers. The runner automatically strips protocol prefixes (http://, https://) if provided. Not required for Exotel, which uses direct WebSocket connections.
--direct / -d: Special mode for Daily that bypasses the web server and connects your bot directly to a Daily room. Useful for quick testing but not recommended for production use.
--dialin: Enables the /daily-dialin-webhook endpoint for handling Daily PSTN dial-in calls. This endpoint receives webhook data from Daily when a phone call dials into your configured phone number, creates a SIP-enabled room, and spawns your bot. (It no longer requires -t daily, though dial-in is a Daily feature.)
--esp32: Enables SDP (Session Description Protocol) modifications needed for ESP32 WebRTC compatibility. Must be used with a specific IP address via --host.
Environment Variables
Different transports require different environment variables: Daily:DAILY_API_KEY: Daily API key for creating rooms and tokens (required for dial-in)DAILY_SAMPLE_ROOM_URL(Optional): Existing room URL to useDAILY_API_URL(Optional): Daily API URL (defaults to https://api.daily.co/v1)
TWILIO_ACCOUNT_SID,TWILIO_AUTH_TOKEN: Twilio credentialsPLIVO_AUTH_ID,PLIVO_AUTH_TOKEN: Plivo credentialsTELNYX_API_KEY: Telnyx API key
Simplifying with the Transport Utility
While the manual approach gives you full control, thecreate_transport utility provides a much cleaner way to handle multiple transports. Instead of writing conditional logic for each transport type, you define transport configurations upfront and let the utility handle the selection:
- Detects the telephony provider from WebSocket messages
- Configures the appropriate serializer (Twilio, Telnyx, Plivo, or Exotel)
- Sets up authentication using environment variables
- Handles WebRTC, Daily, and plain WebSocket transport creation
RTVI Integration
The development runner provides RTVI (Real-Time Voice Interface) compatible endpoints for the Pipecat client SDKs. This allows you to use the Pipecat client libraries locally during development as well as when deployed to Pipecat Cloud.The /start Endpoint
The runner exposes a single unified POST /start endpoint that works for all transports. The client picks the transport via the "transport" field in the request body (default: "webrtc"); the runner then spawns the bot and returns transport-specific connection details in RTVI-compatible format.
-t <transport>, a /start request for any other transport is rejected with HTTP 400.
Request Format ("transport": "webrtc", the default):
sessionId (and an iceConfig when enableDefaultIceServers is set). The bot starts when the WebRTC offer arrives.
Request Format ("transport": "daily"):
createDailyRoom: true (or a configured DAILY_ROOM_URL) makes the runner create a room and token using your DAILY_API_KEY. dailyRoomProperties and dailyMeetingTokenProperties are applied when provided. Response:
"transport": "twilio" | "telnyx" | "plivo" | "exotel" or "transport": "websocket", /start returns the WebSocket URL the client should connect to:
/ws; plain WebSocket clients use /ws-client (and also receive a sessionId). The bot starts when the connection is established.
The /status Endpoint
GET /status reports which transports the running instance accepts — all of them by default, or the single transport passed via -t:
Accessing Request Data in Your Bot
Thebody field from the /start request is passed to your bot through DailyRunnerArguments.body:
RTVI Client Example
You can use RTVI client libraries to connect to your local development runner:The
/start endpoint serves every transport. The client SDK’s transport
(e.g. DailyTransport, SmallWebRTCTransport) determines the "transport"
value sent in the request.Daily Dial-In Webhook
The development runner can handle Daily PSTN dial-in webhooks when started with the--dialin flag. This allows you to test phone call integrations locally before deploying to production.
Enabling Dial-In Support
How It Works
When a phone call dials into your Daily phone number:- Daily sends a webhook to your configured endpoint with call details
- The runner creates a SIP-enabled room with appropriate configuration
- Your bot is spawned with dial-in context in
runner_args.body - The call is connected to the room where your bot is waiting
Webhook Payload
Daily sends the following data to the/daily-dialin-webhook endpoint:
Accessing Dial-In Data in Your Bot
The dial-in webhook data is passed to your bot throughDailyRunnerArguments.body. You need to parse it and configure the Daily transport with dial-in settings:
Configuring Daily Phone Numbers
To test dial-in locally, you need to:- Configure a Daily phone number in your Daily dashboard
- Set the webhook URL to your public endpoint (e.g., via ngrok)
- Ensure
DAILY_API_KEYis set in your environment
Dial-in is a Daily feature and requires a valid
DAILY_API_KEY environment
variable. --dialin no longer requires -t daily, but you can still pass it
to restrict the runner to Daily.Quick Reference
All transports are available frompython bot.py; the -t form below restricts the server to one. Access columns assume the default localhost:7860.
| Transport | Command | Access | Environment Variables |
|---|---|---|---|
| All (default) | python bot.py | http://localhost:7860/client | Per transport (see below) |
| WebRTC | python bot.py -t webrtc | http://localhost:7860/client | None |
| Daily | python bot.py -t daily | GET /daily, POST /start | DAILY_API_KEY, DAILY_SAMPLE_ROOM_URL (Optional) |
| Daily Direct | python bot.py -d | Direct connection | DAILY_API_KEY, DAILY_SAMPLE_ROOM_URL (Optional) |
| Daily Dial-In | python bot.py --dialin | Phone calls via Daily PSTN | DAILY_API_KEY (Required) |
| Twilio | python bot.py -t twilio -x proxy.ngrok.io | Phone calls | TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN |
| Telnyx | python bot.py -t telnyx -x proxy.ngrok.io | Phone calls | TELNYX_API_KEY |
| Plivo | python bot.py -t plivo -x proxy.ngrok.io | Phone calls | PLIVO_AUTH_ID, PLIVO_AUTH_TOKEN |
| Exotel | python bot.py -t exotel | Phone calls | None |
| WebSocket | python bot.py | ws://localhost:7860/ws-client | None |
| ESP32 WebRTC | python bot.py --esp32 --host <ESP32_IP> | ESP32 WebRTC connection | None |
Examples
For practical examples of using the development runner with different transports, check out the following:Runner Examples
Explore the examples for different ways to use the development runner with
various transports.