Create and send the task module

Important

The code samples in this section are based on 4.6 and later versions of the Bot Framework SDK. If you're looking for documentation for earlier versions, see the Messaging Extensions - v3 SDK section in the Resources folder of the documentation.

You can create the task module using an Adaptive Card or an embedded web view. To create a task module, you must perform the process called the initial invoke request. This document covers the initial invoke request, payload activity properties when a task module is invoked from 1:1 chat, group chat, channel (new post), channel (reply to thread), and command box.

Note

If you are not populating the task module with parameters defined in the app manifest, you must create the task module for users with either an Adaptive Card or an embedded web view.

The initial invoke request

In the process of the initial invoke request, your service receives an Activity object of type composeExtension/fetchTask, and you must respond with a task object containing either an Adaptive Card or a URL to the embedded web view. Along with the standard bot activity properties, the initial invoke payload contains the following request metadata:

Property name Purpose
type Type of request. It must be invoke.
name Type of command that is issued to your service. It must be composeExtension/fetchTask.
from.id ID of the user that sent the request.
from.name Name of the user that sent the request.
from.aadObjectId Azure Active Directory object ID of the user that sent the request.
channelData.tenant.id Azure Active Directory tenant ID.
channelData.channel.id Channel ID (if the request was made in a channel).
channelData.team.id Team ID (if the request was made in a channel).
value.commandId Contains the ID of the command that was invoked.
value.commandContext The context that triggered the event. It must be compose.
value.context.theme The user's client theme, useful for embedded web view formatting. It must be default, contrast or dark.

Example

The code for the initial invoke request is given in the following example:

