Skip to main content

WAVoice: Set Up WhatsApp Voice AI in 90 Seconds

Python 3.12 License: MIT Powered by Pipecat Author: Amit Bhakt

The zero-friction, one-command pipeline for WhatsApp Voice AI.
Go from zero to an active AI voice agent answering live WhatsApp calls in under 90 seconds. No manual Meta dashboard clicking, no ngrok account setup, and no WebRTC configuration required.

Created by Amit Bhakt, WAVoice solves the hardest part of building WhatsApp voice agents: the entire telephony and networking plumbing.


Why Developers Use WAVoice

Setting up WhatsApp voice calling traditionally requires hours of manual work: navigating Meta Business Manager, registering phone number IDs, manually creating ngrok tunnels, pasting webhook verification tokens, handling WebRTC SDP offer/answers, and diagnosing why audio drops over NAT.

WAVoice collapses all of that into a single 90-second command (wavoice init):

  1. Automated Cloudflare Quick Tunnel: Ephemeral public HTTPS TLS gateway with zero tokens or account sign-ups.
  2. Auto-Discovery: Extracts your WABA ID and Phone Number ID directly from your token via Meta Graph API.
  3. Programmatic Calling Activation: Enables WhatsApp Voice Calling and makes the Call button visible automatically.
  4. Full 3-Tier Webhook Sync: Programmatically configures Phone Number overrides, WABA subscriptions, and App subscriptions.
  5. Production WebRTC Infrastructure: Pre-configured STUN/TURN, SRTP audio handling, and atomic call claim locks (preventing duplicate webhook deliveries).

How It Works: Instant Testing vs. Custom Pipelines

Whether you want a complete out-of-the-box agent or a custom multi-model architecture, WAVoice separates the telephony infrastructure from your AI logic:

                       ┌────────────────────────────────────────┐
                       │  Telephony Infrastructure Layer        │
                       │  (Handled automatically by WAVoice)    │
                       │                                        │
                       │  - Cloudflare Quick Tunnel             │
                       │  - Meta Graph API Webhooks             │
                       │  - WebRTC SDP Offer / Answer           │
                       │  - SRTP Audio Stream Decoupling        │
                       └───────────────────┬────────────────────┘
                                           │
                       ┌───────────────────┴────────────────────┐
                       ▼                                        ▼
      ┌─────────────────────────────────┐      ┌─────────────────────────────────┐
      │  Mode A: Out-of-the-Box (90s)   │      │  Mode B: Custom Layers          │
      │                                 │      │  (Pluggable Pipecat Pipeline)   │
      │  Run: `wavoice start`           │      │                                 │
      │  Native Speech-to-Speech via    │      │  - STT: Deepgram, Whisper, Groq │
      │  Gemini 2.0 Flash Live          │      │  - LLM: OpenAI, Claude, Ollama  │
      │  (~300ms latency, zero code)    │      │  - TTS: Cartesia, ElevenLabs    │
      └─────────────────────────────────┘      └─────────────────────────────────┘

How does the one-command setup help developers who want separate layers?

When you want to build a cascaded stack (STT $\rightarrow$ LLM $\rightarrow$ TTS), you still face the exact same frustrating hurdle: connecting WhatsApp's WebRTC audio stream to your server.

By running wavoice init, your WhatsApp number and webhook plumbing are 100% configured in 90 seconds. Then, instead of maintaining complex SIP/WebRTC servers, you simply write standard, modular Python:

from wavoice import WhatsAppVoiceApp

app = WhatsAppVoiceApp()

@app.on_call
async def handle_call(transport, call_info):
    # 'transport' already receives raw audio from WhatsApp WebRTC
    # Plug in any separate STT, LLM, or TTS processor:
    pipeline = Pipeline([
        transport.input(),
        DeepgramSTTService(...),
        OpenAILLMService(...),
        CartesiaTTSService(...),
        transport.output(),
    ])
    ...

90-Second Quickstart

Step 1: Install

git clone https://github.com/amitbhakt/wavoice.git
cd wavoice
uv sync

(Or install via pip install wavoice)

Step 2: One-Command Setup

uv run wavoice init

The interactive wizard asks for only 3 credentials:

  1. WHATSAPP_TOKEN: Meta System User access token.
  2. WHATSAPP_APP_SECRET: Meta App Secret.
  3. GEMINI_API_KEY: Google Gemini API key.

WAVoice automatically discovers your business accounts, activates WhatsApp voice calling, saves .env, and starts the server immediately.

Step 3: Dial & Talk

Open WhatsApp on your phone and dial your business number. Your AI agent answers immediately.


Pre-Flight Diagnostics

To inspect your setup, token scopes, voice calling flags, and webhook routing tiers at any time:

uv run wavoice doctor

Output:

╦ ╦╔═╗╦  ╦╔═╗╦╔═╗╔═╗   WAVoice v0.1.0
║║║╠═╣╚╗╔╝║ ║║║  ║╣    One-command WhatsApp Voice AI runtime
╚╩╝╩ ╩ ╚╝ ╚═╝╩╚═╝╚═╝

╭────────────────────────────────╮
│ WAVoice Pre-Flight Diagnostics │
╰────────────────────────────────╯
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Check                          ┃ Status       ┃ Details                      ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ Meta Credentials               │ PASS         │ Token & Phone ID configured  │
│ Phone Number Reachability      │ PASS         │ Verified number: +1 555-188  │
│ WhatsApp Voice Calling API     │ PASS         │ Voice calling is ENABLED     │
│ Tier 1: Phone Override         │ ACTIVE       │ Cloudflare Tunnel Verified   │
│ Tier 2: WABA Subscription      │ ACTIVE       │ Webhook Subscribed           │
│ Tier 3: App Subscriptions      │ ACTIVE       │ calls, messages Active       │
│ Default AI Agent               │ PASS         │ Gemini 2.0 Flash Live ready  │
└────────────────────────────────┴──────────────┴──────────────────────────────┘

