Create a simple Teams creation workflow using Power Automate

Why do I need to build a Teams creation process using Power Automate? What’s wrong with the standard Team creation process?

When you create Microsoft Teams out of the box, there are only limited governance capabilities. For example:

  • Limited Teams naming convention
  • Duplicate Teams names
  • Only one owner required
  • No justification or approval process

This blog describes how to create Teams using Power Automate plus add governance steps to the workflow to include:

  • Apply a tailored Teams naming convention
  • Add an approval step
  • Stop duplicate Team names
  • Add multiple owners
  • Add sensitivity label to allow or block guests and external sharing
  • Capture additional metadata such as justification, Team type, or Team duration

Read on for my step-by-step guide on creating a Power Automate Flow for your Teams creation process.

Part A – Teams creation using Power Automate – Create your data entry Form and List

Microsoft Form

I create a Microsoft Form for the data capture. The Form captures standard information for a new Team and additional metadata to provide more granularity.

For example:

  • Add a sensitivity label to control whether guests and allow external sharing is permitted.
  • Team type. Capture information about the purpose of the Team In my example, I ask whether the Team is operational or project-based so I can use this information to add a prefix to the Team name.
  • Team duration – the length of time the owner needs the Team.
  • An additional owner. I recommend having multiple Team owners who can cover for absences.
  • Justification – provide further information to the approvers as to why the Team is needed

SharePoint List

I use a SharePoint List to store the information entered onto the Form, so there is a record of the requests.

Create columns to map onto the data captured on the forms.

  • Title – This will store the requested Team name
  • Description – multiple lines of text column
  • Privacy – a single line of text column
  • Sensitivity label – a single line of text column
  • Team type – a single line of text column
  • Duration – Date column
  • Second owner – Person or group column
  • Justification – multiple lines of text column

Create columns to store information about the requester, the approval outcome and the final Team

  • Requestor – Person or group column
  • Requestor country – a single line of text column
  • Approver – Person or group column
  • Approval status – a single line of text column
  • Approval date – Date column
  • Approval comments- multiple lines of text column
  • Team ID – a single line of text column

Create a calculated column to derive the Team naming standard

I want to add a prefix to the Team name that shows whether it is an operational or project-based team. So I create a calculated column to convert the Team type in the Form to a shorter value to use as the prefix in the Team name.

Example.

  • Team type code  = calculated column – IF([Team Type]=”Project” ,”PROJ”,”OP”)

Create a calculated column for creating the Final Team name. This column will add the Team Type as a prefix and Requestor country as a suffix to the Team name.

  • Final Team name=[Team Type code] &”-“&Title&”-“&[Requestor Country]

Example

  • Team Type = Project
  • Team Type code = PROJ
  • Requestor country = UK
  • Team Name = Marketing
  • Final Team name = PROJ-Marketing-UK

Part B – Teams creation using Power Automate – Create your Power Automate Flow

The Power Automate flow will cover:

Trigger = When a Form is submitted

Actions =

  • Apply a Team naming convention
  • Stop duplicate Teams
  • Add an approval step
  • Create the Team
  • Add sensitivity label to allow or block guests and external sharing
  • Add multiple owners

Start the Flow when a Form is submitted

Every time a Form is submitted, read the information from the Form.

Trigger = When a new request is submitted.

  • Form id = select the name of the Form you created

To access the information in the Form.

Action = Get response details

  • Response id = dynamic content Response id

Get the user details

Get flow owner user details

Get details of the flow owner. The system automatically adds the flow owner as the Team owner. Note. As part of the Flow, the owner is removed from the Team if they are not the Requestor or the second owner.

Action = Get my profile (V2)

Get the requestor user details

Get details of the person who submitted the Form (the Requestor). Note. A later step will add the Requestor as a Team owner.

Action = Get user profile (V2)

  • UPN = Responders email from Form

Get the second owner user details

Get details of the second owner. Note. A later step will add the Second owner as a Team owner.

Action = Get user profile (V2)

  • UPN = Second owner from Form

Initialize variables

Add four Variables actions to store information needed in the Flow.

Create a variable to store the Team id

I use the members of a Team as the Approvers. I do not recommend hard-coding email addresses in the Flow or having a single approver.

Create a variable to store the Team Id.

Find your Team id by selecting the three dots next to the Team name and selecting Get Link to Team. Copy the information between groupId= and &tenantId. The example below highlights the Team id.

https://teams.microsoft.com/l/team/19%3aMm4thjj4BUWWTIXVer6uHubE3iR0LiXbRcPHQ6LPPS01%40thread.tacv2/conversations?groupId=113cf6c5-2523-4d9d-875d-c660a03655ce&tenantId=e0e8a05c-0000-0000-0000-0000fd3820ff

