Skip to main content
Cloudflare Agents is a framework for building voice agents that run on Cloudflare Workers. Plivo Audio Streaming bridges a phone call to one of these agents over a WebSocket, using the Plivo adapter. The Voice Agent pipeline is composed of independent stages instead of a single hosted API. The speech-to-text, response text generation, and text-to-speech stages each run on a Workers AI model or a third-party provider model through AI Gateway, so quality, latency, and cost can be tuned independently per stage. The agent itself runs on Cloudflare Workers, requiring no server infrastructure to provision or scale.

How it works

PipelineCloudflare Agents
  1. Phone Call
    PlivoAudio Stream
    Cloudflare WorkerVoiceAgentSTTLLMTTS
The Cloudflare Worker runs a WebSocket server. On an inbound call, Plivo opens a bidirectional WebSocket to it and streams the caller’s audio in both directions. The Plivo adapter accepts the connection and bridges the caller and the 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:
  • transcriber for STT
  • tts for TTS
  • onTurn for the LLM
Then add two routes to the Worker.
  • /answer returns the Plivo answer XML that opens the audio stream
  • /plivo is 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.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.
Add it to package.json as a deploy script.
Then deploy and connect Plivo in one command.
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 the env.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:
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 the env.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 the ai-gateway-provider package, which plugs into the same ai SDK that onTurn already uses.

Text-to-Speech Stage

The tts 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.
Set it as the agent’s tts stage.

Speech-to-Text Stage

The transcriber 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.

Audio Streaming

The Plivo streaming API this integration builds on

Stream XML

The <Stream> element the answer URL returns

Cloudflare Agents docs

The Cloudflare Agents platform documentation

Cloudflare Agents repo

The Cloudflare Agents source and examples