{
  "type": "invoke",
  "id": "f:bc319b1d-571a-194d-9ffb-11d7ab37c9ff",
  "from": {
    "id": "29:1aBjVi5MwCFfhPIV03E5uDdfpBFXp_2Yz-sjrvVg12oavg96cqpE_DiMhOpmN9zHeZpYbJcuUEKuSDy2AYWPz1A",
    "name": "Olo Brockhouse",
    "aadObjectId": "b130c271-d2eb-45f9-83ab-9eb3fe3788bc"
  }
  "channelData": {
    "tenant": {
      "id": "0d9b645f-597b-41f0-a2a3-ef103fbd91bb"
    },
    "source": {
      "name": "compose"
    }
  },
  "value": {
    "commandId": "Test",
    "commandContext": "compose",
    "requestId": "fe50f49e5c74440bb2ebf07f49e9553c",
    "context": {
      "theme": "default"
    }
  },
  "name": "composeExtension/fetchTask"

Payload activity properties when a task module is invoked from 1:1 chat

The payload activity properties when a task module is invoked from 1:1 chat are listed as follows:

Property name Purpose
type Type of request. It must be invoke.
name Type of command that is issued to your service. It must be composeExtension/fetchTask.
from.id ID of the user that sent the request.
from.name Name of the user that sent the request.
from.aadObjectId Azure Active Directory object ID of the user that sent the request.
channelData.tenant.id Azure Active Directory tenant ID.
channelData.source.name The source name from where task module is invoked.
ChannelData.legacy. replyToId Gets or sets the ID of the message to which this message is a reply.
value.commandId Contains the ID of the command that was invoked.
value.commandContext The context that triggered the event. It must be compose.
value.context.theme The user's client theme, useful for embedded web view formatting. It must be default, contrast or dark.

Example

The payload activity properties when a task module is invoked from 1:1 chat are given in the following example:

{
  "type": "invoke",
  "id": "f:bc319b1d-571a-194d-9ffb-11d7ab37c9ff",
  "from": {
    "id": "29:1aBjVi5MwCFfhPIV03E5uDdfpBFXp_2Yz-sjrvVg12oavg96cqpE_DiMhOpmN9zHeZpYbJcuUEKuSDy2AYWPz1A",
    "name": "Olo Brockhouse",
    "aadObjectId": "b130c271-d2eb-45f9-83ab-9eb3fe3788bc"
  }
  "channelData": {
    "tenant": {
      "id": "0d9b645f-597b-41f0-a2a3-ef103fbd91bb"
    },
    "source": {
      "name": "compose"
    }
  },
  "value": {
    "commandId": "Test",
    "commandContext": "compose",
    "requestId": "fe50f49e5c74440bb2ebf07f49e9553c",
    "context": {
      "theme": "default"
    }
  },
  "name": "composeExtension/fetchTask"
}

Payload activity properties when a task module is invoked from a group chat

The payload activity properties when a task module is invoked from a group chat are listed as follows:

Property name Purpose
type Type of request. It must be invoke.
name Type of command that is issued to your service. It must be composeExtension/fetchTask.
from.id ID of the user that sent the request.
from.name Name of the user that sent the request.
from.aadObjectId Azure Active Directory object ID of the user that sent the request.
channelData.tenant.id Azure Active Directory tenant ID.
channelData.source.name The source name from where task module is invoked.
ChannelData.legacy. replyToId Gets or sets the ID of the message to which this message is a reply.
value.commandId Contains the ID of the command that was invoked.
value.commandContext The context that triggered the event. It must be compose.
value.context.theme The user's client theme, useful for embedded web view formatting. It must be default, contrast or dark.

Example

The payload activity properties when a task module is invoked from a group chat are given in the following example:

{
  "type": "invoke",
  "id": "f:bf72031f-a17e-f99c-48dc-5c0714950d87",
  "from": {
    "id": "29:1aBjVi5MwCFfhPIV03E5uDdfpBFXp_2Yz-sjrvVg12oavg96cqpE_DiMhOpmN9zHeZpYbJcuUEKuSDy2AYWPz1A",
    "name": "Olo Brockhouse",
    "aadObjectId": "b130c271-d2eb-45f9-83ab-9eb3fe3788bc"
  },
  "conversation": {
    "isGroup": true,
    "conversationType": "groupChat",
    "id": "19:d77be72390a1416e9644261e9064fa00@thread.skype",
    "tenantId": "0d9b645f-597b-41f0-a2a3-ef103fbd91bb"
  },
  "channelData": {
    "tenant": {
      "id": "0d9b645f-597b-41f0-a2a3-ef103fbd91bb"
    },
    "source": {
      "name": "compose"
    }
  },
  "value": {
    "commandId": "Test",
    "commandContext": "compose",
    "requestId": "213167a1e3b6428b93e186ea5407c759",
    "context": {
      "theme": "default"
    }
  },
  "name": "composeExtension/fetchTask"
}

Payload activity properties when a task module is invoked from a channel (new post)

The payload activity properties when a task module is invoked from a channel (new post) are listed as follows:

Property name Purpose
type Type of request. It must be invoke.
name Type of command that is issued to your service. It must be composeExtension/fetchTask.
from.id ID of the user that sent the request.
from.name Name of the user that sent the request.
from.aadObjectId Azure Active Directory object ID of the user that sent the request.
channelData.tenant.id Azure Active Directory tenant ID.
channelData.channel.id Channel ID (if the request was made in a channel).
channelData.team.id Team ID (if the request was made in a channel).
channelData.source.name The source name from where task module is invoked.
ChannelData.legacy. replyToId Gets or sets the ID of the message to which this message is a reply.
value.commandId Contains the ID of the command that was invoked.
value.commandContext The context that triggered the event. It must be compose.
value.context.theme The user's client theme, useful for embedded web view formatting. It must be default, contrast, or dark.

Example

The payload activity properties when a task module is invoked from a channel (new post) are given in the following example:

{
  "type": "invoke",
  "id": "f:a5fbb109-c989-c449-ee83-71ac99919d4b",
  "from": {
    "id": "29:1aBjVi5MwCFfhPIV03E5uDdfpBFXp_2Yz-sjrvVg12oavg96cqpE_DiMhOpmN9zHeZpYbJcuUEKuSDy2AYWPz1A",
    "name": "Olo Brockhouse",
    "aadObjectId": "b130c271-d2eb-45f9-83ab-9eb3fe3788bc"
  },
  "conversation": {
    "isGroup": true,
    "conversationType": "channel",
    "id": "19:6decf54d86d945e4b3924b63a9161a78@thread.skype",
    "name": "parsable",
    "tenantId": "0d9b645f-597b-41f0-a2a3-ef103fbd91bb"
  },
  "channelData": {
    "channel": {
      "id": "19:6decf54d86d945e4b3924b63a9161a78@thread.skype"
    },
    "team": {
      "id": "19:acca514e83cb497e960e0b014d405336@thread.skype"
    },
    "tenant": {
      "id": "0d9b645f-597b-41f0-a2a3-ef103fbd91bb"
    },
    "source": {
      "name": "compose"
    }
  },
  "value": {
    "commandId": "Test",
    "commandContext": "compose",
    "requestId": "5336640edc7748b28ce2df43f5b45963",
    "context": {
      "theme": "default"
    }
  },
  "name": "composeExtension/fetchTask"
}

Payload activity properties when a task module is invoked from a channel (reply to thread)

The payload activity properties when a task module is invoked from a channel (reply to thread) are listed as follows:

Property name Purpose
type Type of request. It must be invoke.
name Type of command that is issued to your service. It must be composeExtension/fetchTask.
from.id ID of the user that sent the request.
from.name Name of the user that sent the request.
from.aadObjectId Azure Active Directory object ID of the user that sent the request.
channelData.tenant.id Azure Active Directory tenant ID.
channelData.channel.id Channel ID (if the request was made in a channel).
channelData.team.id Team ID (if the request was made in a channel).
channelData.source.name The source name from where task module is invoked.
ChannelData.legacy. replyToId Gets or sets the ID of the message to which this message is a reply.
value.commandId Contains the ID of the command that was invoked.
value.commandContext The context that triggered the event. It must be compose.
value.context.theme The user's client theme, useful for embedded web view formatting. It must be default, contrast or dark.

Example

The payload activity properties when a task module is invoked from a channel (reply to thread) are given in the following example:

{
  "type": "invoke",
  "id": "f:19ccc884-c792-35ef-2f40-d0ff43dcca71",
  "from": {
    "id": "29:1aBjVi5MwCFfhPIV03E5uDdfpBFXp_2Yz-sjrvVg12oavg96cqpE_DiMhOpmN9zHeZpYbJcuUEKuSDy2AYWPz1A",
    "name": "Olo Brockhouse",
    "aadObjectId": "b130c271-d2eb-45f9-83ab-9eb3fe3788bc"
  },
  "conversation": {
    "isGroup": true,
    "conversationType": "channel",
    "id": "19:6decf54d86d945e4b3924b63a9161a78@thread.skype;messageid=1611060744833",
    "name": "parsable",
    "tenantId": "0d9b645f-597b-41f0-a2a3-ef103fbd91bb"
  },
  "channelData": {
    "channel": {
      "id": "19:6decf54d86d945e4b3924b63a9161a78@thread.skype"
    },
    "team": {
      "id": "19:acca514e83cb497e960e0b014d405336@thread.skype"
    },
    "tenant": {
      "id": "0d9b645f-597b-41f0-a2a3-ef103fbd91bb"
    },
    "source": {
      "name": "compose"
    }
  },
  "value": {
    "commandId": "TEst",
    "commandContext": "message",
    "requestId": "7f7d22efe5414818becebcec649a7912",
    "messagePayload": {
      "linkToMessage": "https://teams.microsoft.com/l/message/19:6decf54d86d945e4b3924b63a9161a78@thread.skype/1611060744833",
      "id": "1611060744833",
      "replyToId": null,
      "createdDateTime": "2021-01-19T12:52:24.833Z",
      "lastModifiedDateTime": null,
      "deleted": false,
      "summary": null,
      "importance": "normal",
      "locale": "en-us",
      "body": {
        "contentType": "html",
        "content": "<div><div><at id=\"0\">Testing outgoing Webhook-Nikitha</at> - Hi</div>\n</div>"
      },
      "from": {
        "device": null,
        "conversation": null,
        "user": {
          "userIdentityType": "aadUser",
          "id": "b130c271-d2eb-45f9-83ab-9eb3fe3788bc",
          "displayName": "Olo Brockhouse"
        },
        "application": null
      },
      "reactions": [],
      "mentions": [
        {
          "id": 0,
          "mentionText": "Testing outgoing Webhook-Nikitha",
          "mentioned": {
            "device": null,
            "conversation": null,
            "user": null,
            "application": {
              "applicationIdentityType": "webhook",
              "id": "b8c1c68c-e290-4bdd-81c3-266f310751dc",
              "displayName": "Testing outgoing Webhook-Nikitha"
            }
          }
        }
      ],
      "attachments": []
    },
    "context": {
      "theme": "default"
    }
  },
  "name": "composeExtension/fetchTask"
}

Payload activity properties when a task module is invoked from a command box

The payload activity properties when a task module is invoked from a command box are listed as follows:

Property name Purpose
type Type of request. It must be invoke.
name Type of command that is issued to your service. It must be composeExtension/fetchTask.
from.id ID of the user that sent the request.
from.name Name of the user that sent the request.
from.aadObjectId Azure Active Directory object ID of the user that sent the request.
channelData.tenant.id Azure Active Directory tenant ID.
channelData.source.name The source name from where task module is invoked.
value.commandId Contains the ID of the command that was invoked.
value.commandContext The context that triggered the event. It must be compose.
value.context.theme The user's client theme, useful for embedded web view formatting. It must be default, contrast, or dark.

Example

The payload activity properties when a task module is invoked from a command box are given in the following example:

{
  "type": "invoke",
  "id": "f:172560f1-95f9-3189-edb2-b7612cd1a3cd",
    "id": "29:1aBjVi5MwCFfhPIV03E5uDdfpBFXp_2Yz-sjrvVg12oavg96cqpE_DiMhOpmN9zHeZpYbJcuUEKuSDy2AYWPz1A",
    "name": "Olo Brockhouse",
    "aadObjectId": "b130c271-d2eb-45f9-83ab-9eb3fe3788bc"
  },
  "conversation": {
    "isGroup": true,
    "conversationType": "channel",
    "id": "19:6decf54d86d945e4b3924b63a9161a78@thread.skype",
    "name": "parsable",
    "tenantId": "0d9b645f-597b-41f0-a2a3-ef103fbd91bb"
  },
  "channelData": {
    "channel": {
      "id": "19:6decf54d86d945e4b3924b63a9161a78@thread.skype"
    },
    "team": {
      "id": "19:acca514e83cb497e960e0b014d405336@thread.skype"
    },
    "tenant": {
      "id": "0d9b645f-597b-41f0-a2a3-ef103fbd91bb"
    },
    "source": {
      "name": "compose"
    }
  },
  "value": {
    "commandId": "TEst",
    "commandContext": "compose",
    "requestId": "d2ce690cdc2b4920a538e75882610a30",
    "context": {
      "theme": "default"
    }
  },
  "name": "composeExtension/fetchTask"
}

