Skip to main content

Smart Routing

Smart routing dynamically directs incoming calls to the most appropriate agent or team based on criteria such as caller attributes, agent skills, geographic location, time of day, or workload distribution. Unlike static routing (where every call follows the same path), smart routing makes real-time decisions to optimize customer experience and operational efficiency.

Smart Routing Strategies​

StrategyRoutes Based OnBest For
Skill-basedAgent skills matching caller needsTechnical support, multilingual teams
Location-basedCaller's geographic locationRegional support, local expertise
Load-balancedAgent workload and availabilityEven call distribution
VIP / PriorityCaller's value or tierHigh-value customer retention
Time-basedCurrent time and schedulesFollow-the-sun support
Data-drivenCRM data, order history, etc.Personalized routing
Round-robinSequential agent assignmentFair distribution

How Smart Routing Works in Exotel​

Smart routing in Exotel is implemented using the Passthru applet, which calls your server mid-flow to make routing decisions:

Incoming Call
|
v
Passthru (POST to your server with caller data)
|
v
Your server evaluates routing rules
|
v
Response: route to Team A / Agent X / Flow Y
|
v
Call flow routes accordingly

Skill-Based Routing​

Route callers to agents with the right skills (e.g., technical expertise, language proficiency, product knowledge).

Setup​

  1. Define skill groups in your system:
