Omnichannel for Customer Service – IVR BOT Skills Based Routing

In this blog post I hope to describe how you can setup an IVR BOT for Microsoft’s Omnichannel for Customer Service voice channel. And how the BOT can question the customer on their needs then trigger skills-based routing to ensure the best agent answers the query.

I may also mention a few “tricks / tips” I have applied in my IVR BOT setup.

There are several parts to this process …

  • IVR BOT Setup
    • Create a custom question type (Entity)
    • Add a “How can I help you” topic
  • Omnichannel Setup
    • Define Skills and add to users
    • Add a context variable to my workstream
    • Update work distribution logic
    • Setup my work classification and routing logic


I have previously blogged about the basic concepts of creating an IVR BOT. You can read that blog here.

In this post I am going to concentrate on now I tailored my BOT to ask the customer what type of query they have. (I will then route to agents skilled in answering that type of question.)

I plan to offer customers a choice of speaking to someone in “sales” or “service”. Obviously, this is just an example you could adapt this concept for any combination of call types and skills.

Create a custom question type (Entity)

When a customer interacts with my IVR I wanted them to be able to say sales or press 1. Or press 2 for service etc.

In the “Entities” option on my BOT I have used the “+New entity” option and created a custom entity. Doing this will allow me to define exactly what options I require.

When we look at my test entity you can see that I have added Sales and Service as possible options. You can also see that I have added a synonym of “1” for “Sales” and “2” for “Service”. This is all I needed to enable the ability for the user to press 1 or say sales etc.

Add a “How can I help you” topic

Next, I created a new topic. You don’t need to follow my exact approach here! The key thing is I am asking a question and storing the result in a variable. That we will later use in our skills classification logic.

My topic is below. It has three actions. The first is to ask a question, next I message the customer just to confirm the BOT has listened to the customer. And finally, I transfer the call to the customer.

Please keep in mind that this is a very simple example. In a production IVR you will probably have many more options and possibly additional complexity you’ll want to build within the BOT. But the overall concept would remain the same.

A closer look at my question will help you understand how I have configured that. Below you can see that under “Identify” I have selected my custom entity. Next I have given the question result a name. “Var_IVRTopic”. You could use any name but make a note of it! (As we will use this information later within our workstream.)

Importantly I have set the usage to be Bot and available to external sources. Doing this will automatically prefix my variable with “bot.”.

The final part of my IVR BOT logic was to trigger the topic I’d just created. In my example I simply added a redirect at the end of my greeting topic to trigger the “How can I help you” topic I’d just created.

It would have been perfectly possible for me to put all this logic into my greeting topic. But I like to break my topic down, so I create small manageable chunks. (Instead of having one massive greeting topic!)

In the above greeting topic you might notice that I have used an uninterruptable message. I have found these useful for any messaging you are keen to ensure the customer always listens to. Such as your opening greeting. This might be important as customers can interrupt the flow by saying or clicking “1” before the greeting has completed.

Don’t forget to publish you BOT after making your changes!

Omnichannel Setup

Now I am ready to configure my workstream in Omnichannel. The logic being that I need to take the information entered in the BOT into the context of my workstream. And once done I can use that in skills-based routing.

Define Skills and add to users

Before we configure our workstream we’ll want to create some skills and assign them to users. You will find the skills option in the user attributes area of the Omnichannel admin center

Below you can see that for my simple test I have created two skills, one called “SALES” and one called “SERVICE”.

Next, we need to add one or more skills to each agent. For this we open the users option and located our agent.

On the Omnichannel tab you will find a sub-grid that is headed “Skills configuration”. You may already have a bookable resource record here. If not you will need to create one. I tend to simply give my bookable resource the same name as my user but you could name this record in any way you like.

On my bookable resource, in the Omnichannel tab I can add as many skills as I like. You can also optionally assign a rating or proficiency value. I haven’t done this but sometimes it might be useful to grade your agents level of proficiency with each skill. As then we can look for the most proficient agent first in the assignment logic.

Add a context variable to my workstream

With my skills created and assigned to my agents I can now turn my attention to the setup of my workstream.

