Detailed Expected Wait Time announcements
Here’s one example of how to implement EWT announcements. I made it for one of my customers who were expecting rather a lot of their brand-new Avaya Call Center. By the time it was deployed they had awfully long waiting times in some queues and despite that, they wanted announcements as detailed as possible. This is how I did it.
The setup was even more complicated by the fact that they wanted the same mechanism to be utilized for all of their queues. While this requirement is not complex per se, the fact that I would have to support all this after deployment made me stop and think. I saw two contradicting requirements there: it should be done as detailed and customized as possible to satisfy the customer and it should be done as generic as possible for ease of maintenance. Since this was CM3/CC3 combo I decided to implement it with Vector Variables and VDN Variables. Please note that I was using 4-digit dial plan and so you may have to adjust these vectors and variables for your system, however I think this will not represent any difficulty.
In this example, the following VDN variables are used. Note that I had to compress some values in one variable because there were a lot of information passed on for processing and not enough VDN variables to hold them all separate. However, I will describe only relevant VDN variables here. Of course it is possible to further “uncompress” these and use separate VDN variable per value but I will leave it as an exercise for the reader.
V2: Dynamic announcements for EWT playback, note that digits are counted right-to-left.
1st-4th digit: extension number for first part of the EWT announcement that goes like “Our manager will answer your call in” or “Our engineer will answer your call in”.
5th-8th digits: extension number for the alternative first part of the EWT announcement that goes like “Our representative will answer your call after”. There is a distinctive difference in pronunciation for these phrases in Russian so I had to separate them in two. For English announcements there may be no difference and this part may be skipped but I decided to keep it as an example for any language that uses more than one form of time announcement.
9th-12th digits: welcome announcement extension number, something like “Hello, you’ve reached this or that company.”
13th-16th digits: extension number for announcement that is to be played immediately after queue-to step, something like “Unfortunately, all our representatives are busy at the moment, please hold”. It is also repeated before EWT announcements.
V3: Queue priorities for calls on a VDN. I don’t know why Avaya didn’t implement this as they did with 1st-3rd skills but I needed this and so had to do it myself.
The following Vector Variables are used:
X: collect type, 4 digits, local. Used to hold first part of the EWT announcement.
Y: collect type, 4 digits, local. Used to hold second part of the EWT announcement.
Z: collect type, 4 digits, local. Contains “welcome” announcement.
W: collect type, 4 digits, local. This variable is set during EWT calculation to approximately half of the Expected Wait Time value.
V: collect type, 4 digits, local. This is set to queue-to announcement, the same from V1.
P: collect type, 1 digit, local. Queue priority for calls on VDN.
Here is the table of announcements used in this example. These are all second part of EWT announcements, they had to be fixed because there are a lot of them and I saw no way to define them in VDN variables.
Extension |
Announcement text (example) |
5950 | less than a minute |
5951 | a minute |
5952 | two minutes |
5953 | three minutes |
5954 | four minutes |
5955 | five minutes |
5956 | six minutes |
5957 | seven minutes |
5958 | eight minutes |
5959 | nine minutes |
5960 | ten minutes |
5961 | twelve minutes |
5962 | fourteen minutes |
5963 | sixteen minutes |
5964 | seventeen minutes |
5965 | eighteen minutes |
5966 | twenty minutes |
5967 | twenty-five minutes |
5968 | thirty minutes |
5969 | thirty-five minutes |
5970 | more than forty minutes |
Next come the vectors. There were several of them, with “goto vector” and “return” steps used heavily throughout.
Vector 1: Unpacking variables
01 set X = none ADD 0 02 set Y = none ADD 0 03 set Z = V2 SEL 12 04 set V = V2 SEL 16 05 set P = V3 SEL 1 06 return
This vector is used for only one purpose: to set variables with their respective default values. While this is not a common practice in Avaya vector processing development, I believe this a healthy habit and do it every time. There can be no unexpected results if one does not rely on built-in defaults.
Vector 2: EWT > 17 minutes
01 goto step 10 if expected-wait for call > 2400 02 set X = V2 SEL 4 03 goto step 13 if expected-wait for call >= 2100 04 goto step 16 if expected-wait for call >= 1800 05 goto step 19 if expected-wait for call >= 1500 06 goto step 22 if expected-wait for call >= 1200 07 goto step 25 if expected-wait for call >= 1080 08 goto step 29 if expected-wait for call >= 1020 09 return 10 set Y = none ADD 5970 11 set W = none ADD 1500 12 return 13 set Y = none ADD 5969 14 set W = none ADD 1125 15 return 16 set Y = none ADD 5968 17 set W = none ADD 975 18 return 19 set Y = none ADD 5967 20 set W = none ADD 825 21 return 22 set Y = none ADD 5966 23 set W = none ADD 675 24 return 25 set X = V2 SEL 8 26 set Y = none ADD 5965 27 set W = none ADD 570 28 return 29 set X = V2 SEL 8 30 set Y = none ADD 5964 31 set W = none ADD 525 32 return
Vector 3: EWT > 7 and < 17 minutes
01 set X = V2 SEL 8 02 goto step 10 if expected-wait for call >= 960 03 goto step 13 if expected-wait for call >= 840 04 goto step 16 if expected-wait for call >= 720 05 goto step 19 if expected-wait for call >= 600 06 goto step 22 if expected-wait for call >= 540 07 goto step 25 if expected-wait for call >= 480 08 goto step 28 if expected-wait for call >= 420 09 return 10 set Y = none ADD 5963 11 set W = none ADD 495 12 return 13 set Y = none ADD 5962 14 set W = none ADD 450 15 return 16 set Y = none ADD 5961 17 set W = none ADD 390 18 return 19 set Y = none ADD 5960 20 set W = none ADD 330 21 return 22 set Y = none ADD 5959 23 set W = none ADD 285 24 return 25 set Y = none ADD 5958 26 set W = none ADD 255 27 return 28 set Y = none ADD 5957 29 set W = none ADD 225 30 return
Vector 4: EWT < 7 minutes
01 set X = V2 SEL 8 02 goto step 10 if expected-wait for call >= 360 03 goto step 13 if expected-wait for call >= 300 04 goto step 16 if expected-wait for call >= 240 05 goto step 19 if expected-wait for call >= 180 06 goto step 22 if expected-wait for call >= 120 07 goto step 25 if expected-wait for call >= 60 08 goto step 28 if expected-wait for call < 60 09 return 10 set Y = none ADD 5956 11 set W = none ADD 195 12 return 13 set Y = none ADD 5955 14 set W = none ADD 165 15 return 16 set Y = none ADD 5954 17 set W = none ADD 135 18 return 19 set Y = none ADD 5953 20 set W = none ADD 105 21 return 22 set Y = none ADD 5952 23 set W = none ADD 75 24 return 25 set Y = none ADD 5951 26 set W = none ADD 90 27 return 28 set X = V2 SEL 4 29 set Y = none ADD 5950 30 set W = none ADD 90 31 return
As you can see, these three vectors are in essence one large subroutine split into three parts due to 32-step limit in CM3. What it does is set variables X, Y and W with their respective values and nothing more so there is no need to elaborate on them.
Vector 5: Play welcome announcement, if there is one
01 goto step 4 if Z = none 02 wait-time 2 secs hearing silence 03 announcement Z 04 return
Note that 2nd step, in my experience the caller is not always connected to announcement immediately and it may happen that there are some delays resulting in first couple seconds not heard. To avoid this, I put a two-second silence before the actual announcement. Your mileage may vary, though.
Vector 6: Queue to 1st skill using VDN-defined priority
01 goto step 5 if P = 1 02 goto step 7 if P = 2 03 goto step 9 if P = 3 04 goto step 11 if P = 4 05 queue-to skill 1st pri l 06 return 07 queue-to skill 1st pri m 08 return 09 queue-to skill 1st pri h 10 return 11 queue-to skill 1st pri t 12 return
This vector is self-explanatory.
Vector 8: Wait time between announcements, part 1
01 goto step 12 if W >= 1500 02 goto step 14 if W >= 1125 03 goto step 16 if W >= 975 04 goto step 18 if W >= 825 05 goto step 20 if W >= 675 06 goto step 22 if W >= 570 07 goto step 24 if W >= 525 08 goto step 26 if W >= 495 09 goto step 28 if W >= 450 10 goto step 30 if W >= 390 11 return 12 wait-time 25 mins hearing music 13 return 14 wait-time 18 mins hearing music 15 return 16 wait-time 975 secs hearing music 17 return 18 wait-time 825 secs hearing music 19 return 20 wait-time 675 secs hearing music 21 return 22 wait-time 570 secs hearing music 23 return 24 wait-time 525 secs hearing music 25 return 26 wait-time 495 secs hearing music 27 return 28 wait-time 495 secs hearing music 29 return 30 wait-time 390 secs hearing music 31 return
Vector 9: Wait time between announcements, part 2
01 goto step 12 if W >= 330 02 goto step 14 if W >= 285 03 goto step 16 if W >= 255 04 goto step 18 if W >= 225 05 goto step 20 if W >= 195 06 goto step 22 if W >= 165 07 goto step 24 if W >= 135 08 goto step 26 if W >= 105 09 goto step 28 if W >= 90 10 goto step 30 if W >= 75 11 return 12 wait-time 330 secs hearing music 13 return 14 wait-time 285 secs hearing music 15 return 16 wait-time 255 secs hearing music 17 return 18 wait-time 225 secs hearing music 19 return 20 wait-time 195 secs hearing music 21 return 22 wait-time 165 secs hearing music 23 return 24 wait-time 135 secs hearing music 25 return 26 wait-time 105 secs hearing music 27 return 28 wait-time 90 secs hearing music 29 return 30 wait-time 75 secs hearing music 31 return
Since there is no way to use vector variable to define the time period for wait-time step, I had to implement this in separate vectors. The purpose of this subroutine is to wait: but wait intelligently. The usual implementation is fixed wait-time period that is repeated along with EWT announcements. This approach has one major drawback though, since, in my opinion, there is no better way to aggravate a customer who has to wait a long time in a queue than is to remind him of his suffering (it ain’t his problem that our Call Center is understaffed, right?) every couple minutes or so. Hence my solution: instead of making a customer rush to his phone for an anticipated agent’s response every time he hears human voice that is really not an agent but autovoice asking to “Please hold”, announce the wait time once instead and then repeat it every half of the time remained, playing soothing music all the while. The time is set in EWT calculation vectors, approximately (high EWT range + low EWT range) / 4, i.e. if EWT lies between 25 and 20 minutes, our W variable is set to (1500+1200)/4=675 seconds. The only exception is made for wait times under two minutes, I see no reason bothering with repeating EWT for such a short wait so we’re setting W to 90 seconds. This is all approximate, as you can see, so these numbers may be changed at will. However, I can say that this scheme proved itself very well.
Also, in case of long wait in a queue, our main vector may exceed the maximum number of steps allowed for call processing – in case of CM3 it’s 999 steps – and we will lose control of what happens next, a vector event will be thrown and vector processing will be terminated. One side effect of my approach is that unnecessary steps are eliminated and no loss of control occurs. In fact, since I have implemented this “intelligent wait” subroutine – it wasn’t there in the first version – I saw no “Maximum vector steps reached” events anymore.
Vector 10: Main vector for 1st skill only
01 goto vector 1 @step 1 if unconditionally 02 goto vector 5 @step 1 if unconditionally 03 wait-time 0 secs hearing music 04 goto vector 6 @step 1 if unconditionally 05 wait-time 5 secs hearing music 06 set X = none ADD none 07 set Y = none ADD none 08 set Z = none ADD 1500 09 goto vector 2 @step 1 if expected-wait for call >= 1020 10 goto vector 3 @step 1 if expected-wait for call >= 420 11 goto vector 4 @step 1 if expected-wait for call < 420 12 goto step 18 if expected-wait for call <= 30 13 announcement V 14 goto step 16 if X = none 15 announcement X 16 goto step 18 if Y = none 17 announcement Y 18 wait-time 0 secs hearing music 19 goto vector 8 @step 1 if W > 360 20 goto vector 9 @step 1 if W < 360 21 goto step 6 if unconditionally 22 busy
Now the main vector. All the main work being split in subroutines, it is relatively simple. First we set the variables we’ll need later, then play welcome announcement if there is one. 3rd step is important: in effect, it turns on the background music. In my view, it is good practice to play music every time except when it should be paused for announcements, so we would want to turn it on as soon as possible after welcome announcement.
Right after the first announcement we’re placing a call in a queue to 1st skill defined on VDN form. 4th step gives us a delay in case the queue is empty and agents are available to pick up the call. It can be shrunk to whatever figure is desired, but in my opinion five seconds is good delay, not too short that the caller can hear a bit of music and not too long that he or she may think that we forgot about them. :)
Steps 6 to 8 reset variables X, Y and Z to default values, this is done to avoid them being reused in a loop.
Steps 9 to 11 call relevant EWT subroutines in order to set X, Y and W variables to their actual values. Note that the expected-wait value is checked for call not skill, this is done with a look for a future need to add 2nd or 3rd skills to this processing. In fact, I had another vector for this processing that utilized 1st and 2nd skills but I decided not to complicate things in this post, since adding alternative skills is done easily.
Step 12 skips all EWT calculation and processing altogether if the expected wait time for this call is less than 30 seconds. No point in bothering with announcements when there may be not enough time to play them.
The rest of the vector is quite simple: we’re playing announcements, first stating that all agents are busy (variable V), then X if it is defined and next Y in the same way, after that we’re calling vectors 8/9 that will wait for amount of seconds defined in variable W and then looping back on step 6.
That’s all. :)
Beautiful, this is well laid out and very informative.
This certainly takes the idea of VAR’s and gives a good insight on how to use them.
Awesome, very well laid out and excellent use of vector variables!
Good to know this.. Can you please explain how the VDN and Vector Variables work.?
Raghunath,
There is very comprehensive documentation provided by Avaya: Call Vectoring and EAS Gude. I’m afraid I can’t add much to that doc without going very deep.
Regards,
Alex.
Thanks for the information. Given this configuration how do you suggest best testing this in order to ensure customer satisfaction?
Hi Nancy,
Unfortunately, Avaya ACD does not have any tools for test automation, so the only way to test vectors is to call their respective VDNs several times and try to simulate all possible scenarios. This particular configuration was heavily tested in production environment and didn’t cause any troubles; however I would suggest implementing it in separate vector/VDN combo first. This way you can call it and make sure it works as expected. When you’re satisfied with it, change incoming call routing from old VDN to new one while call volume is low and use VDN Service Observing feature to make sure live calls are treated the right way. If something goes wrong you can switch incoming call routing back go old VDN and retest.
Regards,
Alex.
Hi dwalin,
I’m not sure if you’re still monitoring this post. it is excellent. thank you.
I do have a question about the use of Local Variables. If these vectors are used in multiple VDN’s even with a local variable, isn’t it possible that Variables you set (eg Y) could be modified by subsequent calls to a new value and therefore play the wrong announcement when the call arrives at the step that says ‘announcement Y’.
My understanding of local variables is that it applies to calls in that vector only. so when the call is hopping in and out of vectors with goto and return steps, won’t the variable then not be persistent to that particular call (Even with a local variable?).
I am hoping I am wrong in my understanding, but wanted to ask the qeustion.
thanks
Mike
Hi Mike,
Thanks for posting this question and sorry for the long wait, somehow I missed it. Unfortunately I cannot really answer your question, it’s been a long time since I have worked with Avaya solutions and my memory of the vector processing detail is getting ever fuzzier.
From the general programming principles you are not wrong and there might be a potential for modifying variable values by subsequent vector steps. CM vector programming reminds me somewhat of software programming in low level assembly languages, where one needs to be very careful not to goto in the wrong place to end up with an incorrect program state. That said, the vectors laid out above were heavily tested in a production environment and I do not recall having any trouble with them, in fact that particular call center has been very low on maintenance ever since the approach above has been implemented.
Also please keep in mind that this approach was worked out around 2006 or so, for the brand new then CM3/CC3. This might not be the best approach for more modern CC solutions, for all I know.