AI Customer Service
PraisonAI Call is a feature that enables voice-based interaction with AI models through phone calls. This functionality allows users to have natural conversations with AI agents over traditional phone lines.Installation
Step 1
Step 2
Buy a number at PraisonAI DashboardStep 3
Enter the Public URL in the PraisonAI Dashboard phone number fieldAuthentication
The PraisonAI Call server now requires authentication configuration for security. You have two options:Option 1: Token Authentication (Recommended)
Set a secure token for API authentication:Option 2: Disable Authentication (Local Development Only)
For local development on your own machine, you can disable authentication. The CLI sets the bind-host env var for you, so this is enough when launching viapraisonai call:
uvicorn, embedding praisonai.api.agent_invoke in another app, or any path that does NOT go through praisonai call / praisonai serve), you must also pin the bind host:
PRAISONAI_CALL_BIND_HOST set to a localhost value, every request is rejected with:
Authentication Flow
WhenCALL_SERVER_TOKEN is not configured and the environment is not development, the server returns:
PRAISONAI_CALL_AUTH=disabled is set but the bind host is not localhost:
Environment Variables
Importing
praisonai.api.call no longer loads .env at import time (was a silent side effect). The praisonai call CLI still loads it explicitly at run time — user-facing behaviour is unchanged. To restore the legacy import-time behaviour (e.g. in a wrapper module that imports the call server but bypasses main()), set PRAISONAI_CALL_LOAD_DOTENV=true.Point the realtime endpoint elsewhere (Azure / self-hosted)
By default the call server connects the Twilio media leg to OpenAI Realtime atwss://api.openai.com/v1/realtime?model=gpt-4o-realtime-preview-2024-10-01 using OPENAI_API_KEY. Teams on Azure OpenAI, OpenRouter, or a self-hosted OpenAI-compatible realtime gateway can override the endpoint without editing the module.
PRAISONAI_REALTIME_URL contains openai.com, the server keeps sending the OpenAI-Beta: realtime=v1 header; for any other host, only Authorization: Bearer … is sent.
Connection timeouts
The realtime WebSocket runs with bounded connect / heartbeat / close so a dead upstream cannot hold a Twilio media leg (and phone number) indefinitely.Introduced in v4.6.163 (PraisonAI PR #3879). Prior to this release, a stuck realtime connection kept the Twilio call live until the carrier hung up — which continues to be billed. These are hardcoded, not env-tunable; open an issue if you need a knob.
Media-stream session tokens
The Twilio path is unchanged —/incoming-call mints a one-shot, 60-second, single-use session token and embeds it as ?session=<token> in the returned TwiML stream URL. /media-stream validates and consumes it once.
Effect for Twilio operators: nothing to configure — the change is transparent for
praisonai call / praisonai call --public. Custom integrations that hard-coded the token in the media-stream URL must move it to the x-call-token header.x-call-token header:
All token comparisons (HTTP
Authorization, header x-call-token, n8n verify_token, media-stream session tokens) are constant-time (hmac.compare_digest). Connection-count and per-IP rate-limit counters are guarded by asyncio.Locks, so MAX_CONCURRENT_CONNECTIONS and MAX_REQUESTS_PER_WINDOW cannot be over-committed by concurrent WebSocket opens.
Binding & Network Access
The call server binds to127.0.0.1 by default, so it is only reachable from the same machine.
Features
- Make and receive phone calls with AI agents
- Natural language processing for voice interactions
- Support for multiple phone carriers and providers
- Call recording and transcription capabilities
- Integration with other PraisonAI features
Adding Tools
- Create a file called
tools.py - Add the following code:
Manage Google Calendar Events
See Google Calendar ToolsDeploy
Docker Deployment
How It Works
A caller dials your number, the provider forwards audio to the call server, and the Agent responds with synthesized speech.Best Practices
Always set CALL_SERVER_TOKEN in production
Always set CALL_SERVER_TOKEN in production
The server fails with 503 unless a token is set or auth is explicitly disabled for localhost. Never disable auth on a public bind.
Keep the default localhost bind
Keep the default localhost bind
praisonai call binds to 127.0.0.1 by default. Add --host 0.0.0.0 only inside a container or when you deliberately expose the LAN.Set secrets via environment variables
Set secrets via environment variables
Export
OPENAI_API_KEY, NGROK_AUTH_TOKEN, and CALL_SERVER_TOKEN in your shell — never inline the raw values.Use the x-call-token header for direct WebSocket clients
Use the x-call-token header for direct WebSocket clients
/media-stream no longer accepts ?token= in the query string. Direct callers must pass x-call-token: $CALL_SERVER_TOKEN as a WebSocket handshake header. Twilio flows are unaffected.Add tools for real actions
Add tools for real actions
Register async tool handlers (like a stock-price lookup) so the phone agent can fetch live data during a call.
Related
Tools
Give your call agent live data and actions.
Security
Harden the call server before exposing it.