Example

The following code section is an example of fetchTask request:

protected override async Task<MessagingExtensionActionResponse> OnTeamsMessagingExtensionFetchTaskAsync(ITurnContext<IInvokeActivity> turnContext, MessagingExtensionAction action, CancellationToken cancellationToken)
{
  //handle fetch task
}

Initial invoke request from a message

When your bot is invoked from a message, the value object in the initial invoke request must contain the details of the message that your messaging extension is invoked from. The reactions and mentions arrays are optional, and they are not present if there are no reactions or mentions in the original message. The following section is an example of the value object:

protected override async Task<MessagingExtensionActionResponse> OnTeamsMessagingExtensionFetchTaskAsync(ITurnContext<IInvokeActivity> turnContext, MessagingExtensionAction action, CancellationToken cancellationToken)
{
  var messageText = action.MessagePayload.Body.Content;
  var fromId = action.MessagePayload.From.User.Id;

  //finish handling the fetchTask
}

Respond to the fetchTask

Respond to the invoke request with a task object that contains either a taskInfo object with the Adaptive Card or web URL, or a simple string message.

Property name Purpose
type Can be either continue to present a form, or message for a simple popup.
value Either a taskInfo object for a form, or a string for a message.

The schema for the taskInfo object is:

Property name Purpose
title The title of the task module.
height It must be either an integer (in pixels), or small, medium, large.
width It must be either an integer (in pixels), or small, medium, large.
card The adaptive card defining the form (if using one).
url The URL to be opened inside of the task module as an embedded web view.
fallbackUrl If a client does not support the task module feature, this URL is opened in a browser tab.