Building Custom Multi-Model Pipelines

For developers building with independent STT, LLM, and TTS providers, WAVoice exposes the complete Pipecat pipeline:

import os
from wavoice import WhatsAppVoiceApp
from pipecat.audio.vad.silero import SileroVADAnalyzer
from pipecat.pipeline.pipeline import Pipeline
from pipecat.pipeline.runner import PipelineRunner
from pipecat.pipeline.task import PipelineParams, PipelineTask
from pipecat.processors.aggregators.llm_context import LLMContext
from pipecat.processors.aggregators.llm_response_universal import (
    LLMContextAggregatorPair,
    LLMUserAggregatorParams,
)
from pipecat.services.deepgram import DeepgramSTTService
from pipecat.services.openai import OpenAILLMService
from pipecat.services.cartesia import CartesiaTTSService

app = WhatsAppVoiceApp()

@app.on_call
async def handle_incoming_call(transport, call_info):
    caller = getattr(call_info, "from_", "caller")
    print(f"Incoming call from {caller}")

    # 1. Custom Layer Services
    stt = DeepgramSTTService(api_key=os.environ["DEEPGRAM_API_KEY"])
    llm = OpenAILLMService(api_key=os.environ["OPENAI_API_KEY"], model="gpt-4o-mini")
    tts = CartesiaTTSService(api_key=os.environ["CARTESIA_API_KEY"], voice_id="...")

    # 2. Context Aggregation & Silero Turn Detection
    context = LLMContext([{"role": "system", "content": "You are a concise voice assistant."}])
    user_agg, assistant_agg = LLMContextAggregatorPair(
        context,
        user_params=LLMUserAggregatorParams(vad_analyzer=SileroVADAnalyzer()),
    )

    # 3. Assemble Pipeline
    pipeline = Pipeline([
        transport.input(),    # WebRTC Audio In from WhatsApp
        stt,                  # Speech-to-Text
        user_agg,             # Turn Aggregator
        llm,                  # Large Language Model
        tts,                  # Text-to-Speech
        transport.output(),   # WebRTC Audio Out to WhatsApp
        assistant_agg,
    ])

    task = PipelineTask(pipeline=pipeline, params=PipelineParams(allow_interruptions=True))
    runner = PipelineRunner()
    await runner.run(task)

if __name__ == "__main__":
    app.run()  # Launches tunnel, registers Meta webhooks, and serves pipeline

(See examples/custom_stt_llm_tts.py for the complete runnable file)


CLI Command Reference

Command Description
wavoice init Complete 90-second setup: prompts for 3 credentials, auto-discovers IDs, turns on voice calling, and launches. Pass --no-telemetry to opt out of usage metrics.
wavoice doctor Runs diagnostics across Meta credentials, calling status, and 3-tier webhooks.
wavoice start Starts the server, establishes the Cloudflare tunnel, and begins accepting calls. Pass --no-telemetry to run with telemetry disabled.

Technical Details

  • WebRTC Protocol: WhatsApp Calling exchanges SDP offers/answers over HTTPS and streams media via SRTP over UDP. WAVoice uses aiortc and Pipecat's SmallWebRTCTransport to negotiate codecs and stream PCM audio.
  • Webhook Delivery Deduplication: Meta delivers webhooks at least once, causing race conditions where multiple workers answer the same call. WAVoice uses atomic in-memory claiming per call_id to guarantee calls are answered exactly once.
  • Bi-directional Termination: If the caller hangs up, WAVoice tears down the pipeline. If the bot hangs up or times out, WAVoice calls POST /v21.0/{phone_number_id}/calls with action: "terminate" to end the call on the user's phone.
  • Telemetry & Privacy: WAVoice collects anonymous usage metrics (command runs, answered calls, and coarse country/timezone) to improve SDK stability. No personal info, phone numbers, tokens, or audio data are ever collected. Telemetry is enabled by default, and you can opt out at any time by:
    • Running wavoice init --no-telemetry or wavoice start --no-telemetry
    • Setting WAVOICE_TELEMETRY=false in .env
    • Setting DO_NOT_TRACK=1 in your environment

Maintainer & Credits

Crafted by Amit Bhakt (@amitbhakt).

Contributions, issues, and feature suggestions are welcome on GitHub at https://github.com/amitbhakt/wavoice.


License

MIT License. Copyright (c) 2026 Amit Bhakt.

Metadata

Release files for wavoice 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for wavoice 0.1.0
File Size Uploaded
wavoice-0.1.0.tar.gz 25.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for wavoice 0.1.0
File Interpreter ABI Platform
wavoice-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 57.8 kB

Release files / wavoice-0.1.0.tar.gz

Download URL wavoice-0.1.0.tar.gz
Size 25.7 kB
Tags Source
SHA-256 checksum
How to use checksums
90ad45a48e9969e91223bec36b0287b928401f44e37c159d29206afd6748c11e
BLAKE2b-256 checksum
How to use checksums
09bd95d994e6ee4b61976b7819de61d48466565256056810179146149c9aaa55
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.13 {"installer":{"name":"uv","version":"0.12.13","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / wavoice-0.1.0-py3-none-any.whl

Download URL wavoice-0.1.0-py3-none-any.whl
Size 32.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4899f315902d8eeff09441f177cdcf6b750ca2487e470a4ef3b76ddb6562db76
BLAKE2b-256 checksum
How to use checksums
30c97a5df84f7dcff1a68788ce680df359babf853b95dc85d4e7bd9a3f459237
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.13 {"installer":{"name":"uv","version":"0.12.13","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page