For AI agents: a documentation index is available at the root level at /llms.txt and /llms-full.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
WebsiteStatusSupportDashboard
DocumentationAPI ReferenceMCPSDKsCLI (new)What's New?
DocumentationAPI ReferenceMCPSDKsCLI (new)What's New?
  • Get started
    • Introduction
    • Phone calls
    • Web calls
    • Vapi Guides
    • Composer
    • CLI quickstart
  • Assistants
    • Quickstart
    • Tools
    • Custom keywords
    • Custom voices
    • Custom transcriber
    • Custom TTS
      • Appointment scheduling
      • Lead qualification
      • Inbound support
      • Voice widget
      • Documentation agent
      • Support escalation
      • Multilingual agent
  • Observability
    • Boards
  • Squads
    • Quickstart
    • Overview
    • Handoff tool
    • Passing data between assistants
  • Best practices
    • Prompting guide
    • Debugging voice agents
    • Enterprise environments (DEV/UAT/PROD)
    • IVR navigation
  • Phone numbers
    • Free Vapi number
    • Inbound SMS
    • Phone Number Hooks
  • Calls
    • Call end reasons
    • Troubleshoot call errors
  • Outbound Campaigns
    • Quickstart
    • Overview
  • Chat
    • Quickstart
    • Streaming
    • Non-streaming
    • OpenAI compatibility
    • Session management
    • Variable substitution
    • SMS chat
    • Web widget
    • Webhooks
  • Workflows
    • Quickstart
    • Overview
LogoLogo
WebsiteStatusSupportDashboard
On this page
  • Overview
  • Prerequisites
  • Scenario
  • 1. Create a Dynamic Escalation Tool
  • 2. Create an Assistant with Smart Escalation
  • 3. Build Escalation Logic Server
  • 4. Test Your Support Escalation System
  • Advanced Integration Examples
  • CRM Integration (Salesforce)
  • Issue Complexity Assessment
  • Agent Availability Checking
  • Error Handling Best Practices
  • Comprehensive Error Handling
  • Queue Management
  • Next Steps
AssistantsExamples

Customer support escalation system

Build intelligent support routing using assistants that escalate calls based on customer tier, issue complexity, and agent expertise.
Was this page helpful?
Edit this page
Previous

Multilingual support agent

Build a global support agent that handles English, Spanish, and French customer inquiries with automatic language detection and native voice quality
Next
Built with

Overview

Build an intelligent customer support escalation system that determines transfer destinations dynamically using customer tier analysis, issue complexity assessment, and real-time agent availability. This approach uses transfer tools with empty destinations and webhook servers for maximum escalation flexibility.

Agent Capabilities:

  • Customer tier-based prioritization and routing
  • Issue complexity analysis for specialist routing
  • Real-time agent availability and expertise matching
  • Intelligent escalation with context preservation

What You’ll Build:

  • Transfer tool with dynamic escalation logic
  • Assistant with intelligent support conversation flow
  • Webhook server for escalation destination logic
  • CRM integration for customer tier-based routing

Prerequisites

  • A Vapi account
  • Node.js or Python server environment
  • (Optional) CRM or customer database for tier lookup

Scenario

We will build a customer support escalation system for TechCorp that intelligently routes support calls based on customer tier, issue complexity, and agent expertise in real-time.


1. Create a Dynamic Escalation Tool

Dashboard
TypeScript (Server SDK)
Python (Server SDK)
cURL
1

Navigate to Tools

In your Vapi dashboard, click Tools in the left sidebar.

2

Create the escalation tool

  • Click Create Tool
  • Select Transfer Call as the tool type
  • Set tool name: Smart Support Escalation
  • Important: Leave the destinations array empty - this creates a dynamic transfer tool
  • Set function name: escalateToSupport
  • Add description: Escalate calls to appropriate support specialists based on customer tier and issue complexity
3

Configure tool parameters

Add these parameters to help the assistant provide context:

  • issue_category (string): Category of customer issue (technical, billing, account, product)
  • complexity_level (string): Issue complexity (basic, intermediate, advanced, critical)
  • customer_context (string): Relevant customer information for routing
  • escalation_reason (string): Why this needs escalation vs self-service

2. Create an Assistant with Smart Escalation

Dashboard
TypeScript (Server SDK)
Python (Server SDK)
cURL
1

Create assistant

  • Navigate to Assistants in your dashboard
  • Click Create Assistant
  • Name: TechCorp Support Assistant
  • Add your dynamic escalation tool to the assistant’s tools
2

Configure system prompt

System Prompt
You are TechCorp's intelligent customer support assistant. Your job is to:
1. Help customers resolve issues when possible
2. Assess issue complexity and customer needs
3. Escalate to human specialists when appropriate using the escalateToSupport function
Try to resolve simple issues first. For complex issues or when customers request human help, escalate intelligently based on:
- Issue category (technical, billing, account, product)
- Complexity level (basic, intermediate, advanced, critical)
- Customer context and history
Always be professional and efficient in your support.
3

Enable server events

In assistant settings, enable the transfer-destination-request server event. This sends webhooks to your server when escalations are triggered.

4

Set server URL