Respond to the fetchTask with an Adaptive Card

When using an adaptive card, you must respond with a task object with the value object containing an Adaptive Card.

Example

The following code section is an example to fetchTask response with an adaptive card:

This sample uses the AdaptiveCards NuGet package in addition to the Bot Framework SDK.

protected override async Task<MessagingExtensionActionResponse> OnTeamsMessagingExtensionFetchTaskAsync(ITurnContext<IInvokeActivity> turnContext, MessagingExtensionAction action, CancellationToken cancellationToken)
{
  string placeholder = "Not invoked from message";

  if (action.MessagePayload != null)
  {
      var messageText = action.MessagePayload.Body.Content;
      var fromId = action.MessagePayload.From.User.Id;
      placeholder = "Invoked from message";
  }

  var response = new MessagingExtensionActionResponse()
  {
    Task = new TaskModuleContinueResponse()
    {
      Value = new TaskModuleTaskInfo()
      {
        Height = "small",
        Width = "small",
        Title = "Example task module",
        Card = new Attachment()
        {
          ContentType = AdaptiveCard.ContentType,
          Content = new AdaptiveCard("1.0")
          {
            Body = new List<AdaptiveElement>()
            {
              new AdaptiveTextInput() { Id = "FormField1", Placeholder = placeholder},
              new AdaptiveTextInput() { Id = "FormField2", Placeholder = "FormField2"},
              new AdaptiveTextInput() { Id = "FormField3", Placeholder = "FormField3"},
            },
            Actions = new List<AdaptiveAction>()
            {
              new AdaptiveSubmitAction()
              {
                Type = AdaptiveSubmitAction.TypeName,
                Title = "Submit",
              },
            },
          },
        },
      },
    },
  };
  return response;
}

