I’m half way through a 3 phase project that started with a Lync Server 2010 to 2013 migration, currently deploying Enterprise Voice, and the final phase will be to deploy a contact centre with PCI compliant call recording.
My client is understandably excited about ditching their Avaya IP Office PBX, but before we start the ACD phase they were very keen to see how they could migrate some of their old hunt groups and call flows to native Response Groups. One in particular, ended up needing 3 Workflows, 6 Queues, 2 Groups, and a new Lync user to act as a ‘place-holder’. I thought it was interesting enough to write about. I’ll do my best to explain it in words first, but will probably end up drawing a Visio diagram at the end anyway, so here we go.
“A caller dials up, if it’s in-hours, to play a welcome message asking the caller to wait, then pass the call to a group of 6 agents in a pre-defined order, for 10 seconds each. If it’s out-of-hours, to play a message to ask the caller to choose an ‘on-call’ agent (by pressing 1,2,3 or 4), each to call that specific person’s mobile phone number.”
On the face of it, it sounds fairly straight forward, right? Lets start from the top and see what we can actually do to achieve this.
Before we go on any further, I would like to point out that I’m certainly NOT recommending the following to my client, and at no point suggested actually using the resulting ‘plate of spaghetti’ in production. Perhaps I should have just said “No, wait for your ACD”, but, working on the clear understanding that this is purely to feed my clients curiosity (and my own), where’s the harm?
Firstly, “Can a Response Group Workflow play a different message in-hours vs out-of-hours?”. Simply put, No. The options available to us are a ‘Welcome Message’ which gets played as soon as the call is picked up, no matter what, and an “Out-of-Hours Message”. Hmm, that doesn’t quite work for us. Here comes the first workaround… A “Hunt Group” Workflow which evaluates the business hours without any announcements, then elects to forward the call out-of-hours to a SIP Address of another Workflow (which will play a “please select from the following agents” message and do the IVR part – I’ll come back to this later) so that’s that bit sorted for now.
Before we get ahead of ourselves, for our In-Hours requirement on this first Workflow, we would need to play a message after we’ve established it’s In-Hours, and then forward to a queue, so lets ask “Can a Response Group Workflow forward to another Workflow if ‘successful’?”. The answer again, is no. The only outcome of a ‘successful’ Workflow is to select a Queue, but this does gives us the option to use (and abuse) the ‘overflow’ feature, and specify a SIP Address of yet another Workflow.
The Overflow feature of a Queue is designed to take the load off your agents, if there are 5 agents, and 50 people waiting in the queue, you may decide that enough is enough and all new callers are told to hang up and try again later, or given the option to leave a message. We can use this to our advantage and basically tell the Queue that the maximum number of calls in the queue is zero, so it will always overflow. For this to actually work the Queue needs a Group associated with it, and an agent in the group, otherwise the call with simply end, and you’ll receive the following error in the Event Log of the server.
Once in a while Microsoft get it right, and you get an error message you can understand, and is exactly spot on. But I don’t want a specify a Group, nor a User, as this should overflow instantly to the specified SIP Address. This is where the ‘NullGroup’ and ‘NullUser’ come in. After creating a Lync-Enabled User (that will never receive a call) in a new Group, and associating that with the Queue, it works.
This next bit is simple, create a Workflow with a Welcome Message and specify a Queue with an Agent Group associated, configured with Participant Policy set to Informal, Alert Time set to 10 seconds, and Routing Method set to Serial.
Lets put together what we have so far in-front of, and behind the scenes…
- Caller’s View “In-Hours” – A caller dials a number, they hear a message asking them to wait, then a ringing tone, and an agent answers the phone.
- Lync’s View “In-Hours” – A caller dials a number and gets a Workflow that checks if the call is in-hours, then calls a queue, overflows, and forwards to SIP Address of another Workflow which plays a message, calls a queue, and the agents phones will ring, and an agent picks up the phone.
Coming back to the IVR for Out-Of-Hours, the next question is “Can a Response Group forward to a telephone number”. Yes, if a result of being outside business hours, or a holiday, but not as a result of an IVR option. So, unfortunately, the answer is once again, no. But we can use the Overflow feature of another Queue to forward to a Telephone Number. With a few more bits of Lego, and sticky tape we have our finished call flow.
- Caller’s View “Out-Of-Hours” – A caller dials a number, they hear a message asking them to select an ‘on-call’ agent by pressing 1,2,3, or 4, then a ringing tone, and an agent answers the phone.
- Lync’s View “Out-Of-Hours” – A caller dials a number and gets a Workflow that checks if the call is out-of-hours, forwards the call to a SIP Address of another Workflow, which plays a message asking them to select an ‘on-call’ agent, and calls a Queue, which overflows, and forwards the call to a telephone number, it rings, and an agent answers the phone.
I told you it was difficult to explain, so here’s the Visio I threatened you with. (Blue = Workflow, Green = Queue, White = Group). Click to enlarge.
The only major drawback is when calling this from a Lync Client, it pops up a new call window each time it forwards through each Workflow, so it looks a bit like the end of the Solitaire card game, which also introduces a small but unwanted delay and confusion as the call initiates.
For all you PowerShell fans out there, life doesn’t get any easier. The following code is not complete, but you should get the idea of what’s going on, and what it takes to rustle up something a bit more than a standard response group.
$parent = "service:ApplicationServer:lyncpool.domain.local"
$nullGroup = New-CsRgsAgentGroup -Parent $parent -Name "NullGroup" -ParticipationPolicy Informal -AgentAlertTime 20 -RoutingMethod Serial -AgentsByUri ("sip:firstname.lastname@example.org")
$promptXfer = New-CsRgsPrompt -TextToSpeechPrompt "Putting you through, please wait"
$action1 = New-CsRgsCallAction -Prompt $prompt1 -Action TransferToPstn -Uri "sip:+email@example.com"
$queue1 = New-CsRgsQueue -Parent $parent -Name "AgentSmith-to-Mobile" -OverflowThreshold 0 -OverflowAction $action1 -AgentGroupIDList ($nullGroup.Identity)
$queueAction1 = New-CsRgsCallAction -Action TransferToQueue -QueueID $queue1.Identity
$answer1 = New-CsRgsAnswer -Action $queueAction1 -DtmfResponse 1 -VoiceResponseList "Mr Smith"
# And the same for options 2,3, and 4
$promptOOHIVR = New-CsRgsPrompt -TextToSpeechPrompt "Sorry the Service Desk is closed. Please press 1 for Smith, press 2 for Jones, press 3 for Johnson, or press 4 for Peterson"
$questionOOH = New-CsRgsQuestion -Name "Service Desk - OOH Question" -Prompt $promptOOHIVR -AnswerList $answer1, $answer2, $answer3, $answer4
$actionOOHQuestion = New-CsRgsCallAction -Action TransferToQuestion -Question $questionOOH
$GoToOOH = New-CsRgsCallAction -Action TransferToUri -Uri "sip:firstname.lastname@example.org"
$actionGoToIH = New-CsRgsCallAction -Action TransferToUri -Uri "sip:email@example.com"
$queueGoToIH = New-CsRgsQueue -Parent $parent -Name "Service Desk - IH Queue" -OverflowThreshold 0 -OverflowAction $actionGoToIH -OverflowCandidate NewestCall -AgentGroupIDList $nullGroup.Identity
$GotoIH = New-CsRgsCallAction -Action TransferToQueue -QueueID $queueGoToIH.Identity
$promptIH = New-CsRgsPrompt -TextToSpeechPrompt "Welcome to the Service Desk, please wait and you will be connected"
$groupIH = New-CsRgsAgentGroup -Parent $parent -Name "Service Desk - InHours Group" -ParticipationPolicy Formal -AgentAlertTime 10 -RoutingMethod Serial -AgentsByUri ("sip:firstname.lastname@example.org","sip:email@example.com","sip:firstname.lastname@example.org","sip:email@example.com","sip:firstname.lastname@example.org")
$queueIH = New-CsRgsQueue -Parent $parent -Name "Service Desk - InHours Queue" -AgentGroupIDList $groupIH.Identity
$actionIH = New-CsRgsCallAction -Prompt $promptIH -Action TransferToQueue -QueueID $queueIH.Identity
$hoursWeekday = New-CsRgsTimeRange -Name "Working Day" -OpenTime "08:30" -CloseTime "17:30"
$workingWeek = New-CsRgsHoursOfBusiness -Parent $parent -Name "Service Desk Hours" -MondayHours1 $hoursWeekday -TuesdayHours1 $hoursWeekday -WednesdayHours1 $hoursWeekday -ThursdayHours1 $hoursWeekday -FridayHours1 $hoursWeekday
$serviceDesk = New-CsRgsWorkflow -Parent $parent -Name "Service Desk" -PrimaryUri "sip:email@example.com" -DisplayNumber "0207 123 1234" -LineUri "tel:+442071231234;ext=1234" -Active $true -EnabledForFederation $true -BusinessHoursID $workingWeek.Identity -NonBusinessHoursAction $GotoOOH -DefaultAction $GoToIH -Language "en-GB"
$serviceDeskOOH = New-CsRgsWorkflow -Parent $parent -Name "Service Desk - Out Of Hours" -PrimaryUri "sip:firstname.lastname@example.org" -Active $true -EnabledForFederation $true -DefaultAction $actionOOHQuestion -Language "en-GB"
$serviceDeskIH = New-CsRgsWorkflow -Parent $parent -Name "Service Desk - In Hours" -PrimaryUri "sip:email@example.com" -Active $true -EnabledForFederation $true -DefaultAction $actionIH -Language "en-GB"
Don’t forget to apply a voice policy to the Workflows as they’ll need to be able to dial out. (And a Dial Plan if there are no rules in your Global).
Conclusion – How far should you bend and twist Lync Response Groups
Although when calling from PSTN, the experience is smooth and quick, unlike the Lync Client, that doesn’t mean you should entertain taking it this far with the built-in Response Group functionality. It’s difficult for any Helpdesk, or Lync User Admin to understand, as this leaves behind a messy and confusing bunch of strange Workflows, Queues, and Groups, and not to mention a funny taste in the mouth.
Microsoft has done a great job of providing ‘some’ functionality that covers most simple cases (Hunt Group Workflow) and even gone as far as to allow a 2-Level, 4-Option IVR with text-to-speech, and speech recognition (Interactive Workflow), that’s not too shabby at all!
But all is not lost, in the guise of UCMA, Lync has embraced 3rd party extensibility, and figuratively thrown the doors wide open to developers, enabling them to create advanced call handling software with very flexible rules, allowing you to create complex call flows for a wide variety of business needs.
If this particular call flow remains a requirement for my client, I will post a follow-up article explaining how it was achieved using their selected ACD software.
Don’t have nightmares…