Developing Voice AI Agents on VAPI: Implementation and Optimization
Is your client complaining that the bot interrupts or responds slowly? Most often the problem lies in incorrect interruption configuration and STT selection. We develop voice AI agents on VAPI — a platform that gives you full control over the stack: from transport to the model. Our experience: over 5 years and 50+ implemented projects, so we guarantee a reduction in p99 latency down to 800 ms and natural dialogue.
VAPI (Voice API) is an infrastructure platform for building voice AI agents with a developer focus. Unlike no-code solutions, VAPI provides full control over the stack: choice of STT provider (Deepgram, AssemblyAI), LLM (GPT-4o, Claude, Llama), TTS (ElevenLabs, Azure, OpenAI) and transport layer (WebRTC, PSTN, SIP). This allows creating agents with RAG, function calling, and custom voices that work 10 times faster than standard IVR systems.
VAPI Agent Architecture
Phone Call / WebRTC
↓
[VAPI Transport Layer]
↓
[STT: Deepgram / Whisper]
↓
[LLM: GPT-4o / Claude] ←→ [Function Calls / Tools]
↓
[TTS: ElevenLabs / Azure]
↓
Audio Response
Why VAPI over Twilio or a Custom Solution?
Twilio Voice API is a low-level SIP stack where you have to connect each latency stage (STT, LLM, TTS) yourself. VAPI aggregates all stages in a single API call, handling timeouts and interruptions out of the box. The result: p99 latency 40% lower, and development costs 2–3 times less. For production, this means up to 40% savings on infrastructure and operators.
Creating an Agent via VAPI API
import requests
from typing import Optional
class VAPIAgentBuilder:
def __init__(self, api_key: str):
self.api_key = api_key
self.base_url = "https://api.vapi.ai"
self.headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
}
def create_assistant(self, name: str,
system_prompt: str,
model: str = "gpt-4o",
voice_provider: str = "elevenlabs",
voice_id: str = "rachel",
tools: Optional[list] = None) -> dict:
assistant_config = {
"name": name,
"model": {
"provider": "openai" if "gpt" in model else "anthropic",
"model": model,
"systemPrompt": system_prompt,
"temperature": 0.7,
},
"voice": {
"provider": voice_provider,
"voiceId": voice_id,
"speed": 1.0,
"stability": 0.5,
},
"transcriber": {
"provider": "deepgram",
"model": "nova-2",
"language": "ru",
},
"firstMessage": "Здравствуйте! Чем могу помочь?",
"endCallMessage": "Спасибо за звонок. До свидания!",
"endCallFunctionEnabled": True,
"silenceTimeoutSeconds": 20,
"maxDurationSeconds": 600,
}
if tools:
assistant_config["model"]["tools"] = tools
response = requests.post(
f"{self.base_url}/assistant",
json=assistant_config,
headers=self.headers
)
return response.json()
def create_tool(self, name: str,
description: str,
parameters: dict,
server_url: str) -> dict:
return {
"type": "function",
"function": {
"name": name,
"description": description,
"parameters": {
"type": "object",
"properties": parameters,
"required": list(parameters.keys())
}
},
"server": {
"url": server_url,
"timeoutSeconds": 5,
}
}
def create_outbound_call(self, assistant_id: str,
phone_number: str,
customer_data: dict = None) -> dict:
payload = {
"assistantId": assistant_id,
"customer": {
"number": phone_number,
"name": customer_data.get("name", "") if customer_data else "",
},
}
if customer_data:
payload["assistantOverrides"] = {
"variableValues": customer_data
}
response = requests.post(
f"{self.base_url}/call",
json=payload,
headers=self.headers
)
return response.json()
def setup_inbound_phone_number(self, phone_number: str,
assistant_id: str) -> dict:
payload = {
"number": phone_number,
"assistantId": assistant_id,
"fallbackDestination": {
"type": "number",
"number": "+1234567890"
}
}
response = requests.post(
f"{self.base_url}/phone-number",
json=payload,
headers=self.headers
)
return response.json()
How to Reduce Latency to a Comfortable Minimum?
Latency consists of three stages: speech recognition (STT), model logic (LLM), and synthesis (TTS). In VAPI, you can influence each:
- STT choice: Deepgram Nova-2 gives ~250 ms with WER 8%, OpenAI Whisper ~600 ms but more accurate. For Russian-language projects, Whisper is often chosen.
- Interruptions: enabling
interruptionsEnabledand settingnumWordsToInterruptAssistant = 1allows the user to interrupt the agent without delay. - Transport: WebRTC is faster than PSTN — use it for clients in the region.
- Load balancing: deploy LLM on endpoints with low latency, for example via vLLM or Groq.
In practice, after optimization, p99 latency is 600–900 ms — a comfortable level for dialogue.
How to Configure Interruptions for Natural Dialogue?
VAPI allows fine-tuning parameters that affect conversational naturalness:
-
interruptionsEnabled— allows the user to interrupt the agent. Critical for dialogue naturalness. -
backgroundDenoisingEnabled— background noise filtering via Krisp. -
numWordsToInterruptAssistant— how many words from the user are needed to interrupt the agent (recommended 1-2). -
backchannelingEnabled— agent utters “uh-huh”, “I see” during pauses.
Example configuration for low latency
{
"model": {
"provider": "openai",
"model": "gpt-4o",
"temperature": 0.7
},
"voice": {
"provider": "elevenlabs",
"voiceId": "rachel",
"speed": 1.0
},
"transcriber": {
"provider": "deepgram",
"model": "nova-2",
"language": "ru"
},
"interruptionsEnabled": true,
"numWordsToInterruptAssistant": 1,
"backchannelingEnabled": false
}
Integration with WebRTC for Web Calls
import Vapi from "@vapi-ai/web";
const vapi = new Vapi("YOUR_PUBLIC_KEY");
vapi.start({
assistantId: "your-assistant-id",
});
vapi.on("call-start", () => console.log("Call started"));
vapi.on("call-end", () => console.log("Call ended"));
vapi.on("message", (message) => {
if (message.type === "transcript") {
console.log(message.role, message.transcript);
}
if (message.type === "function-call") {
console.log("Tool:", message.functionCall.name);
}
});
STT Provider Comparison in VAPI
| Provider | Latency (WER) | Russian | Cost |
|---|---|---|---|
| Deepgram Nova-2 | ~250ms, WER 8% | good | $0.0059/min |
| AssemblyAI Universal | ~400ms, WER 7% | good | $0.0065/min |
| OpenAI Whisper | ~600ms, WER 6% | excellent | $0.006/min |
| Azure Cognitive | ~300ms, WER 9% | good | $0.016/min |
Latency Optimization Parameters
| Parameter | Default Value | Recommendation |
|---|---|---|
interruptionsEnabled |
false | true |
numWordsToInterruptAssistant |
3 | 1-2 |
backgroundDenoisingEnabled |
false | true (if noise) |
| Transport | PSTN | WebRTC |
What's Included in the Work
Each project includes:
- Agent architecture with optimal provider selection for your scenario.
- Implementation of Function Calls for integration with your systems (CRM, knowledge bases).
- Configuration of interruptions and limits for natural dialogue.
- Deployment to production (SageMaker, Vercel, own server).
- Code documentation and maintenance instructions.
- Warranty support for one month after launch.
Typical Mistakes When Developing a VAPI Agent
- Enabling interruptions without testing real scenarios: the agent does not listen to long responses.
- Using PSTN instead of WebRTC: latency is 1–2 seconds higher.
- Ignoring Function Call timeouts: if the endpoint takes longer than 5 seconds, the agent freezes.
- Missing fallback number: on error, the client should switch to an operator.
Timelines and Cost
A prototype of a voice agent with a basic scenario — from 2 to 3 days. A full-fledged solution with integrations, testing, and training — from 3 to 5 weeks. Cost is calculated individually for your project. Contact us to get a prototype in 2-3 days. Request a consultation to evaluate your scenario.
Source: VAPI REST API







