The Concept
Vapi Architecture
| What Vapi Handles | What You Bring |
|---|
| Telephony integration | LLM API key (OpenAI, Anthropic) |
| ASR (Deepgram built-in) | TTS API key (Cartesia, ElevenLabs) |
| VAD + endpointing | Phone number (or use Vapi's) |
| Barge-in | System prompt |
| Conversation state | Function definitions |
| Call recording | Webhooks for events |
| Call analytics | — |
What does "BYO-stack" mean in the context of Vapi?
Bring Your Own — you provide the LLM, TTS, and phone number, Vapi handles everything else (telephony, ASR, VAD, endpointing, barge-in)
Creating a Vapi Agent
import requests
def create_vapi_agent():
"""Create a voice agent on Vapi."""
response = requests.post(
"https://api.vapi.ai/assistant",
headers={"Authorization": f"Bearer {VAPI_API_KEY}"},
json={
"name": "DeVenture Airlines Agent",
"transcriber": {
"provider": "deepgram",
"model": "nova-2",
"language": "en-US"
},
"model": {
"provider": "openai",
"model": "gpt-4o-mini",
"messages": [
{
"role": "system",
"content": "You are a DeVenture Airlines voice agent. Keep responses to 1-3 sentences. Be conversational."
}
],
"temperature": 0.7,
"maxTokens": 250
},
"voice": {
"provider": "cartesia",
"voiceId": "79125125-1e22-47a6-9e8e-f4e1c4b2b914"
},
"silenceTimeoutSeconds": 30,
"responseDelaySeconds": 0.5,
"llmRequestDelaySeconds": 0.1,
}
)
return response.json()
Making Outbound Calls
def make_call(phone_number, assistant_id):
"""Make an outbound call via Vapi."""
response = requests.post(
"https://api.vapi.ai/call",
headers={"Authorization": f"Bearer {VAPI_API_KEY}"},
json={
"assistantId": assistant_id,
"phoneNumberId": "your-vapi-phone-id",
"customer": {
"number": phone_number
}
}
)
return response.json()
Function Calling in Vapi
"model": {
"provider": "openai",
"model": "gpt-4o-mini",
"messages": [...],
"tools": [
{
"type": "function",
"function": {
"name": "check_flight_status",
"description": "Check flight status",
"parameters": {
"type": "object",
"properties": {
"flight_number": {"type": "string"}
}
}
},
"async": False,
"serverUrl": "https://your-server.com/webhook/vapi-tool"
}
]
}
When the LLM calls a function, Vapi sends a webhook to your server:
@app.post("/webhook/vapi-tool")
async def handle_vapi_tool(request):
"""Handle function call from Vapi."""
data = await request.json()
tool_name = data["toolCall"]["name"]
args = data["toolCall"]["arguments"]
if tool_name == "check_flight_status":
result = await check_flight_status(**args)
return {"result": result}
Vapi vs Building from Scratch
| Factor | Vapi | From Scratch (Pipecat) |
|---|
| Setup time | Hours | Days/Weeks |
| Telephony | Included (Twilio/Vonage) | Wire yourself |
| ASR | Deepgram built-in | Configure yourself |
| VAD/Endpointing | Built-in | Implement yourself |
| Barge-in | Built-in | Implement yourself |
| LLM choice | BYO (OpenAI, Anthropic) | Any |
| TTS choice | BYO (Cartesia, ElevenLabs) | Any |
| Cost | $0.05/min + provider costs | Provider costs only |
| Customization | Medium | Full |
| Call analytics | Built-in dashboard | Build yourself |
| Call recording | Built-in | Build yourself |
Vapi Configuration Options
| Parameter | Default | Purpose |
|---|
silenceTimeoutSeconds | 30 | Hang up if caller silent |
responseDelaySeconds | 0.5 | Delay before agent responds |
llmRequestDelaySeconds | 0.1 | Delay before LLM call |
maxDurationSeconds | 600 | Max call duration |
backgroundSound | "office" | Ambient background sound |
customMessages | {} | Custom voicemail, idle messages |
firstMessage | "" | Agent's first message |
endCallMessage | "" | Agent's goodbye message |
Unlock the full lesson
You've read the first 2 sections. The rest of this lesson covers Build It, Use It, Ship It, Evaluation, Key Terms, Common Pitfalls, Interview Framing — plus a hands-on lab, quiz, and project artifact.
Create a free account to unlock Phase 0 and Phase 1 of every course — no credit card.