In my IVR BOT I captured the customers required topic and stored it in a variable called “Var_IVRTopic”. I now need to make that variable available to my workstream.

Below you can see that I have opened my workstream.

Towards the bottom of the workstream screen you will find an “advanced settings” option. Opening that will reveal a “context variables” section. I have used the edit option and added my variable. I think it might be important to ensure the case of the variable is the same as you used in your bot. Although notice that I didn’t need to include the “bot.” in the name of my variable.

Variables can be of type text or number. Mine will hold a word and is therefore (obviously) a text variable.

Update work distribution logic

At this point you may want to check and alter your work distribution logic. Still on my workstream I checked that my default skill matching algorithm was closest match. (If yours isn’t set as you required click “See more” and edit as required.)

The possible options are;

  • None – This is the default option. And if we aren’t using skills is fine. But if you are using skills you will want to select one of the two following options.
  • Exact Match – As the name suggests the conversation will only be routed to agents who have the exact required skill and proficiency rating.
  • Closest Match – Here we will look for agents with an exact match. If none are available agents with the required skill and a lower proficiency would be considered next. Followed by any available agent. I personally often use closest match rather than exact match. As the odds of the call being assigned to an agent are obviously higher.

Setup my work classification and routing logic

We can now create one or more rulesets to classify what skill is required for this conversation. Again, I will stress that this is a very simple example! We could get clever with work classification …. For example, I am using a simple logical condition on a variable that can only hold two values. But we could use machine learning to “read” a longer text string and try and “guess” the skills an agent would require.

Tip: I have found that any successful machine learning model needs more training data than you might think! Hence, I tend to recommend starting off with a logical model and only later consider using a more complex machine learning approach. (When the system has been running long enough to create a volume of data that can be used to train a model from.)

Below you can see that I have created a work classification ruleset and then whilst creating the ruleset I opted for the “logical rules” option.

If I open my classification ruleset you can see that I have two rules. In my example these just link to the “SALES” or “SERVICE” skills based on the topic passed in from my IVR BOT.

As an example, I have opened my sales classification below. You can see that I have a condition that looked for a value of “Sales” in my topic variable. And then assigns a skill of SALES to this conversation.

Tip: I haven’t used a proficiency rating in this example. But I could also use the classification logic to assign a required level of proficiency.

You might notice that my condition above is using my variable from the context. A little explanation on how I achieved that might help! Below you can see that as I add my condition I have used the “Add related entity” option. As we could have multiple context variables related to this conversation.

Next, under the “One to Many” heading I selected the “Context item value” option.

Finally, a drop down will allow me to pick whichever context variable I’d like to based my condition on.

Now my conversation will be classified as requiring a particular skill. The routing logic will pass this conversation to a queue containing multiple agents. Then the assignment logic will look for the best agent to handle this call. In my example an available agent with the skill of Sales or Service.

It maybe common to simply route all the conversations on one workstream to one queue. But if required we could have multiple queues. Maybe one containing all the sales agents and one with all the service agents.

As an example, I have shown how in the ruleset on my routing logic I can additionally add a condition using the skill.


With my logic completed I called my phone number, my IVR BOT asked if I had a Sales or Service query, I entered “1” (for sales) and was immediately connected to a sales agent.

After the call I opened my conversation record to double check the logic has worked as expected. Below you can see the transcript from my IVR bot and also that the conversation has been tagged with the SALES skill.

I was lucky because my routing worked as expected. But with a more complex scenario I would expect it might take you a few attempts to get everything setup correctly. In that situation you might find the “Diagnostics” option in the “Omnichannel admin center” useful. Once you turn on diagnostics a record is created for each conversation. You can then see which queue and agent were assigned to each call. Plus we can open the diagnostic records to see more information about the classification and routing logic applied.

This has been a very simple example meaning significantly more complex logic could be built into skills-based routing. In my example I have just gone for a simple question with two fixed options. Hopefully you can appreciate that in your implementation you could get much more creative with the questions the BOT will ask and how we decide which skills agents require. Enjoy!

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s