How to Build a Voice AI Agent: The Complete Guide (2026)

Text-based AI agents are everywhere. But voice AI agents — the ones that actually talk to your customers on the phone, handle appointments, and close deals — are where the real money is in 2026.

The voice AI market hit $8.2 billion in 2025 and is projected to cross $15 billion by 2027. Companies like Bland.ai are handling millions of calls. Vapi processes tens of thousands of concurrent voice sessions. And the cost? A voice AI agent costs roughly $0.08-0.15 per minute versus $1-3 per minute for a human agent.

This guide covers everything: the voice AI stack, architecture patterns, platform comparisons, production code, and the mistakes that kill voice agent projects before they launch.

$0.10
Cost per minute (avg)
500ms
Target latency
85%
Resolution rate
24/7
Availability

How Voice AI Agents Actually Work

Every voice AI agent follows the same fundamental pipeline. Understanding it is the difference between building something that works and building something that frustrates every caller.

The Voice AI Pipeline

Voice AI has four stages that run in a continuous loop:

  1. Speech-to-Text (STT) — Convert audio input to text. Deepgram, AssemblyAI, or Whisper. Latency target: <300ms.
  2. Language Understanding (LLM) — Process the text, maintain context, decide what to do. Claude, GPT-4o, or Gemini. Latency target: <500ms for first token.
  3. Text-to-Speech (TTS) — Convert the response back to natural-sounding audio. ElevenLabs, Cartesia, or PlayHT. Latency target: <200ms.
  4. Telephony/WebRTC — Handle the actual voice connection. Twilio, Vonage, or WebRTC for browser-based. Always-on duplex audio.

The total round-trip — from when the user stops speaking to when they hear a response — needs to be under 800ms to feel natural. Over 1.5 seconds and callers start saying "hello? are you there?"

⚡ The Latency Tax: Every millisecond matters. A voice agent with 2-second latency has a 40% higher hang-up rate than one with 500ms latency. Optimize for speed first, accuracy second. You can always add post-processing — you can't add patience.

Streaming vs. Batch Processing

The old way: wait for the user to finish speaking → transcribe → process → generate audio → play back. Total latency: 3-5 seconds. Terrible.

The modern way: streaming everything.

With full streaming, you can get voice-to-voice latency under 500ms. That's faster than most humans think before responding.

The Voice AI Tech Stack

You have three options: use a managed platform, build on an orchestration layer, or go fully custom. Here's the honest breakdown.

Option 1: Managed Platforms (Ship in Days)

Platform Best For Pricing Latency
Vapi Developer-first, custom flows $0.05/min + provider costs ~600ms
Bland.ai High-volume outbound calls $0.07-0.09/min all-in ~500ms
Retell AI Realistic conversations $0.07-0.14/min ~550ms
Vocode Open-source, self-hosted Provider costs only ~700ms
Play AI Ultra-realistic voices $0.08/min + LLM costs ~650ms

Our recommendation: Start with Vapi or Retell if you're building a product. Use Bland if you need outbound at scale. Use Vocode if you need full control and don't mind ops work.

Option 2: Build Your Own Stack

For maximum control, wire the components yourself:

Component Budget Pick Pro Pick Enterprise Pick
STT Whisper (self-hosted) Deepgram Nova-2 AssemblyAI Universal-2
LLM Claude 3.5 Haiku GPT-4o-mini Claude Sonnet / GPT-4o
TTS Cartesia Sonic ElevenLabs Turbo v2.5 Custom cloned voice
Telephony Twilio Twilio / Vonage Telnyx / custom SIP
Cost/min ~$0.04 ~$0.10 ~$0.15

Architecture Deep Dive

The Conversation State Machine

Voice agents aren't just chat agents with audio. They need to handle things text agents never deal with: interruptions, silence, background noise, emotional tone, and the fact that humans don't speak in clean paragraphs.

Here's the state machine every voice agent needs:

┌─────────────┐
│   LISTENING  │ ← Waiting for user speech
└──────┬──────┘
       │ Voice Activity Detected
       ▼
┌─────────────┐
│  PROCESSING  │ ← STT → LLM → TTS pipeline
└──────┬──────┘
       │ Audio ready
       ▼
┌─────────────┐
│  SPEAKING    │ ← Playing TTS audio
└──────┬──────┘
       │ User interrupts OR audio complete
       ▼
