Sponsored Content

DEV Community

Sonam
Sonam

Posted on

Build an AI Call Router That Sends Callers to the Right Team

Traditional IVRs make callers do the routing work.

You call a business, listen to a menu, remember the options, press a number, and hope you picked the right path. That works, but it is not how people naturally ask for help.

Most callers already know what they want:

  • "I need to pay my bill."
  • "I want to upgrade my plan."
  • "I need help with support."

The ai-powered-call-router example turns that sentence into the routing decision.

Code: https://github.com/team-telnyx/telnyx-code-examples/tree/main/ai-powered-call-router

What the app builds

This is a Python Flask app that handles inbound calls with Telnyx Call Control and classifies caller intent with Telnyx AI Inference.

The flow looks like this:

Inbound call
  -> Telnyx sends a Call Control webhook
  -> Flask verifies the webhook
  -> app answers the call
  -> app speaks a greeting
  -> app gathers caller speech
  -> AI classifies intent
  -> app announces the transfer
  -> Call Control transfers the caller
Enter fullscreen mode Exit fullscreen mode

Instead of asking the caller to press buttons, the app asks what they need and routes based on their answer.

The core pieces

The example uses:

  • Telnyx Call Control for answering, speaking, gathering, and transferring calls
  • Telnyx AI Inference for intent classification
  • Telnyx webhook verification for signed inbound events
  • a simple route table for mapping intents to destinations

The source keeps the route table intentionally small:

ROUTE_TABLE = {
    "billing": "+1XXXXXXXXXX",
    "sales": "+1XXXXXXXXXX",
    "support": "+1XXXXXXXXXX",
}
Enter fullscreen mode Exit fullscreen mode

In a real app, those destinations might be queues, agents, contact center flows, or PBX extensions.

Gathering caller speech

Once the inbound call is answered, the app plays a greeting. After the greeting finishes, it starts speech capture using Call Control's AI gather action.

The important detail is that the app waits for the call.speak.ended event before starting the gather. That avoids the greeting and the caller's first response overlapping.

The gather step produces a call.ai_gather.ended event with the caller's utterance.

That text becomes the input to the intent classifier.

Classifying intent with AI

The app sends the caller's transcribed request to Telnyx AI Inference and asks the model to classify it into one of the supported routes.

The default model in the sample is:

meta-llama/Llama-3.3-70B-Instruct
Enter fullscreen mode Exit fullscreen mode

The model does not need to write a long answer. It only needs to return a routing label such as:

billing
sales
support
Enter fullscreen mode Exit fullscreen mode

That keeps the AI part narrow and practical. The LLM is not running the whole call center. It is doing one job: mapping natural language to a route.

Transferring the call

After intent classification, the app speaks a short announcement:

Transferring you to billing. Please hold.
Enter fullscreen mode Exit fullscreen mode

Then it waits for that announcement to finish before calling the transfer action.

That makes the caller experience cleaner. They hear what is happening before the bridge is created.

The example uses a blind transfer: Telnyx dials the destination and connects the original caller once the destination answers.

Webhook verification

Voice automation should not trust random HTTP requests.

The app verifies inbound Telnyx webhooks with Ed25519 signature verification before processing the event:

event = unwrap_with_ed25519(
    request.get_data(),
    request.headers,
    key=TELNYX_PUBLIC_KEY,
)
Enter fullscreen mode Exit fullscreen mode

That means call actions like answer, gather, and transfer only run after the app verifies the webhook came from Telnyx.

Running it locally

Clone the examples repo:

git clone https://github.com/team-telnyx/telnyx-code-examples.git
cd telnyx-code-examples/ai-powered-call-router
Enter fullscreen mode Exit fullscreen mode

Create a virtual environment and install dependencies:

python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
Enter fullscreen mode Exit fullscreen mode

Create your .env file:

cp .env.example .env
Enter fullscreen mode Exit fullscreen mode

Set the required values:

TELNYX_API_KEY=<your_telnyx_api_key>
TELNYX_PUBLIC_KEY=<your_telnyx_public_key>
TELNYX_CONNECTION_ID=<your_call_control_application_id>
AI_MODEL=meta-llama/Llama-3.3-70B-Instruct
PORT=5000
Enter fullscreen mode Exit fullscreen mode

Then run:

python app.py
Enter fullscreen mode Exit fullscreen mode

Expose your local server with a tunnel and point your Telnyx Call Control Application webhook to:

https://<your-tunnel-domain>/webhook
Enter fullscreen mode Exit fullscreen mode

Why I like this pattern

This is a good example of where AI is useful without making the system vague.

The caller still moves through a deterministic telephony flow:

  • answer the call
  • gather speech
  • classify intent
  • look up a destination
  • transfer the call

The model only handles the messy human-language part.

That is the sweet spot for a lot of production AI apps: use the LLM where language is ambiguous, but keep the workflow itself explicit and observable.

Production notes

Before using this with real callers, I would add:

  • retries and fallback routing
  • latency tracking for gather and classification
  • route-level analytics
  • auth around any admin/config endpoints
  • call recording/transcript retention policy
  • escalation rules for uncertain classifications
  • monitoring for failed transfers

But the core idea is simple: callers should be able to say what they need, and your app should route them without forcing them through a rigid menu.

Resources

Top comments (0)