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. :)

8 Comments

  • Colin Haines says:

    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.

  • Donna W says:

    Awesome, very well laid out and excellent use of vector variables!

  • Raghunath R says:

    Good to know this.. Can you please explain how the VDN and Vector Variables work.?

  • Nancy N says:

    Thanks for the information. Given this configuration how do you suggest best testing this in order to ensure customer satisfaction?

    • dwalin says:

      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.

  • Mike says:

    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

    • dwalin says:

      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.

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>