┌─────────────┐        ┌──────────────┐
│  LISTENING   │───────▶│  INTERRUPTED  │
└─────────────┘        └──────┬───────┘
                              │ Stop audio, process new input
                              ▼
                       ┌──────────────┐
                       │  PROCESSING   │
                       └──────────────┘

The critical feature: interruption handling. When a user starts talking while the agent is speaking, you need to:

  1. Immediately stop audio playback
  2. Discard any buffered audio not yet played
  3. Keep the context of what was said so far
  4. Process the new user input with full context

This is called barge-in, and it's what separates real voice agents from interactive voice jail (IVR).

Production Voice Agent — Python Implementation

Here's a production-ready voice agent using Vapi's SDK. This handles inbound calls, tool execution, and conversation management:

# voice_agent.py — Production voice agent with Vapi
import os
import json
from vapi import Vapi
from datetime import datetime

# Initialize Vapi client
vapi = Vapi(api_key=os.environ["VAPI_API_KEY"])

# Define the assistant configuration
assistant_config = {
    "name": "Support Agent",
    "model": {
        "provider": "anthropic",
        "model": "claude-sonnet-4-20250514",
        "temperature": 0.3,
        "systemPrompt": """You are a friendly, efficient customer support agent 
for TechCorp. You handle billing questions, account issues, and product support.

RULES:
- Keep responses under 2 sentences when possible
- Ask ONE question at a time
- If you can't help, offer to transfer to a human
- Never make up information about account details
- Confirm before making any account changes

TONE: Warm but professional. Like a helpful colleague, not a robot.
Don't say "I understand your frustration" — just solve the problem."""
    },
    "voice": {
        "provider": "elevenlabs",
        "voiceId": "21m00Tcm4TlvDq8ikWAM",  # Rachel - warm, professional
        "stability": 0.6,
        "similarityBoost": 0.8
    },
    "firstMessage": "Hey there! How can I help you today?",
    "transcriber": {
        "provider": "deepgram",
        "model": "nova-2",
        "language": "en"
    },
    "endCallPhrases": ["goodbye", "that's all", "bye"],
    "silenceTimeoutSeconds": 30,
    "maxDurationSeconds": 600,
    "backgroundSound": "off"
}

