Messages in bot conversations
Each message in a conversation is an Activity
object of type messageType: message
. When a user sends a message, Microsoft Teams posts the message activity to your bot. Teams sends a JSON object to your bot's messaging endpoint and Teams allows only one endpoint for messaging. Your bot examines the message to determine its type and responds accordingly.
Basic conversations are handled through the Bot Framework connector, a single REST API. This API enables your bot to communicate with Teams and other channels. The Bot Builder SDK provides the following features:
- Easy access to the Bot Framework connector.
- Functionality to manage conversation flow and state.
- Simple ways to incorporate cognitive services, such as natural language processing (NLP).
Your bot receives messages from Teams using the Text
property and it sends single or multiple message responses to the users.
For more information, see user attribution for bot messages.
Receive a message
To receive a text message, use the Text
property of an Activity
object. In the bot's activity handler, use the turn context object's Activity
to read a single message request.
The following code shows an example of receiving a message activity:
protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
{
// Sends an activity to the sender of the incoming activity.
await turnContext.SendActivityAsync(MessageFactory.Text($"Echo: {turnContext.Activity.Text}"), cancellationToken);
}
Send a message
To send a text message, specify the string you want to send as an activity. In the bot's activity handler, use the turn context object's SendActivityAsync
method to send a single message response. Use the object's SendActivitiesAsync
method to send multiple responses.
The following code shows an example of sending a message when a user is added to a conversation:
protected override async Task OnMembersAddedAsync(IList<ChannelAccount> membersAdded, ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken)
{
// Sends an activity to the sender of the incoming activity.
await turnContext.SendActivityAsync(MessageFactory.Text($"Hello and welcome!"), cancellationToken);
}
Note
- Message splitting occurs when a text message and an attachment are sent in the same activity payload. Teams splits this activity into two separate activities, one with a text message and the other with an attachment. As the activity is split, you do not receive the message ID in response, which is used to update or delete the message proactively. It is recommended to send separate activities instead of depending on message splitting.
- Messages sent can be localized to provide personalization. For more information, see localize your app.
Messages sent between users and bots include internal channel data within the message. This data allows the bot to communicate properly on that channel. The Bot Builder SDK allows you to modify the message structure.
Update message
When you edit or undelete a message in a chat, the bot gets a notification of the edit message or undelete message event.
To get an edit or undelete message event notification in a bot, you can override the following handlers:
- For edit:
OnTeamsMessageEditAsync
- For undelete:
OnTeamsMessageUndeleteAsync
The following is an example of an edit message event notification when a sent message is edited:
protected override async Task OnTeamsMessageEditAsync(ITurnContext<IMessageUpdateActivity> turnContext, CancellationToken cancellationToken)
{
var replyActivity = MessageFactory.Text("message is updated");
await turnContext.SendActivityAsync(replyActivity, cancellationToken);
}
The following is an example of an undelete message event notification when a deleted message is restored:
protected override async Task OnTeamsMessageUndeleteAsync(ITurnContext<IMessageUpdateActivity> turnContext, CancellationToken cancellationToken)
{
var replyActivity = MessageFactory.Text("message is undeleted");
await turnContext.SendActivityAsync(replyActivity, cancellationToken);
}
Soft delete message
When you soft delete a message in a chat, the bot gets a notification of the soft delete message event.
To get a soft delete message event notification in a bot, you can override the OnTeamsMessageSoftDeleteAsync
handler.
The following is an example of a soft delete message event notification when a message is soft deleted:
protected override async Task OnTeamsMessageSoftDeleteAsync(ITurnContext<IMessageDeleteActivity> turnContext, CancellationToken cancellationToken)
{
var replyActivity = MessageFactory.Text("message is soft deleted");
await turnContext.SendActivityAsync(replyActivity, cancellationToken);
}
Send suggested actions
The suggested actions enable your bot to present buttons that the user can select to provide input. Suggested actions enhance user experience by enabling the user to answer a question or make a choice with selection of a button, rather than typing a response with a keyboard. When the user selects a button, it remains visible and accessible in the rich cards, but not for the suggested actions. This prevents the user from selection of stale buttons within a conversation.
To add suggested actions to a message, set the suggestedActions
property of an activity object to specify the list of card action objects that represent the buttons to be presented to the user. For more information, see sugestedActions
.
The following is an example for implementation and experience of suggested actions:
"suggestedActions": {
"actions": [
{
"type": "imBack",
"title": "Action 1",
"value": "Action 1"
},
{
"type": "imBack",
"title": "Action 2",
"value": "Action 2"
}
],
"to": [<list of recepientIds>]
}
The following illustrates an example of suggested actions:
Note
SuggestedActions
are only supported for one-on-one chat bots and text based messages and not for Adaptive Cards or attachments.imBack
is the only supported action type and Teams display up to three suggested actions.
Teams channel data
The channelData
object contains Teams-specific information and is a definitive source for team and channel IDs. Optionally, you can cache and use these IDs as keys for local storage. The TeamsActivityHandler
in the SDK pulls out important information from the channelData
object to make it accessible. However, you can always access the original data from the turnContext
object.
The channelData
object isn't included in messages in personal conversations, as these take place outside of a channel.
A typical channelData
object in an activity sent to your bot contains the following information:
eventType
: Teams event type passed only in cases of channel modification events.tenant.id
: Microsoft Azure Active Directory (Azure AD) tenant ID passed in all contexts.team
: Passed only in channel contexts, not in personal chat.id
: GUID for the channel.name
: Name of the team passed only in cases of team rename events.
channel
: Passed only in channel contexts, when the bot is mentioned or for events in channels in teams, where the bot has been added.id
: GUID for the channel.name
: Channel name passed only in cases of channel modification events.
channelData.teamsTeamId
: Deprecated. This property is only included for backward compatibility.channelData.teamsChannelId
: Deprecated. This property is only included for backward compatibility.
Example channelData object (channelCreated event)
The following code shows an example of channelData object:
"channelData": {
"eventType": "channelCreated",
"tenant": {
"id": "72f988bf-86f1-41af-91ab-2d7cd011db47"
},
"channel": {
"id": "19:693ecdb923ac4458a5c23661b505fc84@thread.skype",
"name": "My New Channel"
},
"team": {
"id": "19:693ecdb923ac4458a5c23661b505fc84@thread.skype"
}
}
Message content
Messages received from or sent to your bot can include different types of message content.
Format | From user to bot | From bot to user | Notes |
---|---|---|---|
Rich text | ✔️ | ✔️ | Your bot can send rich text, pictures, and cards. Users can send rich text and pictures to your bot. |
Pictures | ✔️ | ✔️ | Maximum 1024 × 1024 pixels and 1 MB in PNG, JPEG, or GIF format. Doesn't support the animated GIF. |
Cards | ❌ | ✔️ | See Teams card reference for supported cards. |
Emojis | ✔️ | ✔️ | Teams currently supports emojis through UTF-16, such as U+1F600 for grinning face. |
Picture messages
To enhance your message, you can include pictures as attachments to that message. For more information on attachments, see add media attachments to messages.
Pictures can be at most 1024 × 1024 pixels and 1 MB in PNG, JPEG, or GIF format. Animated GIF isn't supported.
Specify the height and width of each image by using XML. In Markdown, the image size defaults to 256×256. For example:
- Use:
<img src="http://aka.ms/Fo983c" alt="Duck on a rock" height="150" width="223"></img>
. - Don't use:

