Skip to main content

🔍 Search commands

Message extension search commands allow users to search external systems and insert the results of that search into a message in the form of a card.

Search command invocation locations​

There are two different areas search commands can be invoked from:

  1. Compose Area
  2. Compose Box

Compose Area and Box​

Screenshot of Teams with outlines around the 'Compose Box' (for typing messages) and the 'Compose Area' (the menu option next to the compose box that provides a search bar for actions and apps).

Setting up your Teams app manifest​

To use search commands you have to define them in the Teams app manifest. Here is an example:

"composeExtensions": [
{
"botId": "${{BOT_ID}}",
"commands": [
{
"id": "searchQuery",
"context": [
"compose",
"commandBox"
],
"description": "Test command to run query",
"title": "Search query",
"type": "query",
"parameters": [
{
"name": "searchQuery",
"title": "Search Query",
"description": "Your search query",
"inputType": "text"
}
]
}
]
}
]

Here we are defining the searchQuery search (or query) command.

Handle submission​

Handle the search query submission when the searchQuery search command is invoked.

using Microsoft.Teams.Apps.MessageExtensions;

//...

bot.OnQuery(async (context, cancellationToken) =>
{
MessageExtensionQuery? query = context.Activity.Value;
string? commandId = query?.CommandId;
string searchText = query?.Parameters?.FirstOrDefault(p => p.Name == "searchQuery")?.Value ?? "";

if (commandId == "searchQuery")
{
return CreateSearchResults(searchText);
}

return MessageExtensionResponse.CreateBuilder()
.WithType(MessageExtensionResponseTypes.Message)
.WithText("Unknown command")
.Build();
});

CreateSearchResults() method

using Microsoft.Teams.Apps.MessageExtensions;
using Microsoft.Teams.Apps.Schema;

//...

private static InvokeResponse<MessageExtensionResponse> CreateSearchResults(string query)
{
var attachments = new List<TeamsAttachment>();

for (int i = 1; i <= 5; i++)
{
// Thumbnail cards with a tap/invoke value to trigger OnSelectItem
var previewCard = new
{
title = $"Result {i}",
text = $"This is a preview of result {i} for query '{query}'.",
tap = new
{
type = "invoke",
value = new { itemIndex = i, query }
}
};

attachments.Add(TeamsAttachment.CreateBuilder()
.WithContent(previewCard)
.WithContentType(AttachmentContentTypes.ThumbnailCard)
.Build());
}

return MessageExtensionResponse.CreateBuilder()
.WithType(MessageExtensionResponseTypes.Result)
.WithAttachmentLayout(TeamsAttachmentLayouts.List)
.WithAttachments([.. attachments])
.Build();
}

To implement custom actions when a user clicks on a search result item, you can handle the select item event:

using System.Text.Json;
using Microsoft.Teams.Apps.MessageExtensions;
using Microsoft.Teams.Apps.Schema;
using Microsoft.Teams.Cards;

//...

bot.OnSelectItem(async (context, cancellationToken) =>
{
JsonElement selectedItem = context.Activity.Value;
string itemJson = JsonSerializer.Serialize(selectedItem);

var card = new AdaptiveCard
{
Body = new List<CardElement>
{
new TextBlock("Item Selected")
{
Weight = TextWeight.Bolder,
Size = TextSize.Large,
Color = TextColor.Good
},
new TextBlock("You selected the following item:") { Wrap = true },
new TextBlock(itemJson) { Wrap = true, FontType = FontType.Monospace, Separator = true }
}
};

TeamsAttachment attachment = TeamsAttachment.CreateBuilder()
.WithAdaptiveCard(JsonSerializer.SerializeToElement(card))
.Build();

return MessageExtensionResponse.CreateBuilder()
.WithType(MessageExtensionResponseTypes.Result)
.WithAttachmentLayout(TeamsAttachmentLayouts.List)
.WithAttachments(attachment)
.Build();
});

The search results include both a full adaptive card and a preview card. The preview card appears as a list item in the search command area:

Screenshot of Teams showing a message extensions search menu open with list of search results displayed as preview cards.

When a user clicks on a list item the dummy adaptive card is added to the compose box:

Screenshot of Teams showing the selected adaptive card added to the compose box.

To implement custom actions when a user clicks on a search result item, you can add the tap property to the preview card. This allows you to handle the click event with custom logic:

Resources​