Action = Initialize variable

  • Name = varApproversTeam
  • Type = string
  • Value = Add the Team id

Create a variable to store the List of approvers

Create a variable to store a list of users who act as approvers for the requests.

Action = Initialize variable

  • Name = varApprovers
  • Type = string
  • Value = blank

Create a variable to store the sensitivity GUID

Create a variable to store the sensitivity label GUID.

Action = Initialize variable

  • Name = varSensitivitylabel
  • Type = string
  • Value = blank

Create a variable to store the Form URL

Create a variable to store the URL to your Request a Team form.

Action = Initialize variable

  • Name = varRequestATeamForm
  • Type = string
  • Value =URL of the Request a Team form we created at the beginning

Create a new item in SharePoint List

The SharePoint List will store the new Team requests. Each request (submitted Form) will add a new item to the List.

Action = Create Item

  • Site Address = Select Team.
  • List name = select list name from the dropdown.
  • Map the SharePoint column to the dynamic content from the Form
    • Title = Team Name
    • Description = Team description
    • Justification = Justification for Team
    • Privacy = Team Privacy
    • Sensitivity = Team sensitivity
    • Team type = Team type
    • Owner 2 claims = User principle name of Owner 2
    • Requester claims = User principle name of the Requestor
    • Requestor country = Country of the Requestor
  • Duration = Use an Expression to reformat the date. Expression =
FormatDateTime(outputs('field in form'])

Initialize variables for duplicate checks

Create four variables for the duplicate check process.

I construct the Sharepoint URL for the Team by merging the.

  • Common SharePoint path
  • Final Team name minus spaces

Create a variable to store the SharePoint site path

Create a variable to store the SharePoint site path before the Team name. Note the URL either ends /teams/ or /sites/ depending on your configuration.

Action = Initialize variable

  • Name = varSiteDomain
  • Type = string
  • Value = URL path before your Team name.
https://<your domain name>.sharepoint.com/teams/
https://<your domain name>.sharepoint.com/sites/

Create a variable to store the final Team name

Create a variable to store the Final Team with spaces removed.

Action = Initialize variable

  • Type = string
  • Name = varTeamNameNoSpace
  • Value = Use an Expression to replace the blanks (‘ ‘ with ”)
  • Expression = Replace()
    • in the bracks select the dynamic content for the Final team name = example replace(outputs(‘Create_item_in_NewTeamList’)?[‘body/Team_x0020_Name’])
    • Between the square bracket and closing bracket, we want to replace spaces with nothing = ‘ ‘,”

The expression will look like

replace(outputs('Create_item')?['body/Final_x0020_team_x0020_name'],' ','')

Create a variable to store the new Team SharePoint site URL

This variable combines the varSiteDomain variable and the varTeamNameNoSpace variable to create the proposed URL for the Team Sharepoint site.

Action = Initialize variable

  • Name = varNewTeamURL
  • Type = string
  • Value = varSiteDomain varTeamNameNoSpace

Create a variable to store if the URL exists

This variable stores the result of the URL. the result is boolean, either True or False.

Action = Initialize variable

  • Name = varNewTeamURLExists
  • Type = boolean
  • Value = blank

Team duplicate check

There is no easy way to check if a Team name exists, so it is possible to have duplicate Team display names. A better approach is to check the SharePoint site URL, as a URL is always unique.

This step will look up the proposed SharePoint site URL (variable varNewTeamURL ) for the new Team to see if the URL already exists. If the SharePoint site URL exists, then the Team is a duplicate.

Action = Get Lists

  • Site Address = variable varNewTeamURL

There are three possible outcomes:

  1. Fails with a Status code of 404 = The site URL does not exist. The Team is not a duplicate.
  2. Is successful with a Status code of 200 =The Site URL exists, and the account running the Flow has permissions to access the site so that the action will return all Lists in the SharePoint site. This status code denotes a duplicate URL.
  3. Fails with an unauthorized error and Status code of 403 = The Site URL exists but the account running the Flow DOES NOT has permissions to access the site. This status code denotes a duplicate URL.

Get status of the Get list action

The status code is stored and used in the following steps. However, by default, if an action fails, the Flow stops with an error. In our process, we need the Flow to continue when the action fails. Therefore the Compose action, which is directly after the get Lists actions, must be changed so that the configure run after settings are adjusted to allow the Flow to continue if the previous step fails.

Action = Compose

  • Configure run after
    • Select the three dots (…) and Configure Run after
    • In the box that appears, tick Is successful and Has failed. The select Done.
    • The line above Compose Status code now shows an exclamation mark.
  • Inputs = Expression
outputs('Get_lists')['statusCode']

Set the variable varTeamURL to True or False based on the Status code

Set the variable varTeamURLExists to True or False based on the Status code.