Create a task module with an embedded web view

When using an embedded web view, you must respond with a task object with the value object containing the URL to the web form that you want to load. The domains of any URL you want to load must be included in the validDomains array in your app's manifest. For more information on building your embedded web view, see the task module documentation.

protected override async Task<MessagingExtensionActionResponse> OnTeamsMessagingExtensionFetchTaskAsync(ITurnContext<IInvokeActivity> turnContext, MessagingExtensionAction action, CancellationToken cancellationToken)
{
  string placeholder = "Not invoked from message";

  if (action.MessagePayload != null)
  {
      var messageText = action.MessagePayload.Body.Content;
      var fromId = action.MessagePayload.From.User.Id;
      placeholder = "Invoked from message";
  }

  var response = new MessagingExtensionActionResponse()
  {
    Task = new TaskModuleContinueResponse()
    {
      Value = new TaskModuleTaskInfo()
      {
        Height = "small",
        Width = "small",
        Title = "Example task module",
        Url = "https://contoso.com/msteams/taskmodules/newcustomer",
        },
      },
    },
  };
  return response;
}

Request to install your conversational bot

If the app contains a conversational bot, install the bot in the conversation and then load the task module. The bot is useful to get additional context for the task module. An example for this scenario is to fetch the roster to populate a people picker control or the list of channels in a team.

When the messaging extension receives the composeExtension/fetchTask invoke, check if the bot is installed in the current context to facilitate the flow. For example, check the flow with a get roster call. If the bot is not installed, return an Adaptive Card with an action that requests the user to install the bot. The user must have the permission to install the apps in that location for checking. If the app installation is unsuccessful, the user receives a message to contact the administrator.

Example

The following code section is an example of the response:

{
  "type": "AdaptiveCard",
  "body": [
    {
      "type": "TextBlock",
      "text": "Looks like you haven't used Disco in this team/chat"
    }
  ],
  "actions": [
    {
      "type": "Action.Submit",
      "title": "Continue",
      "data": {
        "msteams": {
          "justInTimeInstall": true
        }
      }
    }
  ],
  "version": "1.0"
}

After the installation of conversational bot, it receives another invoke message with name = composeExtension/submitAction, and value.data.msteams.justInTimeInstall = true.

Example

The following code section is an example of the task response to the invoke:

{
  "value": {
    "commandId": "giveKudos",
    "commandContext": "compose",
    "context": {
      "theme": "default"
    },
    "data": {
      "msteams": {
        "justInTimeInstall": true
      }
    }
  },
  "conversation": {
    "id": "19:7705841b240044b297123ad7f9c99217@thread.skype"
  },
  "name": "composeExtension/submitAction",
  "imdisplayname": "Bob Smith"
}

The task response to the invoke must be similar to that of the installed bot.

Example

The following code section is an example of just-in time installation of app with Adaptive card:

private static Attachment GetAdaptiveCardAttachmentFromFile(string fileName)
  {
      //Read the card json and create attachment.
         string[] paths = { ".", "Resources", fileName };
         var adaptiveCardJson = File.ReadAllText(Path.Combine(paths));
         var adaptiveCardAttachment = new Attachment()
            {
                ContentType = "application/vnd.microsoft.card.adaptive",
                Content = JsonConvert.DeserializeObject(adaptiveCardJson),
            };
            return adaptiveCardAttachment;
        }

Code sample

Sample Name Description .NET Node.js
Teams messaging extension action Describes how to define action commands, create task module, and respond to task module submit action. View View
Teams messaging extension search Describes how to define search commands and respond to searches. View View

See also

Define action commands

Next step