From c5b1ee54f7b018b87160920a2b6379927c93c588 Mon Sep 17 00:00:00 2001 From: v-nikitach Date: Fri, 3 Apr 2026 06:58:47 +0530 Subject: [PATCH 01/10] Update create-a-bot-commands-menu.md --- .../bots/how-to/create-a-bot-commands-menu.md | 355 ++++++++++++++++-- 1 file changed, 322 insertions(+), 33 deletions(-) diff --git a/msteams-platform/bots/how-to/create-a-bot-commands-menu.md b/msteams-platform/bots/how-to/create-a-bot-commands-menu.md index b84caaf1882..58bead424f6 100644 --- a/msteams-platform/bots/how-to/create-a-bot-commands-menu.md +++ b/msteams-platform/bots/how-to/create-a-bot-commands-menu.md @@ -5,7 +5,7 @@ ms.topic: how-to ms.localizationpriority: medium ms.author: anclear ms.owner: ginobuzz -ms.date: 03/11/2025 +ms.date: 04/03/2026 --- # Create a commands menu @@ -28,11 +28,7 @@ To define a set of core commands that your bot can respond to, you can add a com ## Create a command menu for your bot > [!NOTE] -> It's recommended that you'd create a command bot by following the step-by-step guide to [build command bot with JavaScript](../../sbs-gs-commandbot.yml) using the new generation development tool for Teams. For more information about Microsoft 365 Agents Toolkit (previously known as Teams Toolkit), see [Agents Toolkit overview for Visual Studio Code](../../toolkit/agents-toolkit-fundamentals.md) and [Agents Toolkit overview for Visual Studio](../../toolkit/toolkit-v4/agents-toolkit-fundamentals-vs.md). - -[!INCLUDE [pre-release-label](~/includes/v4-to-v3-pointer-bots.md)] - -Command menus are defined in your app manifest. You can either use **Developer Portal** to create them or add them manually in the app manifest. +> It's recommended that you create a command bot by following the [Teams SDK quickstart](/microsoftteams/platform/teams-sdk/getting-started/quickstart) and reviewing the [code basics](/microsoftteams/platform/teams-sdk/getting-started/code-basics). For more information about Microsoft 365 Agents Toolkit (previously known as Teams Toolkit), see [Agents Toolkit overview for Visual Studio Code](../../toolkit/agents-toolkit-fundamentals.md) and [Agents Toolkit overview for Visual Studio](../../toolkit/toolkit-v4/agents-toolkit-fundamentals-vs.md). ### Create a command menu for your bot using Developer Portal @@ -159,59 +155,353 @@ The manifest example code for the menu for each scope is as follows: } ``` -You must handle menu commands in your bot code as you handle any message from users. You can handle menu commands in your bot code by parsing out the **\@Mention** portion of the message text. +You must handle menu commands in your bot code as you handle any message from users. ## Handle menu commands in your bot code -Bots in a group or channel respond only when they're mentioned `@botname` in a message. Every message received by a bot when in a group or channel scope contains its name in the message text. Before handling the command being returned, your message parsing must handle the message received by a bot with its name. +In the Teams SDK, incoming messages are routed through an activity handler. You register a message handler using `app.on('message', ...)` (TypeScript), `app.OnMessage(...)` (C#), or `@app.on_message` (Python), and the message text is available directly via `activity.text`. The SDK's activity router handles message delivery across all scopes (personal, group chat, and channel), so you don't need to manually parse or strip bot mentions from the message text. > [!NOTE] > To handle the commands in code, they are sent to your bot as a regular message. You must handle them as you would handle any other message from your users. The commands in code insert pre-configured text into the text box. The user must then send that text as they do for any other message. # [C#](#tab/dotnet) -* [SDK reference](/dotnet/api/microsoft.bot.schema.activityextensions.removerecipientmention?view=botbuilder-dotnet-stable&preserve-view=true) +* [Sample code reference](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/abc97268bf41536509383283114c3a33684f0568/samples/bot-quickstart/dotnet/bot-quickstart) -* [Sample code reference](https://github.com/OfficeDev/Microsoft-Teams-Samples/blob/main/samples/app-hello-world/csharp/Microsoft.Teams.Samples.HelloWorld.Web/Bots/MessageExtension.cs#L19) +```csharp +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Microsoft.Teams.Plugins.AspNetCore.Extensions; +using Microsoft.Teams.Apps; +using Microsoft.Teams.Apps.Activities; +using Microsoft.Teams.Api.Activities; +using Microsoft.Teams.Api.Clients; + +// Initialize Teams App - automatically uses CLIENT_ID and CLIENT_SECRET from environment variables +var builder = WebApplication.CreateBuilder(args); +builder.AddTeams(); +var webApp = builder.Build(); +var teamsApp = webApp.UseTeams(true); + +// Handle conversation update events (when bot is added or members join) +teamsApp.OnConversationUpdate(async context => +{ + var membersAdded = context.Activity.MembersAdded; + if (membersAdded != null) + { + foreach (var member in membersAdded) + { + // Check if bot was added to the conversation + if (member.Id == context.Activity.Recipient?.Id) + { + await SendWelcomeMessage(context); + } + } + } +}); + +// Handles incoming messages and routes to appropriate functions based on message content +teamsApp.OnMessage(async context => +{ + // Get message text and normalize it + var text = (context.Activity.Text ?? "").Trim().ToLower(); + + // Handle mention me command + if (text.Contains("mentionme") || text.Contains("mention me")) + { + await MentionUser(context); + } + // Handle whoami command + else if (text.Contains("whoami")) + { + await GetSingleMember(context); + } + // Handle welcome command + else if (text.Contains("welcome")) + { + await SendWelcomeMessage(context); + } + // Echo greeting messages + else if (text.Contains("hi") || text.Contains("hello")) + { + await EchoMessage(context, text); + } + else + { + await SendWelcomeMessage(context); + } +}); -You can parse out the **\@Mention** portion of the message text using a static method provided with the Microsoft Bot Framework. It's a method of the `Activity` class named `RemoveRecipientMention`. +// Sends a welcome message +async Task SendWelcomeMessage(IContext context) where T : IActivity +{ + await context.Send("Welcome to the Teams Quickstart Bot!"); +} -The C# code to parse out the **\@Mention** portion of the message text is as follows: +// Echo back the user's message +async Task EchoMessage(IContext context, string text) +{ + await context.Send($"**Echo :** {text}"); +} -```csharp -// Remove recipient mention text from Text property. -// Use with caution because this function is altering the text on the Activity. -var modifiedText = turnContext.Activity.RemoveRecipientMention(); -``` +// Retrieves and displays information about the current user +async Task GetSingleMember(IContext context) +{ + await context.Send($"You are: {context.Activity.From.Name}"); +} -# [JavaScript](#tab/javascript) +// Mention a user in a message +async Task MentionUser(IContext context) +{ + var member = context.Activity.From; + var mentionText = $"{member.Name}"; + var activity = new MessageActivity() + .WithText($"Hello {mentionText}") + .AddMention(member, addText: false); -* [SDK reference](/javascript/api/botbuilder-core/turncontext?view=botbuilder-ts-latest&preserve-view=true#botbuilder-core-turncontext-removementiontext) + await context.Send(activity); +} -* [Sample code reference](https://github.com/OfficeDev/Microsoft-Teams-Samples/blob/main/samples/bot-people-picker-adaptive-card/nodejs/bots/teamsBot.js#L21) +// Starts the Teams bot application and listens for incoming requests +webApp.Run(); +``` -You can parse out the **\@Mention** portion of the message text using a static method provided with the Bot Framework. It's a method of the `TurnContext` class named `removeMentionText`. +# [TypeScript](#tab/typescript) -The JavaScript code to parse out the **\@Mention** portion of the message text is as follows: +* [Sample code reference](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/abc97268bf41536509383283114c3a33684f0568/samples/bot-quickstart/nodejs/bot-quickstart) ```javascript -// Remove mention text from Text property, this function is altering the text on the Activity. -const modifiedText = TurnContext.removeMentionText(turnContext.activity, turnContext.activity.recipient.id); -``` +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. -# [Python](#tab/python) +import { App, IActivityContext } from '@microsoft/teams.apps'; +import { TeamsChannelAccount, IMessageActivity } from '@microsoft/teams.api'; + +// Initialize Teams App - automatically uses CLIENT_ID and CLIENT_SECRET from environment variables +// Note: .env file is only required when running on Teams (not needed for local development with devtools) +const app = new App(); + +// Handle conversation update events (when bot is added or members join) +app.on('conversationUpdate', async (context) => { + const { activity } = context; + const membersAdded = (activity as any).membersAdded || []; + + for (const member of membersAdded) { + // Check if bot was added to the conversation + if (member.id === activity.recipient.id) { + await sendWelcomeMessage(context); + } + } +}); + +// Handles incoming messages and routes to appropriate functions based on message content +app.on('message', async (context) => { + const { activity } = context; + + // Get message text and normalize it + const messageActivity = activity as IMessageActivity; + let text = (messageActivity.text || '').trim().toLowerCase(); + + // Handle mention me command + if (text.includes('mentionme') || text.includes('mention me')) { + await mentionUser(context); + } + // Handle whoami command + else if (text.includes('whoami')) { + await getSingleMember(context); + } + // Handle welcome command + else if (text.includes('welcome')) { + await sendWelcomeMessage(context); + } + // Handle greeting messages + else if (text.includes('hi') || text.includes('hello')) { + await echoMessage(context, text); + } + // Default: echo back any other message + else if (text) { + await echoMessage(context, text); + } +}); + +// Sends a welcome message +async function sendWelcomeMessage(context: IActivityContext): Promise { + await context.send({ + type: 'message', + text: 'Welcome to the Teams Quickstart Bot!' + }); +} -* [SDK reference](/python/api/botbuilder-core/botbuilder.core.turncontext?view=botbuilder-py-latest&preserve-view=true#botbuilder-core-turncontext-remove-recipient-mention) +// Echo back the user's message +async function echoMessage(context: IActivityContext, text: string): Promise { + await context.send({ + type: 'message', + text: `**Echo:** ${text}` + }); +} -* [Sample code reference](https://github.com/OfficeDev/Microsoft-Teams-Samples/blob/main/samples/bot-conversation/python/bots/teams_conversation_bot.py#L34) +// Retrieves and displays information about the current user +async function getSingleMember(context: IActivityContext): Promise { + const { activity } = context; + const conversationId = activity.conversation.id; + const userId = activity.from.id; + + try { + const member: TeamsChannelAccount = await context.api.conversations.members(conversationId).getById(userId); + await context.send({ + type: 'message', + text: `You are: ${member.name}` + }); + } catch (error) { + console.error('Error getting member:', error); + } +} -You can parse out the **@Mention** portion of the message text using a static method provided with the Bot Framework. It's a method of the `TurnContext` class named `remove_recipient_mention`. +// Mention a user in a message +async function mentionUser(context: IActivityContext): Promise { + const { activity } = context; + const conversationId = activity.conversation.id; + const userId = activity.from.id; + + try { + const member: TeamsChannelAccount = await context.api.conversations.members(conversationId).getById(userId); + + // Create a text message with user mention + const mentionText = `${member.name}`; + await context.send({ + type: 'message', + text: `Hello ${mentionText}`, + entities: [ + { + type: 'mention', + text: mentionText, + mentioned: { + id: userId, + name: member.name, + role: 'user' + } + } + ] + }); + } catch (error) { + console.error('Error mentioning user:', error); + } +} -The Python code to parse out the **\@Mention** portion of the message text is as follows: +// Starts the Teams bot application and listens for incoming requests +app.start().catch(console.error); +``` + +# [Python](#tab/python) + +* [Sample code reference](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/abc97268bf41536509383283114c3a33684f0568/samples/bot-quickstart/python/bot-quickstart) ```python -# Remove recipient mention text from Text property, this function is altering the text on the Activity. -modified_text = TurnContext.remove_recipient_mention(turn_context.activity) +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +import asyncio + +from dotenv import load_dotenv +from microsoft_teams.api import MessageActivity, MessageActivityInput +from microsoft_teams.apps import ActivityContext, App + +# Load environment variables +load_dotenv() + +# Initialize Teams App - automatically uses CLIENT_ID and CLIENT_SECRET from environment variables +# Note: .env file is only required when running on Teams (not needed for local development with devtools) +app = App() + +async def send_welcome_message(ctx: ActivityContext) -> None: + """Sends a welcome message with available commands.""" + welcome_message = ( + "Welcome to the Teams Quickstart Bot!" + ) + await ctx.send(MessageActivityInput(text=welcome_message)) + + +async def echo_message(ctx: ActivityContext, text: str) -> None: + """Echo back the user's message.""" + await ctx.send(MessageActivityInput(text=f"**Echo:** {text}")) + + +async def get_single_member(ctx: ActivityContext[MessageActivity]) -> None: + """Retrieves and displays information about the current user.""" + try: + conversationId = ctx.activity.conversation.id + userId = ctx.activity.from_.id + user = await ctx.api.conversations.members(conversationId).get(userId) + await ctx.send(MessageActivityInput(text=f"You are: {user.name}")) + except Exception as error: + print(f"Error getting member: {error}") + + +async def mention_user(ctx: ActivityContext[MessageActivity]) -> None: + """Mention a user in a message.""" + try: + + conversationId = ctx.activity.conversation.id + userId = ctx.activity.from_.id + + # Get user info directly from the activity + user = await ctx.api.conversations.members(conversationId).get(userId) + + # Create a text message with user mention + mention_text = f"{user.name}" + await ctx.send(MessageActivityInput( + text=f"Hello {mention_text}", + entities=[ + { + "type": "mention", + "text": mention_text, + "mentioned": { + "id": userId, + "name": user.name, + "role": "user" + } + } + ] + )) + except Exception as error: + print(f"Error mentioning user: {error}") + + +@app.on_conversation_update +async def handle_conversation_update(ctx: ActivityContext) -> None: + """Handle conversation update events (when bot is added or members join).""" + members_added = getattr(ctx.activity, 'members_added', []) + + for member in members_added: + # Check if bot was added to the conversation + if member.id == ctx.activity.recipient.id: + await send_welcome_message(ctx) + + +@app.on_message +async def handle_message(ctx: ActivityContext[MessageActivity]) -> None: + """Handles incoming messages and routes to appropriate functions based on message content.""" + # Get message text and normalize it + text = (ctx.activity.text or "").strip().lower() + + # Handle mention me command + if "mentionme" in text or "mention me" in text: + await mention_user(ctx) + # Handle whoami command + elif "whoami" in text: + await get_single_member(ctx) + # Handle welcome command + elif 'welcome' in text: + await send_welcome_message(ctx) + # Handle hi/hello - echo back + elif "hi" in text or "hello" in text: + await echo_message(ctx, text) + + +# Starts the Teams bot application and listens for incoming requests +if __name__ == "__main__": + asyncio.run(app.start()) ``` * * * @@ -229,7 +519,6 @@ Following are the command menu best practices: > [!NOTE] > If you remove any commands from your manifest, you must redeploy your app to implement the changes. In general, any changes to the manifest require you to redeploy your app. - ## Next step > [!div class="nextstepaction"] From 66ef82e2f3c3732e25bb6fc8e20d5378f2a88ec6 Mon Sep 17 00:00:00 2001 From: v-nikitach Date: Mon, 6 Apr 2026 15:52:52 +0530 Subject: [PATCH 02/10] Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- msteams-platform/bots/how-to/create-a-bot-commands-menu.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msteams-platform/bots/how-to/create-a-bot-commands-menu.md b/msteams-platform/bots/how-to/create-a-bot-commands-menu.md index 58bead424f6..d4eddae7e1c 100644 --- a/msteams-platform/bots/how-to/create-a-bot-commands-menu.md +++ b/msteams-platform/bots/how-to/create-a-bot-commands-menu.md @@ -159,7 +159,7 @@ You must handle menu commands in your bot code as you handle any message from us ## Handle menu commands in your bot code -In the Teams SDK, incoming messages are routed through an activity handler. You register a message handler using `app.on('message', ...)` (TypeScript), `app.OnMessage(...)` (C#), or `@app.on_message` (Python), and the message text is available directly via `activity.text`. The SDK's activity router handles message delivery across all scopes (personal, group chat, and channel), so you don't need to manually parse or strip bot mentions from the message text. +In the Teams SDK, incoming messages are routed through an activity handler. You register a message handler using `app.on('message', ...)` (TypeScript), `app.OnMessage(...)` (C#), or `@app.on_message` (Python), and the message text is available via `activity.text`. The SDK's activity router handles message delivery across all scopes (personal, group chat, and channel). However, in group chat and channel conversations, `activity.text` can include the bot `@mention` (for example, `Bot Name`), so strip the bot mention before matching the command text, or use the activity's mention entities or an SDK helper for mention removal where available. > [!NOTE] > To handle the commands in code, they are sent to your bot as a regular message. You must handle them as you would handle any other message from your users. The commands in code insert pre-configured text into the text box. The user must then send that text as they do for any other message. From 5afa84c9c8422c650739f8d2957c585dce99f9bb Mon Sep 17 00:00:00 2001 From: v-nikitach Date: Mon, 6 Apr 2026 16:05:19 +0530 Subject: [PATCH 03/10] Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../bots/how-to/create-a-bot-commands-menu.md | 48 ++++++++++--------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/msteams-platform/bots/how-to/create-a-bot-commands-menu.md b/msteams-platform/bots/how-to/create-a-bot-commands-menu.md index d4eddae7e1c..b0647a15a5e 100644 --- a/msteams-platform/bots/how-to/create-a-bot-commands-menu.md +++ b/msteams-platform/bots/how-to/create-a-bot-commands-menu.md @@ -207,29 +207,33 @@ teamsApp.OnMessage(async context => // Get message text and normalize it var text = (context.Activity.Text ?? "").Trim().ToLower(); - // Handle mention me command - if (text.Contains("mentionme") || text.Contains("mention me")) - { - await MentionUser(context); - } - // Handle whoami command - else if (text.Contains("whoami")) - { - await GetSingleMember(context); - } - // Handle welcome command - else if (text.Contains("welcome")) - { - await SendWelcomeMessage(context); - } - // Echo greeting messages - else if (text.Contains("hi") || text.Contains("hello")) - { - await EchoMessage(context, text); - } - else + switch (text) { - await SendWelcomeMessage(context); + // Handle mention me command + case "mentionme": + case "mention me": + await MentionUser(context); + break; + + // Handle whoami command + case "whoami": + await GetSingleMember(context); + break; + + // Handle welcome command + case "welcome": + await SendWelcomeMessage(context); + break; + + // Echo greeting messages + case "hi": + case "hello": + await EchoMessage(context, text); + break; + + default: + await SendWelcomeMessage(context); + break; } }); From 7183f3b91940d71512af83b89b520455054308a9 Mon Sep 17 00:00:00 2001 From: v-nikitach Date: Mon, 6 Apr 2026 16:12:48 +0530 Subject: [PATCH 04/10] Update create-a-bot-commands-menu.md --- .../bots/how-to/create-a-bot-commands-menu.md | 77 +++++++++---------- 1 file changed, 38 insertions(+), 39 deletions(-) diff --git a/msteams-platform/bots/how-to/create-a-bot-commands-menu.md b/msteams-platform/bots/how-to/create-a-bot-commands-menu.md index b0647a15a5e..97ea93a070e 100644 --- a/msteams-platform/bots/how-to/create-a-bot-commands-menu.md +++ b/msteams-platform/bots/how-to/create-a-bot-commands-menu.md @@ -17,7 +17,7 @@ To define a set of core commands that your bot can respond to, you can add a com # [Desktop](#tab/desktop) -:::image type="content" source="conversations/Media/bot-menu-sample.png" alt-text="Bot-command-menu"::: +:::image type="content" source="conversations/Media/bot-menu-sample.png" alt-text="Desktop-bot-menu"::: # [Mobile](#tab/mobile) @@ -164,6 +164,9 @@ In the Teams SDK, incoming messages are routed through an activity handler. You > [!NOTE] > To handle the commands in code, they are sent to your bot as a regular message. You must handle them as you would handle any other message from your users. The commands in code insert pre-configured text into the text box. The user must then send that text as they do for any other message. +> [!IMPORTANT] +> When routing messages based on command text, use exact (whole-word) matching instead of substring checks. For example, `text.Contains("hi")` in C# or `text.includes('hi')` in TypeScript also matches unrelated words like "this" or "thinking", which can route messages unexpectedly. Since command menus insert the exact command string into the compose box, use equality operators such as `==` (C#, Python) or `===` (TypeScript) to compare the normalized message text against each command. + # [C#](#tab/dotnet) * [Sample code reference](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/abc97268bf41536509383283114c3a33684f0568/samples/bot-quickstart/dotnet/bot-quickstart) @@ -207,33 +210,29 @@ teamsApp.OnMessage(async context => // Get message text and normalize it var text = (context.Activity.Text ?? "").Trim().ToLower(); - switch (text) + // Handle mention me command - use exact matching to avoid false positives from substrings + if (text == "mentionme" || text == "mention me") + { + await MentionUser(context); + } + // Handle whoami command + else if (text == "whoami") + { + await GetSingleMember(context); + } + // Handle welcome command + else if (text == "welcome") + { + await SendWelcomeMessage(context); + } + // Echo greeting messages + else if (text == "hi" || text == "hello") + { + await EchoMessage(context, text); + } + else { - // Handle mention me command - case "mentionme": - case "mention me": - await MentionUser(context); - break; - - // Handle whoami command - case "whoami": - await GetSingleMember(context); - break; - - // Handle welcome command - case "welcome": - await SendWelcomeMessage(context); - break; - - // Echo greeting messages - case "hi": - case "hello": - await EchoMessage(context, text); - break; - - default: - await SendWelcomeMessage(context); - break; + await SendWelcomeMessage(context); } }); @@ -246,7 +245,7 @@ async Task SendWelcomeMessage(IContext context) where T : IActivity // Echo back the user's message async Task EchoMessage(IContext context, string text) { - await context.Send($"**Echo :** {text}"); + await context.Send($"**Echo:** {text}"); } // Retrieves and displays information about the current user @@ -275,7 +274,7 @@ webApp.Run(); * [Sample code reference](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/abc97268bf41536509383283114c3a33684f0568/samples/bot-quickstart/nodejs/bot-quickstart) -```javascript +```typescript // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. @@ -307,20 +306,20 @@ app.on('message', async (context) => { const messageActivity = activity as IMessageActivity; let text = (messageActivity.text || '').trim().toLowerCase(); - // Handle mention me command - if (text.includes('mentionme') || text.includes('mention me')) { + // Handle mention me command - use exact matching to avoid false positives from substrings + if (text === 'mentionme' || text === 'mention me') { await mentionUser(context); } // Handle whoami command - else if (text.includes('whoami')) { + else if (text === 'whoami') { await getSingleMember(context); } // Handle welcome command - else if (text.includes('welcome')) { + else if (text === 'welcome') { await sendWelcomeMessage(context); } // Handle greeting messages - else if (text.includes('hi') || text.includes('hello')) { + else if (text === 'hi' || text === 'hello') { await echoMessage(context, text); } // Default: echo back any other message @@ -489,17 +488,17 @@ async def handle_message(ctx: ActivityContext[MessageActivity]) -> None: # Get message text and normalize it text = (ctx.activity.text or "").strip().lower() - # Handle mention me command - if "mentionme" in text or "mention me" in text: + # Handle mention me command - use exact matching to avoid false positives from substrings + if text in ("mentionme", "mention me"): await mention_user(ctx) # Handle whoami command - elif "whoami" in text: + elif text == "whoami": await get_single_member(ctx) # Handle welcome command - elif 'welcome' in text: + elif text == "welcome": await send_welcome_message(ctx) # Handle hi/hello - echo back - elif "hi" in text or "hello" in text: + elif text in ("hi", "hello"): await echo_message(ctx, text) From 787a4ea88b8c432fbe582265208f27e5b01e3758 Mon Sep 17 00:00:00 2001 From: v-nikitach Date: Mon, 6 Apr 2026 16:28:15 +0530 Subject: [PATCH 05/10] Uploaded new image --- .../conversations/Media/bot-menu-sample.png | Bin 22463 -> 26380 bytes .../bots/how-to/create-a-bot-commands-menu.md | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/msteams-platform/bots/how-to/conversations/Media/bot-menu-sample.png b/msteams-platform/bots/how-to/conversations/Media/bot-menu-sample.png index 077e26a30b3e3a70042fc8fefe2534731c5b27f1..fc556488b0ae877c411c04863360c2104c907c3e 100644 GIT binary patch literal 26380 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 aQb?m`3gIoa2VPclO8>6Oo$6bTQU41PeS-l2 literal 22463 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 diff --git a/msteams-platform/bots/how-to/create-a-bot-commands-menu.md b/msteams-platform/bots/how-to/create-a-bot-commands-menu.md index 97ea93a070e..4a54c5f8079 100644 --- a/msteams-platform/bots/how-to/create-a-bot-commands-menu.md +++ b/msteams-platform/bots/how-to/create-a-bot-commands-menu.md @@ -17,7 +17,7 @@ To define a set of core commands that your bot can respond to, you can add a com # [Desktop](#tab/desktop) -:::image type="content" source="conversations/Media/bot-menu-sample.png" alt-text="Desktop-bot-menu"::: +:::image type="content" source="conversations/Media/bot-menu-sample.png" alt-text="Desktop-menu-sample"::: # [Mobile](#tab/mobile) From b749666089c2f858962e404553a4d694161f6dd8 Mon Sep 17 00:00:00 2001 From: v-nikitach Date: Thu, 9 Apr 2026 16:38:44 +0530 Subject: [PATCH 06/10] Update create-a-bot-commands-menu.md --- .../bots/how-to/create-a-bot-commands-menu.md | 246 +----------------- 1 file changed, 4 insertions(+), 242 deletions(-) diff --git a/msteams-platform/bots/how-to/create-a-bot-commands-menu.md b/msteams-platform/bots/how-to/create-a-bot-commands-menu.md index 4a54c5f8079..473fbd19ca3 100644 --- a/msteams-platform/bots/how-to/create-a-bot-commands-menu.md +++ b/msteams-platform/bots/how-to/create-a-bot-commands-menu.md @@ -5,7 +5,7 @@ ms.topic: how-to ms.localizationpriority: medium ms.author: anclear ms.owner: ginobuzz -ms.date: 04/03/2026 +ms.date: 04/09/2026 --- # Create a commands menu @@ -169,41 +169,9 @@ In the Teams SDK, incoming messages are routed through an activity handler. You # [C#](#tab/dotnet) -* [Sample code reference](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/abc97268bf41536509383283114c3a33684f0568/samples/bot-quickstart/dotnet/bot-quickstart) +* [Sample code reference](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/TeamsSDK/bot-quickstart/dotnet/bot-quickstart) ```csharp -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using Microsoft.Teams.Plugins.AspNetCore.Extensions; -using Microsoft.Teams.Apps; -using Microsoft.Teams.Apps.Activities; -using Microsoft.Teams.Api.Activities; -using Microsoft.Teams.Api.Clients; - -// Initialize Teams App - automatically uses CLIENT_ID and CLIENT_SECRET from environment variables -var builder = WebApplication.CreateBuilder(args); -builder.AddTeams(); -var webApp = builder.Build(); -var teamsApp = webApp.UseTeams(true); - -// Handle conversation update events (when bot is added or members join) -teamsApp.OnConversationUpdate(async context => -{ - var membersAdded = context.Activity.MembersAdded; - if (membersAdded != null) - { - foreach (var member in membersAdded) - { - // Check if bot was added to the conversation - if (member.Id == context.Activity.Recipient?.Id) - { - await SendWelcomeMessage(context); - } - } - } -}); - // Handles incoming messages and routes to appropriate functions based on message content teamsApp.OnMessage(async context => { @@ -236,68 +204,13 @@ teamsApp.OnMessage(async context => } }); -// Sends a welcome message -async Task SendWelcomeMessage(IContext context) where T : IActivity -{ - await context.Send("Welcome to the Teams Quickstart Bot!"); -} - -// Echo back the user's message -async Task EchoMessage(IContext context, string text) -{ - await context.Send($"**Echo:** {text}"); -} - -// Retrieves and displays information about the current user -async Task GetSingleMember(IContext context) -{ - await context.Send($"You are: {context.Activity.From.Name}"); -} - -// Mention a user in a message -async Task MentionUser(IContext context) -{ - var member = context.Activity.From; - var mentionText = $"{member.Name}"; - var activity = new MessageActivity() - .WithText($"Hello {mentionText}") - .AddMention(member, addText: false); - - await context.Send(activity); -} - -// Starts the Teams bot application and listens for incoming requests -webApp.Run(); ``` # [TypeScript](#tab/typescript) -* [Sample code reference](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/abc97268bf41536509383283114c3a33684f0568/samples/bot-quickstart/nodejs/bot-quickstart) +* [Sample code reference](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/TeamsSDK/bot-quickstart/nodejs/bot-quickstart) ```typescript -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -import { App, IActivityContext } from '@microsoft/teams.apps'; -import { TeamsChannelAccount, IMessageActivity } from '@microsoft/teams.api'; - -// Initialize Teams App - automatically uses CLIENT_ID and CLIENT_SECRET from environment variables -// Note: .env file is only required when running on Teams (not needed for local development with devtools) -const app = new App(); - -// Handle conversation update events (when bot is added or members join) -app.on('conversationUpdate', async (context) => { - const { activity } = context; - const membersAdded = (activity as any).membersAdded || []; - - for (const member of membersAdded) { - // Check if bot was added to the conversation - if (member.id === activity.recipient.id) { - await sendWelcomeMessage(context); - } - } -}); - // Handles incoming messages and routes to appropriate functions based on message content app.on('message', async (context) => { const { activity } = context; @@ -328,160 +241,13 @@ app.on('message', async (context) => { } }); -// Sends a welcome message -async function sendWelcomeMessage(context: IActivityContext): Promise { - await context.send({ - type: 'message', - text: 'Welcome to the Teams Quickstart Bot!' - }); -} - -// Echo back the user's message -async function echoMessage(context: IActivityContext, text: string): Promise { - await context.send({ - type: 'message', - text: `**Echo:** ${text}` - }); -} - -// Retrieves and displays information about the current user -async function getSingleMember(context: IActivityContext): Promise { - const { activity } = context; - const conversationId = activity.conversation.id; - const userId = activity.from.id; - - try { - const member: TeamsChannelAccount = await context.api.conversations.members(conversationId).getById(userId); - await context.send({ - type: 'message', - text: `You are: ${member.name}` - }); - } catch (error) { - console.error('Error getting member:', error); - } -} - -// Mention a user in a message -async function mentionUser(context: IActivityContext): Promise { - const { activity } = context; - const conversationId = activity.conversation.id; - const userId = activity.from.id; - - try { - const member: TeamsChannelAccount = await context.api.conversations.members(conversationId).getById(userId); - - // Create a text message with user mention - const mentionText = `${member.name}`; - await context.send({ - type: 'message', - text: `Hello ${mentionText}`, - entities: [ - { - type: 'mention', - text: mentionText, - mentioned: { - id: userId, - name: member.name, - role: 'user' - } - } - ] - }); - } catch (error) { - console.error('Error mentioning user:', error); - } -} - -// Starts the Teams bot application and listens for incoming requests -app.start().catch(console.error); ``` # [Python](#tab/python) -* [Sample code reference](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/abc97268bf41536509383283114c3a33684f0568/samples/bot-quickstart/python/bot-quickstart) +* [Sample code reference](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/TeamsSDK/bot-quickstart/python/bot-quickstart) ```python -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. - -import asyncio - -from dotenv import load_dotenv -from microsoft_teams.api import MessageActivity, MessageActivityInput -from microsoft_teams.apps import ActivityContext, App - -# Load environment variables -load_dotenv() - -# Initialize Teams App - automatically uses CLIENT_ID and CLIENT_SECRET from environment variables -# Note: .env file is only required when running on Teams (not needed for local development with devtools) -app = App() - -async def send_welcome_message(ctx: ActivityContext) -> None: - """Sends a welcome message with available commands.""" - welcome_message = ( - "Welcome to the Teams Quickstart Bot!" - ) - await ctx.send(MessageActivityInput(text=welcome_message)) - - -async def echo_message(ctx: ActivityContext, text: str) -> None: - """Echo back the user's message.""" - await ctx.send(MessageActivityInput(text=f"**Echo:** {text}")) - - -async def get_single_member(ctx: ActivityContext[MessageActivity]) -> None: - """Retrieves and displays information about the current user.""" - try: - conversationId = ctx.activity.conversation.id - userId = ctx.activity.from_.id - user = await ctx.api.conversations.members(conversationId).get(userId) - await ctx.send(MessageActivityInput(text=f"You are: {user.name}")) - except Exception as error: - print(f"Error getting member: {error}") - - -async def mention_user(ctx: ActivityContext[MessageActivity]) -> None: - """Mention a user in a message.""" - try: - - conversationId = ctx.activity.conversation.id - userId = ctx.activity.from_.id - - # Get user info directly from the activity - user = await ctx.api.conversations.members(conversationId).get(userId) - - # Create a text message with user mention - mention_text = f"{user.name}" - await ctx.send(MessageActivityInput( - text=f"Hello {mention_text}", - entities=[ - { - "type": "mention", - "text": mention_text, - "mentioned": { - "id": userId, - "name": user.name, - "role": "user" - } - } - ] - )) - except Exception as error: - print(f"Error mentioning user: {error}") - - -@app.on_conversation_update -async def handle_conversation_update(ctx: ActivityContext) -> None: - """Handle conversation update events (when bot is added or members join).""" - members_added = getattr(ctx.activity, 'members_added', []) - - for member in members_added: - # Check if bot was added to the conversation - if member.id == ctx.activity.recipient.id: - await send_welcome_message(ctx) - - @app.on_message async def handle_message(ctx: ActivityContext[MessageActivity]) -> None: """Handles incoming messages and routes to appropriate functions based on message content.""" @@ -501,10 +267,6 @@ async def handle_message(ctx: ActivityContext[MessageActivity]) -> None: elif text in ("hi", "hello"): await echo_message(ctx, text) - -# Starts the Teams bot application and listens for incoming requests -if __name__ == "__main__": - asyncio.run(app.start()) ``` * * * From c600a1b3a363b2e4bbf344a46d85cbc2b9dbd8fc Mon Sep 17 00:00:00 2001 From: v-nikitach Date: Mon, 13 Apr 2026 13:12:00 +0530 Subject: [PATCH 07/10] Update create-a-bot-commands-menu.md --- msteams-platform/bots/how-to/create-a-bot-commands-menu.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/msteams-platform/bots/how-to/create-a-bot-commands-menu.md b/msteams-platform/bots/how-to/create-a-bot-commands-menu.md index 473fbd19ca3..31046882bb9 100644 --- a/msteams-platform/bots/how-to/create-a-bot-commands-menu.md +++ b/msteams-platform/bots/how-to/create-a-bot-commands-menu.md @@ -5,7 +5,7 @@ ms.topic: how-to ms.localizationpriority: medium ms.author: anclear ms.owner: ginobuzz -ms.date: 04/09/2026 +ms.date: 04/13/2026 --- # Create a commands menu @@ -164,9 +164,6 @@ In the Teams SDK, incoming messages are routed through an activity handler. You > [!NOTE] > To handle the commands in code, they are sent to your bot as a regular message. You must handle them as you would handle any other message from your users. The commands in code insert pre-configured text into the text box. The user must then send that text as they do for any other message. -> [!IMPORTANT] -> When routing messages based on command text, use exact (whole-word) matching instead of substring checks. For example, `text.Contains("hi")` in C# or `text.includes('hi')` in TypeScript also matches unrelated words like "this" or "thinking", which can route messages unexpectedly. Since command menus insert the exact command string into the compose box, use equality operators such as `==` (C#, Python) or `===` (TypeScript) to compare the normalized message text against each command. - # [C#](#tab/dotnet) * [Sample code reference](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/TeamsSDK/bot-quickstart/dotnet/bot-quickstart) From 6457170345ac00858c1c7c6bcd275bb905b1453c Mon Sep 17 00:00:00 2001 From: v-nikitach Date: Fri, 24 Apr 2026 11:38:36 +0530 Subject: [PATCH 08/10] Update create-a-bot-commands-menu.md --- .../bots/how-to/create-a-bot-commands-menu.md | 61 +++++-------------- 1 file changed, 14 insertions(+), 47 deletions(-) diff --git a/msteams-platform/bots/how-to/create-a-bot-commands-menu.md b/msteams-platform/bots/how-to/create-a-bot-commands-menu.md index 31046882bb9..872cfe0f7cc 100644 --- a/msteams-platform/bots/how-to/create-a-bot-commands-menu.md +++ b/msteams-platform/bots/how-to/create-a-bot-commands-menu.md @@ -5,7 +5,7 @@ ms.topic: how-to ms.localizationpriority: medium ms.author: anclear ms.owner: ginobuzz -ms.date: 04/13/2026 +ms.date: 04/24/2026 --- # Create a commands menu @@ -168,6 +168,8 @@ In the Teams SDK, incoming messages are routed through an activity handler. You * [Sample code reference](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/TeamsSDK/bot-quickstart/dotnet/bot-quickstart) +In C#, Teams SDK does not feature a method to remove **\@Mention** portion. You can refer to the code snippet below on how to handle commands in your bot. + ```csharp // Handles incoming messages and routes to appropriate functions based on message content teamsApp.OnMessage(async context => @@ -207,36 +209,13 @@ teamsApp.OnMessage(async context => * [Sample code reference](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/TeamsSDK/bot-quickstart/nodejs/bot-quickstart) -```typescript -// Handles incoming messages and routes to appropriate functions based on message content -app.on('message', async (context) => { - const { activity } = context; +You can parse out the **\@Mention** portion of the message text using a static method provided with Teams SDK. It's a method of the `TurnContext` class named `stripMentionsText`. - // Get message text and normalize it - const messageActivity = activity as IMessageActivity; - let text = (messageActivity.text || '').trim().toLowerCase(); +The TypeScript code to parse out the **\@Mention** portion of the message text is as follows: - // Handle mention me command - use exact matching to avoid false positives from substrings - if (text === 'mentionme' || text === 'mention me') { - await mentionUser(context); - } - // Handle whoami command - else if (text === 'whoami') { - await getSingleMember(context); - } - // Handle welcome command - else if (text === 'welcome') { - await sendWelcomeMessage(context); - } - // Handle greeting messages - else if (text === 'hi' || text === 'hello') { - await echoMessage(context, text); - } - // Default: echo back any other message - else if (text) { - await echoMessage(context, text); - } -}); +```typescript +// Remove mention text from Text property, this function is altering the text on the Activity. +const text = context.activity.stripMentionsText().text.trim().toLowerCase(); ``` @@ -244,25 +223,13 @@ app.on('message', async (context) => { * [Sample code reference](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/TeamsSDK/bot-quickstart/python/bot-quickstart) +You can parse out the **@Mention** portion of the message text using a static method provided with Teams SDK. It's a method of the `TurnContext` class named `strip_mentions_text`. + +The Python code to parse out the **\@Mention** portion of the message text is as follows: + ```python -@app.on_message -async def handle_message(ctx: ActivityContext[MessageActivity]) -> None: - """Handles incoming messages and routes to appropriate functions based on message content.""" - # Get message text and normalize it - text = (ctx.activity.text or "").strip().lower() - - # Handle mention me command - use exact matching to avoid false positives from substrings - if text in ("mentionme", "mention me"): - await mention_user(ctx) - # Handle whoami command - elif text == "whoami": - await get_single_member(ctx) - # Handle welcome command - elif text == "welcome": - await send_welcome_message(ctx) - # Handle hi/hello - echo back - elif text in ("hi", "hello"): - await echo_message(ctx, text) +# Remove recipient mention text from Text property, this function is altering the text on the Activity. +text = context.activity.strip_mentions_text().text. Strip().lower() ``` From 3a12decd447c45c0d3a9d220a4e1b298e7d0c4f8 Mon Sep 17 00:00:00 2001 From: v-nikitach Date: Tue, 28 Apr 2026 16:41:45 +0530 Subject: [PATCH 09/10] Update create-a-bot-commands-menu.md --- msteams-platform/bots/how-to/create-a-bot-commands-menu.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/msteams-platform/bots/how-to/create-a-bot-commands-menu.md b/msteams-platform/bots/how-to/create-a-bot-commands-menu.md index 872cfe0f7cc..f242e4b24c6 100644 --- a/msteams-platform/bots/how-to/create-a-bot-commands-menu.md +++ b/msteams-platform/bots/how-to/create-a-bot-commands-menu.md @@ -28,7 +28,7 @@ To define a set of core commands that your bot can respond to, you can add a com ## Create a command menu for your bot > [!NOTE] -> It's recommended that you create a command bot by following the [Teams SDK quickstart](/microsoftteams/platform/teams-sdk/getting-started/quickstart) and reviewing the [code basics](/microsoftteams/platform/teams-sdk/getting-started/code-basics). For more information about Microsoft 365 Agents Toolkit (previously known as Teams Toolkit), see [Agents Toolkit overview for Visual Studio Code](../../toolkit/agents-toolkit-fundamentals.md) and [Agents Toolkit overview for Visual Studio](../../toolkit/toolkit-v4/agents-toolkit-fundamentals-vs.md). +> We recommend creating a command bot by following the [Teams SDK quickstart](/microsoftteams/platform/teams-sdk/getting-started/quickstart) and reviewing the [code basics](/microsoftteams/platform/teams-sdk/getting-started/code-basics). For more information about Microsoft 365 Agents Toolkit (previously known as Teams Toolkit), see [Agents Toolkit overview for Visual Studio Code](../../toolkit/agents-toolkit-fundamentals.md) and [Agents Toolkit overview for Visual Studio](../../toolkit/toolkit-v4/agents-toolkit-fundamentals-vs.md). ### Create a command menu for your bot using Developer Portal @@ -162,7 +162,7 @@ You must handle menu commands in your bot code as you handle any message from us In the Teams SDK, incoming messages are routed through an activity handler. You register a message handler using `app.on('message', ...)` (TypeScript), `app.OnMessage(...)` (C#), or `@app.on_message` (Python), and the message text is available via `activity.text`. The SDK's activity router handles message delivery across all scopes (personal, group chat, and channel). However, in group chat and channel conversations, `activity.text` can include the bot `@mention` (for example, `Bot Name`), so strip the bot mention before matching the command text, or use the activity's mention entities or an SDK helper for mention removal where available. > [!NOTE] -> To handle the commands in code, they are sent to your bot as a regular message. You must handle them as you would handle any other message from your users. The commands in code insert pre-configured text into the text box. The user must then send that text as they do for any other message. +> To handle the commands in code, they're sent to your bot as a regular message. Handle them as you would any other message from your users. The commands insert pre-configured text into the text box. After that, the user sends the text as they do for any other message. # [C#](#tab/dotnet) From 751ec612f9c643ab07b844e64a75becdb3471e4c Mon Sep 17 00:00:00 2001 From: v-nikitach Date: Tue, 28 Apr 2026 16:42:11 +0530 Subject: [PATCH 10/10] Update create-a-bot-commands-menu.md --- msteams-platform/bots/how-to/create-a-bot-commands-menu.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msteams-platform/bots/how-to/create-a-bot-commands-menu.md b/msteams-platform/bots/how-to/create-a-bot-commands-menu.md index f242e4b24c6..e62b1c16a5f 100644 --- a/msteams-platform/bots/how-to/create-a-bot-commands-menu.md +++ b/msteams-platform/bots/how-to/create-a-bot-commands-menu.md @@ -5,7 +5,7 @@ ms.topic: how-to ms.localizationpriority: medium ms.author: anclear ms.owner: ginobuzz -ms.date: 04/24/2026 +ms.date: 04/28/2026 --- # Create a commands menu