Automating Responses to Meeting Invites

A while back I was involved in a discussion about the need for agendas when accepting meeting invites. The general consensus was that agendas are required to allow the attendees to be able to understand whether they can commit to the expected time commitments and, if there is a conflict, effectively prioritise meetings. See my blog on the subject for more information.

Off the back of the conversation, I have been testing some automation around agendas which I want to now share.


There were several key requirements when handling meeting invites depending on a few criteria:

  • Is the invite from someone internal or external?
    • I do not want to automatically respond to clients and other external people as they may not be familiar with my ways of working (yet)
  • Does the invite have an agenda?
    • This is a tricky one as the definition of an agenda is very variable. The criteria I have are as follows:
    • If the word agenda is in the body, then there is an agenda
    • If the word TBC is in the body as well as the word agenda, then there is a partial agenda
  • Are there meetings already booked?
    • I am checking my calendar for existing meetings at the same time

The following table describes the expected responses:

Scenario ID Source Has Agenda? Has TBC? Has Conflicts Action Action ID
0 Internal No No No Respond with message requesting agenda 2
1 Internal No No Yes Respond with message requesting agenda 2
2 Internal No Yes No Respond with message requesting agenda 2
3 Internal No Yes Yes Respond with message requesting agenda 2
4 Internal Yes No No Accept 1
5 Internal Yes No Yes Tentative with message about scheduling 3
6 Internal Yes Yes No Tentative with message requesting agenda 4
7 Internal Yes Yes Yes Tentative with message requesting agenda and informing about scheduling 5

Anatomy of the Flow

To implement this process the Flow is split into the following sections:

  • Trigger and initialisation of variables
  • Try
    • Get information from Trigger item
    • Check for agenda
    • Check for TBC
    • Check for Conflicts
    • Determine action based on Scenario ID
    • Execute Action
  • Catch
    • Record failure
  • Finally
    • Send a message to user in Teams

In this Flow I have used binary logic to determine the scenario by allocating the following value to each condition:

  • Has Agenda = 4
  • Has TBC = 2
  • Has Conflicts = 1

If any of these conditions are true, then the appropriate value is added to the Scenario ID variable.

Based on the response table, a switch statement is used to set the Action ID variable.

Again, a switch statement is used to evaluate the Action ID to determine the actions to take.


The Flow is triggered when a new event is created. This is a simple trigger that allows the calendar to be selected and then it listens for every new event.

One of my requirements is that the responses are only sent to invites from internal organisers. To do this I have provided a trigger condition to filter organiser’s email address.

As I have invites for my team so I know when they are on holiday and they always have the word holiday in the subject, I have filtered those out as well.


The Try phase of the Flow is where the processing taking places. It starts with a set of Compose actions that are useful for debugging the executions if anything goes wrong.

For each of the three criteria there are steps to check for the condition. At this point the “agenda” and “tbc” checks are simply checking for the words within a function in a Compose action:

if (

If the condition is true, then the appropriate value is added to the Scenario ID variable.

To check for conflicts, I am using the “Find meeting times (V2)” action which is the equivalent of using the scheduling assistant, but only for me and only between the start and end times of the meeting.

Rather than being able to just use the meeting time from the meeting invite, the value needs to be converted as it is provided without the time zone. This is overcome by combining the time zone with the start and end dates using the convertToUtc function:


Once all of the checks have been completed, a switch statement is used to map the Scenarios to the Actions that need to be carried out. For each of the Scenarios, the Action ID variable is set, and a description is set that will be used in the diagnostics and notifications.

The next step is another switch statement that assesses the Action ID variable and carries out the associated actions. Action 2 is an email so the “Send an email (V2)” action is used, and for all other responses, the “Respond to an event invite (V2)” action is used.

It should be noted that the event responses need to be formatted as HTML.

The text that I use for the messages is available in the associated text files.

As an afterthought to writing the messages, I have published “Meetings Manifesto” which layout some ground rules for inviting people and being invited to meetings. This can be found here


The Catch scope does nothing other than set the Status variable to “Failed”.


The “Finally” scope builds an adaptive card and posts it to the user via Teams.

The structure of the JSON for the adaptive card is available in the associated text file.


There are many improvements that could probably be made to this process, but over the last couple of months while I have tested this with my colleagues, this process has worked effectively to encourage them to provide agendas.

If you use this pattern, then you should be able to change the actions and the mappings of the actions to the scenarios. Each message has the Scenario ID and Action ID to help with debugging changes to the mapping.

The next big enhancement would be to identify the contents of an invite more effectively as an agenda. This is a significant challenge and will likely require a healthy dose of machine learning as the complexities of defining what constitutes an agenda are more than I can do in checking for specific words.

The whole Flow is available as a zip file that can be imported into your tenant.

Comment on this post: