One of the most complex activities for Teams admins is creating call queues and auto attendants. You don't create them every day, but when you do, you might need to create a lot of them at once.
In this tutorial, you'll learn how to automate all the required steps. You'll create an auto attendant and associate it with a call queue for a full-fledged voice application.
Tip
This article is a part of the series about managing Teams call queues and auto attendants with PowerShell.
Part 1 - Automating Call Queue and Auto Attendant onboarding (this article)
Part 2 - Managing Auto Attendant general settings with PowerShell
To go through the steps in this blog post, you need the following:
You'll create an auto attendant and configure it to redirect to the call queue.
An auto attendant in conjunction with a call queue ensures the best flexibility. It is also easy to extend. The diagram of what you're going to create would be:
For simplicity, you'll not assign the number to your application yet.
Ok then, enough talking. Let's start creating. Before you start, connect to Microsoft Teams from your PowerShell:
Connect-MicrosoftTeams
You can now specify variables to use later:
# Your config
$cqName = 'RobTestQueue2'
$resourceAccountDomain = 'yourdomain.onmicrosoft.com'
Before working on the auto attendant, you can create a call queue. In that configuration, you'll be able to configure forward to the call queue immediately.
I use splatting for all cmdlets below. If you want to learn more about that term, take a look at PowerShell Splatting: What is it and How Does it Work?.
You might wonder why use splatting when you provide only one or two parameters to the cmdlet. You're right that it seems a bit unnecessary. The purpose of it here is to make the code easily expandable when you add more features.
# Create resource account of call queue type
$cqRaParams = @{
UserPrincipalName = "RA_CQ_$cqName@$resourceAccountDomain"
# ID taken from cmdlet documentation
ApplicationId = '11cd3e2e-fccb-42ad-ad00-878b93575e07'
DisplayName = "RA_CQ_$cqName"
}
$newCqRa = New-CsOnlineApplicationInstance @cqRaParams
# Create call queue
$newCqParams = @{
Name = "CQ_$($cqName)"
UseDefaultMusicOnHold = $true
}
$newCq = New-CsCallQueue @newCqParams
# Associate resource account with call queue
$newCqAppInstanceParams = @{
# Requires array of strings
# Use array sub-expression operator
Identities = @($newCqRa.ObjectId)
ConfigurationId = $newCq.Identity
ConfigurationType = 'CallQueue'
ErrorAction = 'Stop'
}
$associationRes = New-CsOnlineApplicationInstanceAssociation @newCqAppInstanceParams
You finished the first part - congrats! The next one is a little bit more complicated. Fear not, though - you'll get there smoothly.
Your call queue is up and running. Let's work on the auto attendant.
Setting a resource account is very similar to the one you created for a call queue. The only difference is the application ID you'll use:
$newAaRaParams = @{
UserPrincipalName = "RA_AA_$($cqName)@$resourceAccountDomain"
# ID taken from cmdlet documentation
ApplicationId = 'ce933385-9390-45d1-9512-c8d228074e07'
DisplayName = "RA_AA_$($cqName)"
}
$newAaRa = New-CsOnlineApplicationInstance @newAaRaParams
To create auto attendant, you use New-CsAutoAttendant
. It requires 4 parameters:
For finding mandatory parameters, you'll have to check the documentation. Look for names not surrounded with square brackets
[ ... ]
. Take a look at the example:
The first three of the parameters listed above are strings. They can be defined inline. DefaultCallFlow can be created using New-CsAutoAttendantCallFlow
, which takes name and menu.
The cmdlet to create the menu is New-CsAutoAttendantMenu
. The only required parameter for it is Name.
However, to configure automatic forward to the call queue, you'll have to configure some objects:
New-CsAutoAttendantCallableEntity
New-CsAutoAttendantMenuOption
So many cmdlets! Let's put them together to your script, shall we?
# Options
$aaLanguage = 'en-GB'
$aaTimezone = 'GMT Standard Time'
# Callable entity
$callableEntityParams = @{
# Point to resource account, not call queue
Identity = $newCqRa.ObjectId
Type = 'ApplicationEndpoint'
}
$targetCqEntity = New-CsAutoAttendantCallableEntity @callableEntityParams
# Menu option
$menuOptionParams = @{
Action = 'TransferCallToTarget'
DtmfResponse = 'Automatic'
CallTarget = $targetCqEntity
}
$menuOptionZero = New-CsAutoAttendantMenuOption @menuOptionParams
# Finally, the menu
$menuParams = @{
Name = "$aaName Default Menu"
# Accepts list, so use array sub-expression operator
MenuOptions = @($menuOptionZero)
}
$menu = New-CsAutoAttendantMenu @menuParams
# And the call flow
$defaultCallFlowParams = @{
Name = "$aaName Default Call Flow"
Menu = $menu
}
$defaultCallFlow = New-CsAutoAttendantCallFlow @defaultCallFlowParams
# You have all the objects
# Now, you can create an auto attendant
$autoAttendantParams = @{
Name = "AA_$cqName"
LanguageId = $aaLanguage
TimeZoneId = $aaTimezone
DefaultCallFlow = $defaultCallFlow
ErrorAction = 'Stop'
}
$newAA = New-CsAutoAttendant @autoAttendantParams
# Last but not least, the association
$aaAssociationParams = @{
# As the previous association, array expected
Identities = @($newAARA.ObjectId)
ConfigurationId = $newAA.Identity
ConfigurationType = 'AutoAttendant'
ErrorAction = 'Stop'
}
$associationRes = New-CsOnlineApplicationInstanceAssociation @aaAssociationParams
To make sure everything went smoothly, let's verify that all the objects are created and configured.
# Check if resource accounts exist
Get-CsOnlineApplicationInstance -Identities @($newAaRa.ObjectId, $newCqRa.ObjectId)
You should receive something along these lines (IDs redacted):
RunspaceId : 00000000-0000-0000-0000-000000000000
ObjectId : 00000000-0000-0000-0000-000000000000
TenantId : 00000000-0000-0000-0000-000000000000
UserPrincipalName : RA_CQ_RobTestQueue@yourdomain.onmicrosoft.com
ApplicationId : 00000000-0000-0000-0000-000000000000
DisplayName : RA_CQ_RobTestQueue
PhoneNumber :
RunspaceId : 00000000-0000-0000-0000-000000000000
ObjectId : 00000000-0000-0000-0000-000000000000
TenantId : 00000000-0000-0000-0000-000000000000
UserPrincipalName : RA_AA_RobTestQueue@yourdomain.onmicrosoft.com
ApplicationId : 00000000-0000-0000-0000-000000000000
DisplayName : RA_AA_RobTestQueue
PhoneNumber :
Then check for call queue:
Get-CsCallQueue -Identity $newCq.Identity
Which returns:
WARNING: No Distribution Lists or Users added to callqueue. There will be no agents to call.
TenantId : 00000000-0000-0000-0000-000000000000
Name : CQ_RobTestQueue
Identity : 00000000-0000-0000-0000-000000000000
RoutingMethod : Attendant
DistributionLists :
Users :
DistributionListsLastExpanded :
Agents :
AllowOptOut : False
ConferenceMode : False
PresenceBasedRouting : False
AgentsCapped : False
AgentsInSyncWithDistributionLists : True
AgentAlertTime : 30
LanguageId :
OverflowThreshold : 50
OverflowAction : DisconnectWithBusy
OverflowActionTarget :
OverflowSharedVoicemailTextToSpeechPrompt :
OverflowSharedVoicemailAudioFilePrompt :
OverflowSharedVoicemailAudioFilePromptFileName :
EnableOverflowSharedVoicemailTranscription : False
TimeoutThreshold : 1200
TimeoutAction : Disconnect
TimeoutActionTarget :
TimeoutSharedVoicemailTextToSpeechPrompt :
TimeoutSharedVoicemailAudioFilePrompt :
TimeoutSharedVoicemailAudioFilePromptFileName :
EnableTimeoutSharedVoicemailTranscription : False
WelcomeMusicFileName :
UseDefaultMusicOnHold : True
MusicOnHoldFileName :
Statistics : Current queue size = 0
ApplicationInstances : 00000000-0000-0000-0000-000000000000
And then for auto attendant:
Get-CsAutoAttendant -Identity $newAA.Identity
Which returns:
Identity : 00000000-0000-0000-0000-000000000000
TenantId : 00000000-0000-0000-0000-000000000000
Name : AA_RobTestQueue
LanguageId : en-GB
VoiceId : Female
DefaultCallFlow : AA_RobTestQueue Default Call Flow
Operator :
TimeZoneId : GMT Standard Time
VoiceResponseEnabled : False
CallFlows :
Schedules :
CallHandlingAssociations :
Status :
DialByNameResourceId :
DirectoryLookupScope :
ApplicationInstances : {00000000-0000-0000-0000-000000000000}
GreetingsSettingAuthorizedUsers : {}
You now have a working application - take a moment to do your happy dance 🎉. Once done, you can think about adding more functionalities:
Tip
Not sure where to start? Check my next article from this series: Part 2 - Managing Auto Attendant general settings with PowerShell
Creating call queues and auto attendants is a time-consuming process. As usual, PowerShell might help you to save some time. Use the skeleton from this article and adapt it to your needs. Happy coding!