Configure your server URL to handle escalation requests (e.g., https://your-app.com/webhook/escalation)


3. Build Escalation Logic Server

Node.js (Express)
Python (FastAPI)
1import express from 'express';
2import crypto from 'crypto';
3
4const app = express();
5app.use(express.json());
6
7// Webhook secret verification
8function verifyWebhookSignature(payload: string, signature: string) {
9 const expectedSignature = crypto
10 .createHmac('sha256', process.env.WEBHOOK_SECRET!)
11 .update(payload)
12 .digest('hex');
13 return crypto.timingSafeEqual(
14 Buffer.from(signature),
15 Buffer.from(expectedSignature)
16 );
17}
18
19// Support escalation logic
20function determineSupportDestination(request: any) {
21 const { functionCall, call, customer } = request;
22 const { issue_category, complexity_level, customer_context, escalation_reason } = functionCall.parameters;
23
24 // Simulate customer tier lookup
25 const customerData = lookupCustomerTier(customer.number);
26
27 // Enterprise customer escalation
28 if (customerData?.tier === 'enterprise' || complexity_level === 'critical') {
29 return {
30 type: "number",
31 number: "+1-555-ENTERPRISE-SUPPORT",
32 message: "Connecting you to our enterprise support specialist.",
33 transferPlan: {
34 mode: "warm-transfer-say-summary",
35 summaryPlan: {
36 enabled: true,
37 messages: [
38 {
39 role: "system",
40 content: "Provide a summary for the enterprise support specialist."
41 },
42 {
43 role: "user",
44 content: `Enterprise customer with ${issue_category} issue. Complexity: ${complexity_level}. Reason: ${escalation_reason}. Context: ${customer_context}`
45 }
46 ]
47 }
48 }
49 };
50 }
51
52 // Advanced technical issues
53 if (issue_category === 'technical' && (complexity_level === 'advanced' || complexity_level === 'intermediate')) {
54 return {
55 type: "number",
56 number: "+1-555-TECH-SPECIALISTS",
57 message: "Transferring you to our technical support specialists.",
58 transferPlan: {
59 mode: "warm-transfer-say-message",
60 message: `Technical ${complexity_level} issue. Customer context: ${customer_context}. Escalation reason: ${escalation_reason}`
61 }
62 };
63 }
64
65 // Billing and account specialists
66 if (issue_category === 'billing' || issue_category === 'account') {
67 return {
68 type: "number",
69 number: "+1-555-BILLING-TEAM",
70 message: "Connecting you with our billing and account specialists.",
71 transferPlan: {
72 mode: "warm-transfer-say-message",
73 message: `${issue_category} issue, complexity ${complexity_level}. Context: ${customer_context}`
74 }
75 };
76 }
77
78 // Product and feature questions
79 if (issue_category === 'product') {
80 return {
81 type: "number",
82 number: "+1-555-PRODUCT-SUPPORT",
83 message: "Transferring you to our product specialists.",
84 transferPlan: {
85 mode: "warm-transfer-say-message",
86 message: `Product ${complexity_level} inquiry. Context: ${customer_context}`
87 }
88 };
89 }
90
91 // Default to general support
92 return {
93 type: "number",
94 number: "+1-555-GENERAL-SUPPORT",
95 message: "Connecting you with our support team.",
96 transferPlan: {
97 mode: "warm-transfer-say-message",
98 message: `General ${issue_category} support needed. Level: ${complexity_level}`
99 }
100 };
101}
102
103// Simulate customer tier lookup
104function lookupCustomerTier(phoneNumber: string) {
105 // In production, integrate with your actual CRM
106 const mockCustomerData = {
107 "+1234567890": { tier: "enterprise", account: "TechCorp Enterprise" },
108 "+0987654321": { tier: "standard", account: "Basic Plan" },
109 "+1111111111": { tier: "premium", account: "Premium Support" }
110 };
111 return mockCustomerData[phoneNumber];
112}
113
114// Support escalation webhook
115app.post('/webhook/escalation', (req, res) => {
116 try {
117 const signature = req.headers['x-vapi-signature'] as string;
118 const payload = JSON.stringify(req.body);
119
120 // Verify webhook signature
121 if (!verifyWebhookSignature(payload, signature)) {
122 return res.status(401).json({ error: 'Invalid signature' });
123 }
124
125 const request = req.body;
126
127 // Only handle transfer destination requests
128 if (request.type !== 'transfer-destination-request') {
129 return res.status(200).json({ received: true });
130 }
131
132 // Determine destination based on escalation context
133 const destination = determineSupportDestination(request);
134
135 res.json({ destination });
136 } catch (error) {
137 console.error('Escalation webhook error:', error);
138 res.status(500).json({
139 error: 'Unable to determine escalation destination. Please try again.'
140 });
141 }
142});
143
144app.listen(3000, () => {
145 console.log('Support escalation server running on port 3000');
146});

4. Test Your Support Escalation System

Dashboard
TypeScript (Testing)
Python (Testing)
1

Create a phone number

  • Navigate to Phone Numbers in your dashboard
  • Click Create Phone Number
  • Assign your support assistant to the number
  • Configure any additional settings
2

Test different escalation scenarios

Call your number and test various scenarios:

  • Basic technical questions (should try to resolve first)
  • Complex billing issues from enterprise customers
  • Advanced technical problems requiring specialists
  • Critical issues requiring immediate escalation
3

Monitor escalation patterns

Check your server logs to see:

  • Escalation requests received
  • Customer tier classifications
  • Destination routing decisions
  • Any errors or routing issues

Advanced Integration Examples

CRM Integration (Salesforce)

1// Example: Salesforce CRM integration for customer tier lookup
2async function lookupCustomerInSalesforce(phoneNumber: string) {
3 const salesforce = new SalesforceAPI({
4 clientId: process.env.SALESFORCE_CLIENT_ID,
5 clientSecret: process.env.SALESFORCE_CLIENT_SECRET,
6 redirectUri: process.env.SALESFORCE_REDIRECT_URI
7 });
8
9 try {
10 const customer = await salesforce.query(`
11 SELECT Id, Account.Type, Support_Tier__c, Case_Count__c, Contract_Level__c
12 FROM Contact
13 WHERE Phone = '${phoneNumber}'
14 `);
15
16 return customer.records[0];
17 } catch (error) {
18 console.error('Salesforce lookup failed:', error);
19 return null;
20 }
21}

Issue Complexity Assessment

1function assessIssueComplexity(issueDescription: string, customerHistory: any) {
2 const complexKeywords = ['api', 'integration', 'custom', 'enterprise', 'migration'];
3 const criticalKeywords = ['down', 'outage', 'critical', 'urgent', 'emergency'];
4
5 const hasComplexKeywords = complexKeywords.some(keyword =>
6 issueDescription.toLowerCase().includes(keyword)
7 );
8
9 const hasCriticalKeywords = criticalKeywords.some(keyword =>
10 issueDescription.toLowerCase().includes(keyword)
11 );
12
13 if (hasCriticalKeywords || customerHistory.previousEscalations > 2) {
14 return 'critical';
15 }
16
17 if (hasComplexKeywords || customerHistory.tier === 'enterprise') {
18 return 'advanced';
19 }
20
21 return 'basic';
22}

Agent Availability Checking

1function getAvailableSpecialist(category: string, complexity: string) {
2 const specialists = getSpecialistsByCategory(category);
3 const qualifiedAgents = specialists.filter(agent =>
4 agent.complexityLevel >= complexity && agent.isAvailable
5 );
6
7 if (qualifiedAgents.length === 0) {
8 return {
9 type: "number",
10 number: "+1-555-QUEUE-CALLBACK",
11 message: "All specialists are busy. You'll be added to our priority queue.",
12 transferPlan: {
13 mode: "warm-transfer-say-message",
14 message: `${category} ${complexity} issue - customer needs callback when specialist available`
15 }
16 };
17 }
18
19 // Return least busy qualified agent
20 const bestAgent = qualifiedAgents.sort(
21 (a, b) => a.activeCallCount - b.activeCallCount
22 )[0];
23
24 return {
25 type: "number",
26 number: bestAgent.phoneNumber,
27 message: `Connecting you to ${bestAgent.name}, our ${category} specialist.`,
28 transferPlan: {
29 mode: "warm-transfer-say-summary",
30 summaryPlan: {
31 enabled: true,
32 messages: [
33 {
34 role: "system",
35 content: `Provide a summary for ${bestAgent.name}`
36 }
37 ]
38 }
39 }
40 };
41}

Error Handling Best Practices

Comprehensive Error Handling

1function handleEscalationError(error: any, context: any) {
2 console.error('Support escalation error:', error);
3
4 // Log escalation details for debugging
5 console.error('Escalation context:', {
6 phoneNumber: context.customer?.number,
7 issueCategory: context.functionCall?.parameters?.issue_category,
8 complexityLevel: context.functionCall?.parameters?.complexity_level,
9 timestamp: new Date().toISOString()
10 });
11
12 // Return fallback destination
13 return {
14 type: "number",
15 number: process.env.FALLBACK_SUPPORT_NUMBER,
16 message: "I'll connect you with our general support team who can help you.",
17 transferPlan: {
18 mode: "warm-transfer-say-message",
19 message: "Escalation routing error - connecting to general support team"
20 }
21 };
22}

Queue Management

1async function getEscalationWithQueueManagement(context: any) {
2 try {
3 const queueStatus = await checkSupportQueueStatus();
4 const destination = await determineEscalationDestination(context);
5
6 // Add queue time estimate if available
7 if (queueStatus.estimatedWaitTime > 5) {
8 destination.message += ` Current wait time is approximately ${queueStatus.estimatedWaitTime} minutes.`;
9 }
10
11 return destination;
12 } catch (error) {
13 return handleEscalationError(error, context);
14 }
15}

Next Steps

You’ve built a sophisticated customer support escalation system using assistants! Consider these enhancements:

  • Property management call routing - Explore the visual workflow approach
  • Call Analysis - Analyze escalation patterns and optimize routing
  • Custom Tools - Build additional tools for advanced support logic
  • Webhooks - Learn more about webhook security and advanced event handling