Skill GroupSkillsAgents
Tech Support L1Basic troubleshootingAgent 1, 2, 3
Tech Support L2Advanced debugging, APIAgent 4, 5
BillingInvoices, refundsAgent 6, 7
Spanish SupportSpanish languageAgent 8, 9
  1. Add a Passthru applet to your call flow.
  2. Your server determines the required skill based on:
    • IVR selection (caller pressed "1" for technical support)
    • CRM data (caller's open ticket is technical)
    • Caller's language preference
  3. Return the appropriate agent group or number.

Example Server Logic​

def route_call(request):
caller_number = request.POST['From']
ivr_selection = request.POST.get('digits', '')

if ivr_selection == '1':
# Technical support - check ticket severity
ticket = crm.get_open_ticket(caller_number)
if ticket and ticket.severity == 'critical':
return {'agents': TECH_L2_AGENTS}
return {'agents': TECH_L1_AGENTS}

elif ivr_selection == '2':
return {'agents': BILLING_AGENTS}

return {'agents': GENERAL_AGENTS}

Location-Based Routing​

Route callers to agents or teams based on the caller's geographic location.

Using Caller Number Prefix​

Indian phone numbers carry geographic information:

Number PrefixRegionRoute To
+91-80-...BangaloreBangalore support team
+91-22-...MumbaiMumbai support team
+91-11-...DelhiDelhi support team
+91-44-...ChennaiChennai support team
+91-98...Mobile (various)Route by mobile circle

Setup​

  1. Add a Passthru applet to your flow.
  2. Your server extracts the caller's location from their phone number or CRM data.
  3. Return the appropriate regional team.
def route_by_location(request):
caller_number = request.POST['From']

# Determine region from phone number prefix
region = get_region_from_number(caller_number)

routing_map = {
'bangalore': BANGALORE_TEAM,
'mumbai': MUMBAI_TEAM,
'delhi': DELHI_TEAM,
'default': NATIONAL_TEAM
}

agents = routing_map.get(region, routing_map['default'])
return {'agents': agents}
tip

For mobile numbers where the geographic origin is less clear, use your CRM data (shipping address, registration city) instead of the phone number prefix for more accurate location-based routing.

Load-Balanced Routing​

Distribute calls evenly across agents to prevent burnout and ensure fair workload.

Strategies​

StrategyHow It WorksProsCons
Round-robinRotate through agents sequentiallySimple, fairDoes not account for agent busy status
Least callsRoute to agent with fewest calls todayBalances loadMay route to slower agents
Longest idleRoute to agent who has been free the longestQuick answerMay not balance total load
WeightedAssign weights based on agent capacityFlexibleMore complex to configure

Setup (Longest Idle)​

  1. Track agent activity in your database (last call end time, current status).
  2. Use a Passthru applet to query your server.
  3. Return the agent who has been idle the longest.
def route_load_balanced(request):
available_agents = db.get_agents(status='available')

if not available_agents:
return {'action': 'queue'}

# Sort by last call end time (longest idle first)
sorted_agents = sorted(available_agents, key=lambda a: a.last_call_ended)
return {'agents': [sorted_agents[0].phone_number]}

VIP / Priority Routing​

Route high-value customers to senior agents, skip the IVR, or provide priority queue access.

Setup​

  1. Maintain a VIP customer list in your CRM (based on account value, plan tier, etc.).
  2. Use a Passthru applet at the start of your flow.
  3. If the caller is a VIP, skip the IVR and connect directly to their account manager.
Passthru (Check VIP status)
|
├── VIP → Connect (Account Manager / Senior Agent)
|
└── Standard → IVR Menu → Connect (General Team)

VIP Routing Criteria​

CriteriaExample
Account valueCustomers spending over Rs. 1 lakh/month
Plan tierEnterprise or Premium plan holders
RelationshipAccounts with dedicated account managers
Escalation statusCustomers with open escalated tickets
Lifetime valueTop 10% of customers by LTV

Data-Driven Routing​

Route calls based on real-time data from your CRM, helpdesk, or business systems.

Common Data Sources​

Data SourceRouting Decision
Open ticketsRoute to the agent assigned to the open ticket
Last interactionRoute to the last agent who handled this caller (sticky agent)
Order statusRoute order-related calls to the fulfillment team
Payment statusRoute overdue accounts to the collections team
Product ownedRoute to the product-specific support team
Language preferenceRoute to an agent who speaks the caller's language

Implementation​

def route_data_driven(request):
caller_number = request.POST['From']

# Check for open ticket
ticket = helpdesk.get_open_ticket(caller_number)
if ticket:
return {'agents': [ticket.assigned_agent.phone]}

# Check customer tier
customer = crm.get_customer(caller_number)
if customer and customer.tier == 'enterprise':
return {'agents': ENTERPRISE_TEAM}

# Default routing
return {'agents': GENERAL_TEAM}

Combining Multiple Strategies​

For the most effective routing, combine strategies in priority order:

1. Check VIP status → VIP? Route to account manager
2. Check open ticket → Has ticket? Route to assigned agent (sticky)
3. Check IVR selection → Route to skill-based team
4. Within team → Use load-balanced (longest idle) distribution
5. All busy → Queue with priority based on customer tier

Configuration via Passthru​

The Passthru applet is the primary tool for implementing smart routing in Exotel:

Request (from Exotel to your server)​

POST https://your-app.com/smart-route
Content-Type: application/x-www-form-urlencoded

CallSid=<call_sid>&From=<caller_number>&To=<exophone>&Direction=incoming&digits=<ivr_input>

Response (from your server to Exotel)​

Your server returns routing instructions that the flow uses to determine the next step. The exact response format depends on your flow design and Passthru configuration.

Performance Considerations​

FactorImpactRecommendation
Server response timeAdds latency to call routingKeep under 2 seconds
Database queriesSlow queries delay routingUse indexes and caching
Fallback handlingServer down = no routingAlways configure a fallback route
CachingReduce repeated lookupsCache customer data for 5-10 minutes
warning

Your smart routing server must respond within 2-3 seconds. If the Passthru applet times out waiting for your server, the call will follow the timeout path. Always configure a timeout fallback that routes to a general agent group.

Best Practices​

  • Start simple, iterate -- Begin with one routing strategy and add complexity based on data and feedback.
  • Always have a fallback -- If your routing server is unreachable, route to a general queue.
  • Monitor routing outcomes -- Track which strategy was applied and the result (connected, dropped, transferred) to measure effectiveness.
  • Keep server response fast -- Optimize database queries and use caching to keep Passthru response times under 2 seconds.
  • Test edge cases -- What happens for unknown callers? New numbers? Numbers not in your CRM? Define default behavior for every scenario.
  • Log routing decisions -- Record why each call was routed the way it was for debugging and optimization.

Troubleshooting​

IssueCauseSolution
All calls go to default teamPassthru server returning errorsCheck server logs and response format
Routing too slowServer response time highOptimize queries, add caching
VIP not getting priorityCRM lookup failingVerify CRM integration and data
Agent overloadedLoad balancing not workingCheck agent status tracking
Wrong team connectedRouting logic errorDebug server-side routing code