.
A conversational bot can include Adaptive Cards that simplify business workflows. Adaptive Cards offer rich customizable text, speech, images, buttons, and input fields.
Adaptive Cards
Adaptive Cards can be authored in a bot and shown in multiple apps such as Teams, your website, and so on. For more information, see Adaptive Cards.
The following code shows an example of sending a simple Adaptive Card:
{
"type": "AdaptiveCard",
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.5",
"body": [
{
"items": [
{
"size": "large",
"text": " Simple Adaptivecard Example with a Textbox",
"type": "TextBlock",
"weight": "bolder",
"wrap": true
},
],
"spacing": "extraLarge",
"type": "Container",
"verticalContentAlignment": "center"
}
]
}
Form completion feedback
You can build form completion feedback using an Adaptive Card. Form completion message appears in Adaptive Cards while sending a response to the bot. The message can be of two types, error or success:
Error: When a response sent to the bot is unsuccessful, Something went wrong, Try again message appears.
Success: When a response sent to the bot is successful, Your response was sent to the app message appears.
You can select Close or switch chat to dismiss the message.
If you don't want to display the success message, set the attribute
hide
totrue
in themsTeams
feedback
property. Following is an example:"content": { "type": "AdaptiveCard", "title": "Card with hidden footer messages", "version": "1.0", "actions": [ { "type": "Action.Submit", "title": "Submit", "msTeams": { "feedback": { "hide": true } } } ] }
For more information on cards and cards in bots, see cards documentation.
Add notifications to your message
There are two ways to send a notification from your application:
- By setting the
Notification.Alert
property on bot message. - By sending an activity feed notification using the Graph API.
You can add notifications to your message using the Notification.Alert
property. Notifications alert users to an event in your application such as new tasks, mentions, or comments. These alerts are related to what users are working on or what they must look at by inserting a notice into their activity feed. For notifications to trigger from your bot message, set the TeamsChannelData
objects Notification.Alert
property to true. If a notification is raised depends on the individual user's Teams settings, and you can't override these settings.
If you want to generate an arbitrary notification without sending a message to the user, then you can use the Graph API. For more information, see how to send activity feed notifications using Graph API along with the best practices.
Note
The Summary field displays any text from the user as a notification message in the feed.
The following code shows an example of adding notifications to your message:
protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
{
// Returns a simple text message.
var message = MessageFactory.Text("You'll get a notification, if you've turned them on.");
message.TeamsNotifyUser();
// Sends an activity to the sender of the incoming activity.
await turnContext.SendActivityAsync(message);
}
Status codes from bot conversational APIs
Ensure to handle these errors appropriately in your Teams app. The following table lists the error codes and the descriptions under which the errors are generated:
Status code | Error code and message values | Description | Retry request | Developer action |
---|---|---|---|---|
400 | Code: Bad Argument Message: *scenario specific |
Invalid request payload provided by the bot. See error message for specific details. | No | Reevaluate request payload for errors. Check returned error message for details. |
401 | Code: BotNotRegistered Message: No registration found for this bot. |
The registration for this bot wasn't found. | No | Verify the bot ID and password. Ensure that the bot ID (AAD ID) is registered in the Teams Developer Portal or via Azure bot channel registration in Azure with 'Teams' channel enabled. |
403 | Code: BotDisabledByAdmin Message: The tenant admin disabled this bot |
Tenant admin has blocked interactions between user and the bot app. Tenant admin needs to allow the app for the user inside of app policies. For more information, see app policies. | No | Stop posting to conversation until interaction with bot is explicitly initiated by a user in the conversation indicating that the bot is no longer blocked. |
403 | Code: BotNotInConversationRoster Message: The bot isn't part of the conversation roster. |
The bot isn't part of the conversation. App needs to be reinstalled in conversation. | No | Before attempting to send another conversation request, wait for an installationUpdate event, which indicates that the bot has been added again. |
403 | Code: ConversationBlockedByUser Message: User blocked the conversation with the bot. |
User has blocked the bot in personal chat or a channel through moderation settings. | No | Delete the conversation from cache. Stop attempting to post to conversations until interaction with bot is explicitly initiated by a user in the conversation, indicating that the bot is no longer blocked. |
403 | Code: InvalidBotApiHost Message: Invalid bot api host. For GCC tenants, please call https://smba.infra.gcc.teams.microsoft.com . |
The bot called the public API endpoint for a conversation that belongs to a GCC tenant. | No | Update the service URL for the conversation to https://smba.infra.gcc.teams.microsoft.com and retry the request. |
403 | Code: NotEnoughPermissions Message: *scenario specific |
Bot doesn't have required permissions to perform the requested action. | No | Determine the required action from the error message. |
404 | Code: ActivityNotFoundInConversation Message: Conversation not found. |
The message ID provided couldn't be found in the conversation. Message doesn't exist or it has been deleted. | No | Check if message ID sent is an expected value. Remove the ID if it was cached. |
404 | Code: ConversationNotFound Message: Conversation not found. |
Conversation wasn't found as it doesn't exist or has been deleted. | No | Check if conversation ID sent is an expected value. Remove the ID if it was cached. |
412 | Code: PreconditionFailed Message: Precondition failed, please try again. |
A precondition failed on one of our dependencies due to multiple concurrent operations on the same conversation. | Yes | Retry with exponential backoff. |
413 | Code: MessageSizeTooBig Message: Message size too large. |
The size of the incoming request was too large. For more information, see format your bot messages. | No | Reduce the payload size. |
429 | Code: Throttled Message: Too many requests. Also returns when to retry after. |
Too many requests were sent by the bot. For more information, see rate limit. | Yes | Retry using Retry-After header to determine backoff time. |
500 | Code: ServiceError Message: *various |
Internal server error. | No | Report the issue in developer community. |
502 | Code: ServiceError Message: *various |
Service dependency issue. | Yes | Retry with exponential backoff. If the issue persists, report the issue in developer community. |
503 | Service is unavailable. | Yes | Retry with exponential backoff. If the issue persists, report the issue in developer community. | |
504 | Gateway Timeout. | Yes | Retry with exponential backoff. If the issue persists, report the issue in developer community. |
Status codes retry guidance
The general retry guidance for each status code is listed in the following table, bot must avoid retrying status codes that aren't specified:
Status code | Retry strategy |
---|---|
403 | Retry by calling the GCC API https://smba.infra.gcc.teams.microsoft.com for InvalidBotApiHost . |
412 | Retry using exponential backoff. |
429 | Retry using Retry-After header to determine the wait time in seconds and in between requests, if available. Otherwise, retry using exponential backoff with thread ID, if possible. |
502 | Retry using exponential backoff. |
503 | Retry using exponential backoff. |
504 | Retry using exponential backoff. |
Code sample
Sample name | Description | Node.js | .NETCore | Python | .NET |
---|---|---|---|---|---|
Teams conversation bot | Messaging and conversation event handling. | View | View | View | NA |
Teams app localization | Teams app localization using bot and tab. | View | NA | NA | View |
Update and delete message | Sample app shows how to get a update and delete event notification in your bot. | View | NA | NA | View |
Next step
See also
Feedback
Submit and view feedback for