How it works
PipelineCloudflare Agents
- Phone CallPlivoAudio StreamWebSocketWebSocket serverCloudflare WorkerVoiceAgentSTTLLMTTS
VoiceAgent. It converts between Plivo’s 8 kHz mulaw and the agent’s 16 kHz PCM, relays call and DTMF events, and handles barge-in when the caller speaks over the agent.
The Plivo adapter routes the call to the VoiceAgent, which transcribes the caller’s speech, generates a response with the model, and synthesizes the reply as audio.
Prerequisites
Quick start
Deploy the ready example to Cloudflare and connect the Plivo number to it.1
Clone and build the repo
2
Set up the example
Copy the example env file to
.env, and add the Plivo Auth ID, Auth Token, and phone number to it.3
Deploy
pnpm run deploy deploys the Worker to Cloudflare, where it runs at a stable workers.dev URL.The deploy script then creates a Plivo application, connects it to the deployed Worker, and assigns the Plivo number to that application.4
Test the call
Dial the Plivo number to reach the agent.
Local development
Run the Worker locally.pnpm run dev opens a cloudflared tunnel that exposes the local Worker to a temporary public URL, then connects the Plivo number to that tunnel. Calls now reach the locally running Cloudflare Worker.
To connect the Plivo number to the deployed Cloudflare Worker, run pnpm run deploy.
Set up the integration
To add the Plivo Adapter to an existing Cloudflare Worker.1
Install the adapter
Install the adapter along with the agent, voice, and Workers AI packages.
2
Add the adapter to the Worker
The
withVoice function takes Cloudflare’s base Agent class and returns a voice-enabled version, VoiceAgent. Create a class that extends VoiceAgent and sets the three stages of the pipeline:Then add two routes to the Worker./answerreturns the Plivo answer XML that opens the audio stream/plivois where the audio stream connects, and it hands the call to the adapter
The TTS model should return PCM instead of MP3 since the adapter needs the audio format in 16 kHz
linear16 and does not decode MP3.The built-in WorkersAITTS returns MP3, hence PCMTTS, the custom class wraps the @cf/deepgram/aura-2-en model to request linear16 output.3
Add tool calling (optional)
onTurn runs the LLM model through the ai SDK. The tools are added with the SDK’s tools option.The model calls a tool, the SDK runs it, and the result feeds back into the reply the agent speaks.4
Handle interruptions (optional)
The adapter lets the caller interrupt the Voice Agent. When it detects the caller speak while the agent is talking, it stops the current reply.It ignores short backchannels and background noise so a stray sound does not cut the agent off.Override
onInterrupt to run custom logic when an interrupt happens.5
Deploy and connect Plivo to the Worker
The Worker must be publicly reachable for Plivo to connect to it.Add it to Then deploy and connect Plivo in one command.
wrangler deploy builds and uploads it to Cloudflare and prints its workers.dev URL. No separate build command is needed.Create a deploy script named deploy.ts. It runs wrangler deploy, reads the deployed Worker URL from the output, and passes it to setupPlivoApplication, which finds or creates a Plivo application, sets its answer URL to the deployed Worker’s /answer endpoint, and assigns the Plivo number to it.Placing it in a scripts folder at the project root (scripts/deploy.ts) is the recommended structure.package.json as a deploy script.setupPlivoApplication is idempotent, so it is safe to run on every deploy.6
Test the call
Dial the Plivo number to reach the agent.
Choose your models
Workers AI Models
Workers AI models are hosted by Cloudflare and called through theenv.AI binding.
Browse the Workers AI catalog, or the models directory in the Cloudflare dashboard, and swap in whichever fits the language, latency, and cost requirements.
The example above uses these Workers AI models:
- STT Provider -
@cf/deepgram/flux - Text Generation Model -
@cf/moonshotai/kimi-k2.6 - TTS Provider -
@cf/deepgram/aura-2-en
The TTS model must return raw PCM, and not MP3. See Set up the integration for the encoding settings that produce it.
Third Party Providers
Cloudflare also lists third-party models from outside providers. These are reached through AI Gateway instead of theenv.AI binding.
Each provider has its own API, so integrating these models for any stage of the pipeline is a provider-specific implementation. AI Gateway gives a consistent way to route and authenticate the request, but the endpoint, parameters, and output format follow the provider.
The snippets below show how to implement a third-party provider model for each stage:
Response-Text-Generation Stage
Route the response text generation stage through AI Gateway with theai-gateway-provider package, which plugs into the same ai SDK that onTurn already uses.
Text-to-Speech Stage
Thetts stage takes a TTSProvider, an interface from @cloudflare/voice with one method, synthesize, that returns the spoken audio.
To use a third-party TTS model, implement TTSProvider in a small class whose synthesize method calls the model through AI Gateway and returns raw PCM.
Requesting a pcm_16000 output format returns the 16 kHz linear16 the adapter needs directly, the same way the example’s PCMTTS class, requests linear16 from the Workers AI model @cf/deepgram/aura-2-en.
tts stage.
Speech-to-Text Stage
Thetranscriber stage takes a Transcriber, a streaming interface from @cloudflare/voice that runs a live session and returns transcripts as the caller speaks.
The built-in WorkersAIFluxSTT implements this interface for the Workers AI models and can be used as a reference. A third-party provider follows the same structure, implemented as a custom class that connects to the provider’s realtime STT API.
Related
Audio Streaming
The Plivo streaming API this integration builds on
Stream XML
The
<Stream> element the answer URL returnsCloudflare Agents docs
The Cloudflare Agents platform documentation
Cloudflare Agents repo
The Cloudflare Agents source and examples