# Define tools the agent can use
tools = [
    {
        "type": "function",
        "function": {
            "name": "lookup_account",
            "description": "Look up customer account by email or phone number",
            "parameters": {
                "type": "object",
                "properties": {
                    "identifier": {
                        "type": "string",
                        "description": "Email or phone number"
                    }
                },
                "required": ["identifier"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "check_order_status",
            "description": "Check the status of an order by order ID",
            "parameters": {
                "type": "object",
                "properties": {
                    "order_id": {
                        "type": "string",
                        "description": "The order ID (e.g., ORD-12345)"
                    }
                },
                "required": ["order_id"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "transfer_to_human",
            "description": "Transfer the call to a human agent",
            "parameters": {
                "type": "object",
                "properties": {
                    "department": {
                        "type": "string",
                        "enum": ["billing", "technical", "sales"],
                        "description": "Department to transfer to"
                    },
                    "reason": {
                        "type": "string",
                        "description": "Brief reason for transfer"
                    }
                },
                "required": ["department", "reason"]
            }
        }
    }
]

# Tool execution handlers
def handle_tool_call(tool_name: str, args: dict) -> str:
    if tool_name == "lookup_account":
        # In production: query your database
        return json.dumps({
            "found": True,
            "name": "Jane Smith",
            "plan": "Pro",
            "status": "active",
            "balance": "$0.00"
        })
    elif tool_name == "check_order_status":
        return json.dumps({
            "order_id": args["order_id"],
            "status": "shipped",
            "tracking": "1Z999AA10123456784",
            "eta": "Feb 21, 2026"
        })
    elif tool_name == "transfer_to_human":
        return json.dumps({
            "transferred": True,
            "department": args["department"],
            "wait_time": "~2 minutes"
        })
    return json.dumps({"error": "Unknown tool"})

# Create the assistant
assistant = vapi.assistants.create(**assistant_config)
print(f"✅ Assistant created: {assistant.id}")

# Set up a phone number (Twilio integration)
phone = vapi.phone_numbers.create(
    provider="twilio",
    number="+1234567890",  # Your Twilio number
    assistant_id=assistant.id
)
print(f"📞 Phone number active: {phone.number}")

Webhook Server for Tool Calls

Vapi sends tool calls to your webhook. Here's the server that handles them:

# server.py — Webhook server for voice agent tool calls
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
import json

app = FastAPI()

@app.post("/webhook/vapi")
async def vapi_webhook(request: Request):
    body = await request.json()
    event_type = body.get("message", {}).get("type")
    
    if event_type == "function-call":
        tool_name = body["message"]["functionCall"]["name"]
        args = body["message"]["functionCall"]["parameters"]
        
        result = handle_tool_call(tool_name, args)
        
        return JSONResponse({
            "result": result
        })
    
    elif event_type == "end-of-call-report":
        # Log call analytics
        report = body["message"]
        log_call({
            "call_id": report.get("callId"),
            "duration": report.get("duration"),
            "cost": report.get("cost"),
            "transcript": report.get("transcript"),
            "summary": report.get("summary"),
            "ended_reason": report.get("endedReason"),
            "timestamp": datetime.now().isoformat()
        })
        return JSONResponse({"status": "ok"})
    
    return JSONResponse({"status": "ok"})

def log_call(data: dict):
    """Log call data for analytics."""
    with open("call_logs.jsonl", "a") as f:
        f.write(json.dumps(data) + "\n")
    print(f"📊 Call logged: {data['call_id']} "
          f"({data['duration']}s, ${data['cost']:.4f})")

Want the Complete AI Agent Playbook?

Voice agents, text agents, multi-agent systems — our playbook covers it all with production code, templates, and deployment guides.

Get the Playbook — €29

Voice-Specific Design Patterns

Voice agents need patterns that text agents don't. Here are the five that matter most.

Pattern 1: Turn-Taking Detection

How does the agent know when the user is done speaking? Three approaches:

Best practice: Use endpoint detection as the primary signal, with a 700ms silence fallback. This catches 95% of natural turn boundaries.

Pattern 2: Backchanneling

Humans use "uh-huh", "right", "okay" to signal they're listening. Your voice agent should too — especially during long user turns.

# Backchannel configuration
backchannel_config = {
    "enabled": True,
    "phrases": ["mhm", "right", "got it", "okay"],
    "trigger_after_seconds": 4,  # Backchannel if user speaks 4+ seconds
    "min_gap_seconds": 3,       # Don't backchannel too frequently
    "audio_overlap": True       # Play over user speech (not interrupting)
}

Without backchanneling, users on long explanations will stop and ask "are you still there?" — destroying the conversational flow.

Pattern 3: Emotional Tone Detection

A frustrated customer needs a different response than a curious one. Modern STT providers can detect emotion from voice characteristics:

# Emotion-aware response routing
async def process_with_emotion(transcript: str, emotion: dict):
    """Adjust system prompt based on detected emotion."""
    
    base_prompt = get_system_prompt()
    
    if emotion.get("anger", 0) > 0.7:
        base_prompt += """
        
The customer sounds frustrated. Be extra empathetic.
Skip the pleasantries — get straight to solving their problem.
Offer to escalate to a human immediately if you can't resolve in 2 turns."""
    
    elif emotion.get("confusion", 0) > 0.6:
        base_prompt += """
        
The customer sounds confused. Use simpler language.
Break your response into smaller steps.
Ask if they'd like you to explain anything differently."""
    
    elif emotion.get("happiness", 0) > 0.7:
        base_prompt += """
        
The customer sounds positive. Match their energy.
This might be a good time to mention upgrades or new features."""
    
    return await llm_generate(base_prompt, transcript)

Pattern 4: Graceful Degradation

Voice connections fail. Audio quality drops. Background noise makes transcription impossible. Your agent needs fallback strategies:

# Filler phrases for latency spikes
FILLER_PHRASES = [
    "Let me check that for you...",
    "One moment...",
    "I'm looking into that right now...",
    "Bear with me just a second..."
]

async def generate_with_filler(prompt: str, max_latency_ms: int = 1500):
    """If LLM takes too long, play a filler phrase."""
    
    filler_task = asyncio.create_task(
        play_filler_after_delay(max_latency_ms)
    )
    
    try:
        response = await asyncio.wait_for(
            llm_generate(prompt), 
            timeout=max_latency_ms / 1000
        )
        filler_task.cancel()
        return response
    except asyncio.TimeoutError:
        # Filler is already playing, wait for actual response
        response = await llm_generate(prompt)
        return response

Pattern 5: Context Window Management

Phone calls can be long. A 10-minute call generates ~1,500 words of transcript. A 30-minute call: ~4,500 words. You'll hit context limits fast if you're sending the full transcript every turn.

# Sliding window context management
class ConversationContext:
    def __init__(self, max_turns: int = 20, summary_threshold: int = 15):
        self.turns = []
        self.summary = ""
        self.max_turns = max_turns
        self.summary_threshold = summary_threshold
    
    def add_turn(self, role: str, content: str):
        self.turns.append({"role": role, "content": content})
        
        if len(self.turns) > self.summary_threshold:
            self._summarize_old_turns()
    
    def _summarize_old_turns(self):
        """Summarize older turns to keep context small."""
        old_turns = self.turns[:10]
        self.turns = self.turns[10:]
        
        summary_prompt = f"""Summarize this conversation so far in 2-3 sentences.
        Focus on: what the customer needs, decisions made, actions taken.
        
        {json.dumps(old_turns)}"""
        
        self.summary = llm_generate_sync(summary_prompt)
    
    def get_context(self) -> list:
        """Return context for LLM with summary + recent turns."""
        messages = []
        if self.summary:
            messages.append({
                "role": "system",
                "content": f"Previous conversation summary: {self.summary}"
            })
        messages.extend(self.turns[-self.max_turns:])
        return messages

Outbound Voice Agents

Inbound (answering calls) is the easy part. Outbound (making calls) is where voice AI gets really interesting — and really tricky.

Use Cases That Actually Work

Outbound Campaign Setup

# outbound_campaign.py — Automated outbound calling with Bland.ai
import requests
import csv
from datetime import datetime

BLAND_API_KEY = os.environ["BLAND_API_KEY"]

def launch_campaign(contacts_csv: str, campaign_config: dict):
    """Launch an outbound calling campaign."""
    
    contacts = load_contacts(contacts_csv)
    results = []
    
    for contact in contacts:
        call = requests.post(
            "https://api.bland.ai/v1/calls",
            headers={"Authorization": BLAND_API_KEY},
            json={
                "phone_number": contact["phone"],
                "task": campaign_config["script"].format(**contact),
                "voice": "mason",
                "first_sentence": f"Hi {contact['name']}, this is Alex from TechCorp.",
                "wait_for_greeting": True,
                "max_duration": 300,  # 5 min max
                "model": "enhanced",
                "temperature": 0.4,
                "transfer_phone_number": "+1987654321",  # Human fallback
                "metadata": {
                    "contact_id": contact["id"],
                    "campaign": campaign_config["name"]
                },
                "webhook": "https://your-server.com/webhook/bland",
                "record": True
            }
        )
        
        results.append({
            "contact": contact["name"],
            "call_id": call.json().get("call_id"),
            "status": call.json().get("status")
        })
    
    return results

# Campaign configuration
appointment_campaign = {
    "name": "Q1 Appointment Reminders",
    "script": """You are calling to remind {name} about their upcoming 
appointment on {appointment_date} at {appointment_time}. 

Ask if they'd like to:
1. Confirm the appointment
2. Reschedule
3. Cancel

If they want to reschedule, offer available slots: 
Monday-Friday, 9 AM to 5 PM.

Be friendly and brief. Don't pressure them."""
}

# Launch
results = launch_campaign("contacts.csv", appointment_campaign)
print(f"📞 Launched {len(results)} calls")
⚠️ Legal Requirements: Outbound AI calling is regulated. In the US, you need prior express consent for marketing calls (TCPA). In the EU, GDPR applies. Always: disclose it's an AI, honor do-not-call lists, record consent, and provide opt-out. Violations carry fines of $500-$1,500 per call in the US.

Voice Agent System Prompts That Work

System prompts for voice agents are fundamentally different from text agent prompts. They need to be shorter (latency), more structured (speech patterns), and include voice-specific instructions.

# Production system prompt for a voice AI agent
VOICE_AGENT_PROMPT = """You are Sarah, a customer support specialist at [Company].

## Voice Rules
- Keep responses under 30 words when possible
- Never use bullet points, numbered lists, or markdown
- Use conversational fillers naturally: "So...", "Well...", "Let me see..."
- Spell out numbers: "twenty-three" not "23"
- Spell out abbreviations: "appointment" not "appt"
- Use contractions: "I'll" not "I will", "can't" not "cannot"
- End statements with slight upward inflection words when appropriate

## Conversation Flow
1. Greet warmly (first message only)
2. Identify the issue (ask ONE question)
3. Solve or escalate (max 3 attempts before offering human)
4. Confirm resolution
5. Close naturally

## What NOT to Do
- Don't say "As an AI..." or "I'm an artificial..."
- Don't apologize more than once per call
- Don't read out long URLs or reference numbers digit by digit
- Don't use phrases like "I understand your frustration"
- Don't ask "Is there anything else?" more than once

## Tool Usage
- Look up accounts before asking the customer for details you should know
- Always confirm before making changes: "I'll update your address to... does that sound right?"
- If a tool fails, say "Let me try that again" — don't explain the technical issue

## Handling Difficult Situations
- Angry customer: Acknowledge once, then focus on solutions
- Confused customer: Simplify, use analogies, offer to slow down
- Silent customer (>5s): "Are you still there?" (once), then "I'll give you a moment"
- Background noise: "I'm having a bit of trouble hearing you — could you speak up a little?"
"""

"The best voice agent prompts read like stage directions for an actor, not instructions for a computer."

Monitoring and Analytics

The 7 Metrics That Matter

Metric Target Red Flag
First Response Latency <800ms >1.5s
Resolution Rate >80% <60%
Average Handle Time 2-4 min >8 min
Hang-up Rate <15% >30%
Transfer Rate <20% >40%
Customer Satisfaction >4.0/5 <3.0/5
Cost per Resolution <$0.50 >$2.00

Call Analytics Dashboard

# analytics.py — Voice agent call analytics
import json
from collections import defaultdict
from datetime import datetime, timedelta

def analyze_calls(log_file: str, days: int = 7):
    """Analyze call logs and generate report."""
    
    calls = []
    with open(log_file) as f:
        for line in f:
            calls.append(json.loads(line))
    
    cutoff = datetime.now() - timedelta(days=days)
    recent = [c for c in calls 
              if datetime.fromisoformat(c["timestamp"]) > cutoff]
    
    if not recent:
        return "No calls in the last {days} days"
    
    # Core metrics
    total = len(recent)
    avg_duration = sum(c["duration"] for c in recent) / total
    total_cost = sum(c.get("cost", 0) for c in recent)
    
    # Resolution analysis
    resolved = [c for c in recent 
                if c.get("ended_reason") == "customer-ended"]
    transferred = [c for c in recent 
                   if c.get("ended_reason") == "transferred"]
    hangups = [c for c in recent 
               if c.get("ended_reason") in ["silence", "hangup"]]
    
    report = {
        "period": f"Last {days} days",
        "total_calls": total,
        "avg_duration_seconds": round(avg_duration),
        "total_cost": round(total_cost, 2),
        "cost_per_call": round(total_cost / total, 4),
        "resolution_rate": round(len(resolved) / total * 100, 1),
        "transfer_rate": round(len(transferred) / total * 100, 1),
        "hangup_rate": round(len(hangups) / total * 100, 1),
    }
    
    return report

Common Use Cases with Code

Restaurant Reservation Agent

# Restaurant booking voice agent
restaurant_config = {
    "systemPrompt": """You are the booking assistant for Bella Italia restaurant.

Available times: Tue-Sun, 5 PM to 10 PM. Closed Mondays.
Party sizes: 1-8 (larger groups need manager approval)

Flow:
1. Ask for date and time preference
2. Check availability (use check_availability tool)
3. Ask for party size and name
4. Confirm all details
5. "You're all set! We'll see you [day] at [time]."

If fully booked: offer alternative times or waitlist.
Mention: "We have a beautiful patio if you'd prefer outdoor seating."
""",
    "tools": ["check_availability", "create_reservation", "join_waitlist"],
    "voice": "sophia",  # Warm, welcoming
    "firstMessage": "Bella Italia, how can I help you today?"
}

Medical Appointment Scheduler

# Healthcare appointment voice agent
medical_config = {
    "systemPrompt": """You are the scheduling assistant for City Health Clinic.

HIPAA COMPLIANCE:
- Verify patient identity: date of birth + last 4 of SSN
- Never discuss medical details over the phone
- Don't confirm or deny if someone is a patient

Flow:
1. "Are you an existing patient or new patient?"
2. Verify identity (existing) or collect info (new)
3. Ask what type of appointment (general, specialist, follow-up)
4. Offer available slots
5. Confirm and send text reminder

Operating hours: Mon-Fri 8 AM - 6 PM, Sat 9 AM - 1 PM
New patient appointments: 45 min | Follow-ups: 15 min
""",
    "tools": ["verify_patient", "check_schedule", "book_appointment", "send_reminder"],
    "voice": "nova",  # Clear, professional
    "firstMessage": "City Health Clinic, this is the scheduling line. How can I help?"
}

7 Mistakes That Kill Voice Agent Projects

  1. Ignoring latency until launch. If you build features first and optimize latency later, you'll have a voice agent nobody wants to talk to. Latency is feature #1. Budget 500ms, optimize everything else around it.
  2. Using text agent prompts. "Here are your options: 1) Check balance, 2) Make payment, 3) Speak to agent." This works in chat. Over voice, it's an IVR from 2005. Write prompts that sound like natural speech.
  3. No interruption handling. If users can't interrupt your agent mid-sentence, they'll hang up. Barge-in support is non-negotiable. Test it with real callers before launch.
  4. Forgetting about accents and noise. Your STT works great in a quiet office. Now test it with a caller driving on the highway, or someone with a thick regional accent. Use noise-robust models (Deepgram Nova-2, AssemblyAI) and test with diverse audio samples.
  5. No fallback to humans. Voice agents should handle 80-85% of calls. The other 15-20%? Those need seamless handoff to a human. Build the transfer flow from day one, not as an afterthought.
  6. Overcomplicating the first version. Start with ONE use case (e.g., appointment scheduling). Get it to 90% accuracy. Then add more capabilities. Don't build a general-purpose voice agent that does everything badly.
  7. Not recording and reviewing calls. You need to listen to real calls. Every week. Set up automatic transcription logging, flag calls with low satisfaction or high duration, and review them. This is how you actually improve.

Cost Breakdown: What Voice AI Really Costs

Component 100 calls/day 1,000 calls/day 10,000 calls/day
STT (Deepgram) $15/mo $120/mo $900/mo
LLM (Claude Sonnet) $30/mo $250/mo $2,000/mo
TTS (ElevenLabs) $22/mo $180/mo $1,200/mo
Telephony (Twilio) $40/mo $350/mo $3,000/mo
Infrastructure $20/mo $100/mo $500/mo
Total ~$127/mo ~$1,000/mo ~$7,600/mo
Cost per call $0.042 $0.033 $0.025

Compare that to a human call center agent: $15-25/hour, handling 8-12 calls/hour = $1.25-3.12 per call. Voice AI is 30-100x cheaper.

💡 Quick Math: A company handling 500 support calls/day with human agents spends ~$45,000/month on staffing. A voice AI agent handling 80% of those calls costs ~$600/month. That's $44,400/month in savings — or $533K/year. Even with a $50K implementation cost, ROI is under 2 months.

60-Minute Quickstart

Build and deploy a working voice AI agent in one hour. We'll use Vapi (fastest time-to-voice).

1 Create a Vapi account (0-5 min)

Sign up at dashboard.vapi.ai. You get $10 free credits — enough for ~100 test calls.

2 Create your assistant (5-15 min)

In the Vapi dashboard, create a new assistant. Paste the system prompt from this guide. Select a voice (we recommend "rachel" from ElevenLabs for warm, professional tone). Set transcriber to Deepgram Nova-2.

3 Test in the browser (15-25 min)

Click "Test Call" in the dashboard. Have a 5-minute conversation. Note: awkward pauses (latency issue), weird phrasing (prompt issue), or wrong information (tool/knowledge issue). Fix each one.

4 Add tools (25-40 min)

Define your tool functions in Vapi's dashboard or set up the webhook server from this guide. Start with one tool (e.g., lookup_account). Test the full flow: caller asks question → agent calls tool → agent responds with data.

5 Connect a phone number (40-50 min)

Buy a Twilio number ($1/month). Connect it in Vapi's Phone Numbers section. Call it from your phone. You now have a working voice AI agent.

6 Set up monitoring (50-60 min)

Configure the webhook to log all calls. Set up alerts for: calls longer than 5 minutes, hang-ups within 30 seconds, and transfer requests. Review your first 10 calls manually.

🎯 Ready to Build Production AI Agents?

The AI Employee Playbook includes voice agent templates, system prompts, deployment checklists, and the exact architecture patterns used by companies processing thousands of calls daily.

Get the Playbook — €29
🎯 Build AI agents that actually work → Get the Playbook (€29)