Equals 200 = TRUE (site url exists)
Equals 403 = TRUE (site url exists)
Equals 404 = FALSE (site url does not exist)

Use a Switch action to set the variable varTeamURLExists to either true or False base on the Status code.

Action = Switch

  • On = Output of the status code
  • Add three Cases
  • Case 1 = Equals 200
    • Action = Set variable
      • Name = varTeamURLExists
      • Value = Expression TRUE
  • Case 2 = Equals 403
    • Action = Set variable
      • Name = varTeamURLExists
      • Value = Expression TRUE
  • Case 3 = Equals 404
    • Action = Set variable
      • Name = varTeamURLExists
      • Value = Expression FALSE

Add a condition to provide different actions based on whether a duplicate team exists

Add a Condition action to provide different branches based on whether the proposed Team site URL is unique or whether the site name already exists (a duplicate Team).

If the outcome is No = The Flow stops the Team creation process and sends a rejection to the Requestor.

If the outcome is Yes = The Flow carries on with the Team creation process.

Action = Condition

  • Condition = varTEAMSiteURLExists is equal to Expression = FALSE

If Condition = No (Duplicate Team name send Rejection)

The Flow stops the Team creation, updates the List with the outcome and sends a rejection message to the Requestor.

Update the SharePoint List with rejection information

Action = Update list

  • Site Address = SharePoint site
  • List name = Choose your List name
  • Approval status = Rejected – Duplicate name
  • Approval date = dynamic content Submission time
  • Approval comments = add standard text for rejection

Send a rejection message to the Requestor

Send a rejection message to the Requestor

In my scenario, I am using an adaptive card; alternatively use the Post message in chat or channel action.

Action = Post Adaptive card in chat or channel

  • Post as chatbot
  • Post in chat
  • Recipient = Requestor email
  • Add adaptive card JSON. Link to the adaptive card JSON used.

Use the following link https://adaptivecards.io/designer/ to design your adaptive cards.

Example Adaptive card output

End of No Condition path

If Condition = Yes (Continue Team creation process)

List members of the approvers’ Team

Get Team members

I do not recommend hard-coding email addresses into the Flow. Instead, use membership of a Team as the approvers. This way, the membership list is maintained outside of the Flow. The variable varApproversTeam stores the Team Id.

Action = List Group members

  • Group id = variable varApproversTeam.

Create a string of the members’ email addresses

For each Team member, append their email address to a string variable followed by a semi-colon.

Action = Append Variable

  • Name = variable varApprovers
  • Value = dynamic content Mail from List group members followed by a semi-colon (to create a semicolon-separated list of email addresses).

Send the Approval

Send the approval to the Team members. Only one of the Team members needs to approve the request.

Action = Start and wait for an approval action

  • Approval type = Approve/reject – First to approve
  • Assigned to = varApprovers variable.
  • Details = Add text and dynamic content as appropriate.

Example approval notification

 

Check the outcome of the Approval request

The Flow waits until approval is approved or rejected. (Note. The Flow times out after 30 days).

The Approval process automatically notifies the Requestor when the request is approved or rejected, and the Flow continues.

Check the Approval response

Check if the approval request is approved.

Action = Condition

  • Condition = dynamic content Outcome of the Approval is equal to Approve

No = The Approval is rejected. The Flow stops the Team creation process and updates the List with the outcome.

Yes = The Approval request is approved. The Team creation process continues.

If No – Stop the Team creation and update the List to show rejection information

The NO branch of the Flow is followed when a request is rejected.

Update List

Update the item in the List with the rejection information.

Action = Update Item

  • Site Address = SharePoint site containing the List
  • List name = name of your List
  • Id = dynamic content ID from Create Item
  • Title = dynamic content Title from Create Item
  • Approver claims = dynamic content Responses Approver user principal name from the Approval step
  • Approval status = dynamic content Outcome from the Approval step
  • Approval date = dynamic content Completion date from the Approval step
  • Approval comments = dynamic content Responses comments from the Approval step

If Yes, Continue creating the Team

The Yes branch of the Flow is followed when a request is approved.

Create a new team

Create a new Team with the Flow owner as the default Team owner. Note. At a later step, the flow owner will be removed as a Team owner and member if they are not the Requestor or the second owner.

Action = Create Team action

  • Team name = dynamic content Final Team name from SharePoint list. Note this is the Team name with the naming convention applied.
  • Description = dynamic content Description from SharePoint list.

Update list to show approval details

Update the List with details of the approval outcome and the Team id. Note an Apply to each action is automatically added as the Responses Approver id could have multiple values.

Action = Update Item

  • Site Address = SharePoint site containing the List
  • List name = name of your List
  • Id = dynamic content ID from Create Item
  • Title =dynamic content Title from Create Item
  • Approver claims = dynamic content Responses Approver user principal name from the Approval step
  • Approval status = dynamic content Outcome from the Approval step
  • Approval date = dynamic content Completion date from the Approval step
  • Approval comments = dynamic content Responses comments from the Approval step
  • Team id = New Team id from the create the Team step.

Add delay to allow the Team to provision

The Team and associate Group provision process takes a few minutes so add a Delay action to pause the Flow. The Flow will fail if it does not find the Group Id. I have added a delay of two minutes. If the Flow is failing, extend the duration.

Action = Delay

  • Count = 2
  • Units = minutes

Get the sensitivity label GUID values

In this scenario, I use two sensitivity labels in the Form.

  • Internal– blocks guests and external sharing
  • Guests – allows guests and external sharing

To add the sensitivity label to the Team requires the GUID of the sensitivity label. Use PowerShell Get-Label (ExchangePowerShell) | Microsoft Docs to find the GUID values.

Add the GUID for the selected sensitivity label

Check the sensitivity label chosen

Add the GUID for the selected sensitivity label to the variable varSensitivityLabel. Note. I have used a Switch rather than a Condition as it allows you to easily add additional Cases if you have more than two sensitivity labels.

Action = Switch

  • On = dynamic content Sensitivity from Create Item

Case 1

Action = Set variable

  • Name = varSensitivityLabel
  • Value = Add the GUID for your Internal sensitivity label

Case 2

Action = Set variable

  • Name = varSensitivityLabel
  • Value = Add the GUID for your Guest sensitivity label

Add a sensitivity label to the Team

There is no standard action to add a sensitivity label to a Team or Group, so a Send an HTTP  request to Group with Graph API to update the Group and add the sensitivity label id to the Group.

Action = Send an HTTP  request to group

  • URI = https://graph.microsoft.com/v1.0/groups/<add TeamId from the create Team step>
  • Method = PATCH
  • Body =
{
   "assignedLabels":
   [
      {
      "labelId" : "<add dynamic content varSensitivitylabel>"
      }
   ]
}

Add Team owners

Add the Requestor as a Team owner.

Action = Add member to Team

  • Team = enter custom value
    • dynamic content New TeamID created in the Create Team step
  • A user AAD ID = dynamic content User Principle Name of the Requestor and the second owner added to the Form (owner 2).
  • Select the advanced option
    • Should the newly added user be an owner = Yes

Add the Second owner as a Team owner

Action = Add member to Team

  • Team = enter custom value
    • dynamic content New TeamID created in the Create Team step
  • A user AAD ID = dynamic content User Principle Name of the second owner added to the Form (owner 2).
  • Select the advanced option
    • Should the newly added user be an owner = Yes

Check if the flow owner is the Requestor or the Second owner

Check if the Flow owner is either the Requestor or the Second owner. If this result is true, the Flow owner remains a Team owner; otherwise, remove the Flow owner as owner and member.

Action = Condition

  • User Principal Name from My profile is equal to User Principal Name from Get user profile Requestor
  • OR
  • User Principal Name from My profile is equal to User Principal Name from Get user profile Second owner

If Yes – End of Flow

Flow ends

If No, remove the Flow owner as Team owner and member

Remove the Flow owner as Team owner

There is no standard action to remove owners from Groups or Teams, so use HTTP request to a Group action with Graph API.

Action = Send HTTP request to a Group

  • URI =
https://graph.microsoft.com/v1.0/groups/<dynamic content New Team ID>/owners/<dynamic content Flow Owner Id>/$ref
  • Method = DELETE
  • Content-Type = application/json

Remove the Flow owner as a member of the Team

Action = Remove member from Group

Group Id = dynamic content New Team id

User principal name = User Principal Name from My profile

Summary

This step-by-step guide shows you how to create a Teams creation process using Power Automate.

You can easily extend and adapt this Flow to suit your specific needs. For example:

  • Send a welcome message to the new Team owners
  • Route the new team requests to different approvers based on the Form’s information.
  • Create channels in the Team
  • Create tags for a Team
  • Add a member to the Team
  • Add a member to tags in Team

Keep Reading

PreviousNext

3 thoughts on “Create a simple Teams creation workflow using Power Automate

  1. Dear Nikki,

    awesome guide – thank you!

    Two question in regards to that:

    1) Sometimes, Teams owners want e-mails to arrive in individual mailboxes rather than the mailbox – is there a possibility to automate this too?

    2) Would adding members at team creation level be of bigger issue? What if we add external people who need to be invited into the Team?

    Thank you!

  2. Would you be willing to share your ‘adaptive card’ JSON example? I really like the setup you created. Thank you in advance.

Leave a Reply

Your email address will not be published.