From d8b9b2478d91e98335ebbfe8d7f186dfaf4bbfeb Mon Sep 17 00:00:00 2001 From: "docsautomation[bot]" <198554515+docsautomation[bot]@users.noreply.github.com> Date: Mon, 12 May 2025 06:41:49 +0000 Subject: [PATCH] Update msteams-platform/bots/how-to/teams-conversational-ai/how-conversation-ai-core-capabilities.md by gourimicrosoft --- .../how-conversation-ai-core-capabilities.md | 573 +++++++++--------- 1 file changed, 271 insertions(+), 302 deletions(-) diff --git a/msteams-platform/bots/how-to/teams-conversational-ai/how-conversation-ai-core-capabilities.md b/msteams-platform/bots/how-to/teams-conversational-ai/how-conversation-ai-core-capabilities.md index 375b2976bc2..4373eecd98a 100644 --- a/msteams-platform/bots/how-to/teams-conversational-ai/how-conversation-ai-core-capabilities.md +++ b/msteams-platform/bots/how-to/teams-conversational-ai/how-conversation-ai-core-capabilities.md @@ -8,19 +8,20 @@ ms.date: 02/26/2025 ms.owner: angovil --- -# Understand Teams AI library +# Understand Teams AI Library -Teams AI library supports JavaScript and simplifies building bots that can interact with Microsoft Teams. It also facilitates the migration of existing bots to use AI-powered features. It supports migrating messaging, message extension, and Adaptive Cards capabilities to the new format. You can also upgrade your existing Teams apps with these features. +Teams AI library supports JavaScript and simplifies building bots that interact with Microsoft Teams. It also facilitates migrating existing bots to leverage AI-powered features. The library supports transitioning messaging, message extension, and Adaptive Cards capabilities to a modern format so that you can upgrade your existing Teams apps effortlessly. -Earlier, you used the BotBuilder SDK to create bots for Teams. Teams AI library is designed to make this process easier and includes AI support. Initially, you might upgrade your bot without AI, but after upgrading, it can connect to AI or Large Language Models (LLMs) available in the AI library. +Previously, you used the BotBuilder SDK to create bots for Teams. The Teams AI library is designed to ease this process while integrating AI support. Initially, you might upgrade your bot without AI, but later you can connect it to AI or Large Language Models (LLMs) available in the library. With Teams AI library, you can focus on: - - Understanding the role of [activity handler](#activity-handlers) in conversation management. - Designing [bot logic](#bot-logic-for-handling-an-action) for intelligent responses. - Integrating Natural Language Processing (NLP) for translating user [intents to actions](#intents-to-actions). -## Activity handlers +--- + +## Activity Handlers Teams AI library supports the following activity handlers: @@ -28,32 +29,32 @@ Teams AI library supports the following activity handlers: - [Message extension (ME) capabilities](#message-extensions) - [Adaptive Cards capabilities](#adaptive-cards-capabilities) - You need to use the AI library to scaffold bot and Adaptive Card handlers to the source file. In the subsequent sections, we've used the samples from the [AI library](https://github.com/microsoft/teams-ai/tree/main) to explain each capability and the path to migration. +You need to use the AI library to scaffold bot and Adaptive Card handlers in the source file. In the subsequent sections, samples from the [AI library](https://github.com/microsoft/teams-ai/tree/main) explain each capability and the migration path. + +--- -### Send or receive message +### Send or Receive Message -You can send and receive messages using the Bot Framework. The app listens for user messages, deletes the conversation state upon receipt, and replies. It also tracks the number of messages in a conversation and echoes back the user's message with the count. +This section shows how to send and receive messages using the Bot Framework. The bot listens for user messages, resets the conversation state when receiving a specific command, and echoes back the user's message with a message count. -# [.NET](#tab/dotnet6) +#### .NET Example - [Code sample](https://github.com/microsoft/teams-ai/tree/main/dotnet/samples/01.messaging.echoBot) - - [Sample code reference](https://github.com/microsoft/teams-ai/blob/main/dotnet/samples/01.messaging.echoBot/Program.cs#L49) ```csharp - // Listen for user to say "/reset" and then delete conversation state - app.OnMessage("/reset", ActivityHandlers.ResetMessageHandler); +// Listen for user to say "/reset" and then delete conversation state +app.OnMessage("/reset", ActivityHandlers.ResetMessageHandler); - // Listen for ANY message to be received. MUST BE AFTER ANY OTHER MESSAGE HANDLERS - app.OnActivity(ActivityTypes.Message, ActivityHandlers.MessageHandler); +// Listen for ANY message to be received. MUST BE AFTER ANY OTHER MESSAGE HANDLERS +app.OnActivity(ActivityTypes.Message, ActivityHandlers.MessageHandler); - return app; +return app; ``` -# [JavaScript](#tab/javascript6) +#### JavaScript Example - [Code sample](https://github.com/microsoft/teams-ai/tree/main/js/samples/01.getting-started/a.echoBot) - - [Sample code reference](https://github.com/microsoft/teams-ai/blob/main/js/samples/01.getting-started/a.echoBot/src/index.ts#L74) ```typescript @@ -69,15 +70,14 @@ app.activity(ActivityTypes.Message, async (context: TurnContext, state: Applicat let count = state.conversation.count ?? 0; state.conversation.count = ++count; - // Echo back users request + // Echo back user's request with the current count await context.sendActivity(`[${count}] you said: ${context.activity.text}`); }); ``` -# [Python](#tab/python6) +#### Python Example - [Code sample](https://github.com/microsoft/teams-ai/tree/main/python/samples/01.messaging.a.echoBot) - - [Sample code reference](https://github.com/microsoft/teams-ai/blob/main/python/samples/01.messaging.a.echoBot/src/bot.py#L25) ```python @@ -89,69 +89,64 @@ async def on_message(context: TurnContext, _state: TurnState): --- -### Message extensions +### Message Extensions -In the Bot Framework SDK's `TeamsActivityHandler`, set up the Message extensions query handler by extending handler methods. The app listens for search actions and item taps. It formats search results as Hero Cards displaying package information, and displays them in the messaging extension. +This section demonstrates how to handle message extension queries using the Bot Framework SDK's `TeamsActivityHandler`. The app listens for search actions and item taps. It formats search results as Hero Cards displaying package information, returning them in the messaging extension. -# [.NET](#tab/dotnet5) +#### .NET Example - [Code sample](https://github.com/microsoft/teams-ai/tree/main/dotnet/samples/02.messageExtensions.a.searchCommand) - - [Sample code reference](https://github.com/microsoft/teams-ai/blob/main/dotnet/samples/02.messageExtensions.a.searchCommand/Program.cs#L47) - - [Search results reference](https://github.com/microsoft/teams-ai/blob/main/dotnet/samples/02.messageExtensions.a.searchCommand/ActivityHandlers.cs#L39) ```csharp // Listen for search actions - app.MessageExtensions.OnQuery("searchCmd", activityHandlers.QueryHandler); - // Listen for item tap - app.MessageExtensions.OnSelectItem(activityHandlers.SelectItemHandler); - - return app; +app.MessageExtensions.OnQuery("searchCmd", activityHandlers.QueryHandler); +// Listen for item tap +app.MessageExtensions.OnSelectItem(activityHandlers.SelectItemHandler); - // Format search results in ActivityHandlers.cs +return app; - List attachments = packages.Select(package => new MessagingExtensionAttachment - { - ContentType = HeroCard.ContentType, - Content = new HeroCard - { - Title = package.Id, - Text = package.Description - }, - Preview = new HeroCard - { - Title = package.Id, - Text = package.Description, - Tap = new CardAction - { - Type = "invoke", - Value = package - } - }.ToAttachment() - }).ToList(); - - // Return results as a list - - return new MessagingExtensionResult - { - Type = "result", - AttachmentLayout = "list", - Attachments = attachments - }; +// Format search results in ActivityHandlers.cs +List attachments = packages.Select(package => new MessagingExtensionAttachment +{ + ContentType = HeroCard.ContentType, + Content = new HeroCard + { + Title = package.Id, + Text = package.Description + }, + Preview = new HeroCard + { + Title = package.Id, + Text = package.Description, + Tap = new CardAction + { + Type = "invoke", + Value = package + } + }.ToAttachment() +}).ToList(); +// Return results as a list +return new MessagingExtensionResult +{ + Type = "result", + AttachmentLayout = "list", + Attachments = attachments +}; ``` -# [JavaScript](#tab/javascript5) +#### JavaScript Example -The app class has `messageExtensions` features to simplify creating the handlers: +This sample illustrates setting up a message extension using the `messageExtensions` features provided by the application class. -- `context`: `TurnContext` -- `state`: `TurnState` -- `query`: The data passed from message extension interaction +- Parameters explained: + - `context`: TurnContext + - `state`: TurnState + - `query`: The data passed from the message extension interaction - [Code sample](https://github.com/microsoft/teams-ai/tree/main/js/samples/02.teams-features/a.messageExtensions.searchCommand) - - [Sample code reference](https://github.com/microsoft/teams-ai/blob/main/js/samples/02.teams-features/a.messageExtensions.searchCommand/src/index.ts#L79) ```javascript @@ -183,14 +178,14 @@ app.messageExtensions.query('searchCmd', async (context: TurnContext, state: Tur }); ``` -Similarly, `selectItem` listener would be set up as: +Similarly, the `selectItem` listener handles an item tap event: ```typescript app.messageExtensions.selectItem(async (context: TurnContext, state: TurnState, item) => { - // Generate detailed result + // Generate detailed result card based on the selected item const card = createNpmPackageCard(item); - // Return results + // Return the detailed result as a list with a single attachment return { attachmentLayout: 'list', attachments: [card], @@ -199,10 +194,9 @@ app.messageExtensions.selectItem(async (context: TurnContext, state: TurnState, }); ``` -# [Python](#tab/python5) +#### Python Example - [Code sample](https://github.com/microsoft/teams-ai/tree/main/python/samples/02.messageExtensions.a.searchCommand) - - [Sample code reference](https://github.com/microsoft/teams-ai/blob/main/python/samples/02.messageExtensions.a.searchCommand/src/bot.py#L44) ```python @@ -233,41 +227,46 @@ async def search_command( return MessagingExtensionResult( attachment_layout="list", attachments=results, type="result" ) + + +# Listen for item tap +@app.message_extensions.select_item() +async def select_item(_context: TurnContext, _state: AppTurnState, item: Any): + card = create_npm_package_card(item) + return MessagingExtensionResult(attachment_layout="list", attachments=[card], type="result") ``` --- -### Adaptive Cards capabilities +### Adaptive Cards Capabilities -Register Adaptive Card action handlers using the `app.adaptiveCards` property. The app listens for messages with `static` or `dynamic` keywords and returns an Adaptive Card using `StaticMessageHandler()` or `DynamicMessageHandler()`. It also listens for queries from a dynamic search card and submit buttons. +Register Adaptive Card action handlers using the `app.adaptiveCards` property. The app listens for messages with keywords like `static` or `dynamic` and returns an Adaptive Card using respective handlers. Additionally, it listens for dynamic search queries and submit buttons from Adaptive Cards. -# [.NET](#tab/dotnet4) +#### .NET Example - [Code sample](https://github.com/microsoft/teams-ai/tree/main/dotnet/samples/03.adaptiveCards.a.typeAheadBot) - - [Sample code reference](https://github.com/microsoft/teams-ai/blob/main/dotnet/samples/03.adaptiveCards.a.typeAheadBot/Program.cs#L52) ```csharp // Listen for messages that trigger returning an Adaptive Card - app.OnMessage(new Regex(@"static", RegexOptions.IgnoreCase), activityHandlers.StaticMessageHandler); - app.OnMessage(new Regex(@"dynamic", RegexOptions.IgnoreCase), activityHandlers.DynamicMessageHandler); +app.OnMessage(new Regex(@"static", RegexOptions.IgnoreCase), activityHandlers.StaticMessageHandler); +app.OnMessage(new Regex(@"dynamic", RegexOptions.IgnoreCase), activityHandlers.DynamicMessageHandler); - // Listen for query from dynamic search card - app.AdaptiveCards.OnSearch("nugetpackages", activityHandlers.SearchHandler); - // Listen for submit buttons - app.AdaptiveCards.OnActionSubmit("StaticSubmit", activityHandlers.StaticSubmitHandler); - app.AdaptiveCards.OnActionSubmit("DynamicSubmit", activityHandlers.DynamicSubmitHandler); +// Listen for query from dynamic search card +app.AdaptiveCards.OnSearch("nugetpackages", activityHandlers.SearchHandler); +// Listen for submit buttons from Adaptive Cards +app.AdaptiveCards.OnActionSubmit("StaticSubmit", activityHandlers.StaticSubmitHandler); +app.AdaptiveCards.OnActionSubmit("DynamicSubmit", activityHandlers.DynamicSubmitHandler); - // Listen for ANY message to be received. MUST BE AFTER ANY OTHER HANDLERS - app.OnActivity(ActivityTypes.Message, activityHandlers.MessageHandler); +// Listen for ANY message to be received. MUST BE AFTER ANY OTHER HANDLERS +app.OnActivity(ActivityTypes.Message, activityHandlers.MessageHandler); - return app; +return app; ``` -# [JavaScript](#tab/javascript4) +#### JavaScript Example - [Code sample](https://github.com/microsoft/teams-ai/tree/main/js/samples/02.teams-features/b.adaptiveCards.typeAheadBot) - - [Sample code reference](https://github.com/microsoft/teams-ai/blob/main/js/samples/02.teams-features/b.adaptiveCards.typeAheadBot/src/index.ts#L86) ```javascript @@ -288,7 +287,7 @@ interface SubmitData { choiceSelect?: string; } -// Listen for submit buttons +// Listen for submit buttons from Adaptive Cards app.adaptiveCards.actionSubmit('DynamicSubmit', async (context, _state, data: SubmitData) => { await context.sendActivity(`Dynamically selected option is: ${data.choiceSelect}`); }); @@ -298,10 +297,9 @@ app.adaptiveCards.actionSubmit('StaticSubmit', async (context, _state, data: Sub }); ``` -# [Python](#tab/python4) +#### Python Example - [Code sample](https://github.com/microsoft/teams-ai/tree/main/python/samples/03.adaptiveCards.a.typeAheadBot) - - [Sample code reference](https://github.com/microsoft/teams-ai/blob/main/python/samples/03.adaptiveCards.a.typeAheadBot/src/bot.py#L39C1-L78C1) ```python @@ -328,22 +326,18 @@ async def dynamic_card(context: TurnContext, _state: AppTurnState) -> bool: --- -## Bot logic for handling an action +### Bot Logic for Handling an Action -The bot responds to the user's input with the action `LightsOn` to turn the lights on. +This section demonstrates how the bot responds to user actions. For example, when the AI prompt instructs an action like `LightsOn` or `LightsOff`, the bot processes the command and returns an appropriate response. This integration with the prompt using OpenAI ensures that actions follow the provided business logic. -The following example shows how Teams AI library makes it possible to manage the bot logic for handling an action `LightsOn` or `LightsOff` and connect it to the prompt used with OpenAI: - -# [.NET](#tab/dotnet3) +#### .NET Example - [Code sample](https://github.com/microsoft/teams-ai/tree/main/dotnet/samples/04.ai.c.actionMapping.lightBot) - - [Sample code reference](https://github.com/microsoft/teams-ai/blob/main/dotnet/samples/04.ai.c.actionMapping.lightBot/Program.cs#L33) - - [Actions sample code reference](https://github.com/microsoft/teams-ai/blob/main/dotnet/samples/04.ai.c.actionMapping.lightBot/LightBotActions.cs#L10) ```csharp -/ Create AI Model +// Create AI Model if (!string.IsNullOrEmpty(config.OpenAI?.ApiKey)) { builder.Services.AddSingleton(sp => new( @@ -422,51 +416,48 @@ builder.Services.AddTransient(sp => // LightBotActions defined in LightBotActions.cs [Action("LightsOn")] - public async Task LightsOn([ActionTurnContext] ITurnContext turnContext, [ActionTurnState] AppState turnState) - { - turnState.Conversation.LightsOn = true; - await turnContext.SendActivityAsync(MessageFactory.Text("[lights on]")); - return "the lights are now on"; - } +public async Task LightsOn([ActionTurnContext] ITurnContext turnContext, [ActionTurnState] AppState turnState) +{ + turnState.Conversation.LightsOn = true; + await turnContext.SendActivityAsync(MessageFactory.Text("[lights on]")); + return "the lights are now on"; +} - [Action("LightsOff")] - public async Task LightsOff([ActionTurnContext] ITurnContext turnContext, [ActionTurnState] AppState turnState) - { - turnState.Conversation.LightsOn = false; - await turnContext.SendActivityAsync(MessageFactory.Text("[lights off]")); - return "the lights are now off"; - } +[Action("LightsOff")] +public async Task LightsOff([ActionTurnContext] ITurnContext turnContext, [ActionTurnState] AppState turnState) +{ + turnState.Conversation.LightsOn = false; + await turnContext.SendActivityAsync(MessageFactory.Text("[lights off]")); + return "the lights are now off"; +} - [Action("Pause")] - public async Task LightsOff([ActionTurnContext] ITurnContext turnContext, [ActionParameters] Dictionary args) +[Action("Pause")] +public async Task LightsOff([ActionTurnContext] ITurnContext turnContext, [ActionParameters] Dictionary args) +{ + // Try to parse entities returned by the model. + // Expecting "time" to be a number of milliseconds to pause. + if (args.TryGetValue("time", out object? time)) + { + if (time != null && time is string timeString) { - // Try to parse entities returned by the model. - // Expecting "time" to be a number of milliseconds to pause. - if (args.TryGetValue("time", out object? time)) + if (int.TryParse(timeString, out int timeInt)) { - if (time != null && time is string timeString) - { - if (int.TryParse(timeString, out int timeInt)) - { - await turnContext.SendActivityAsync(MessageFactory.Text($"[pausing for {timeInt / 1000} seconds]")); - await Task.Delay(timeInt); - } - } + await turnContext.SendActivityAsync(MessageFactory.Text($"[pausing for {timeInt / 1000} seconds]")); + await Task.Delay(timeInt); } - - return "done pausing"; } + } + return "done pausing"; +} ``` -# [JavaScript](#tab/javascript3) +#### JavaScript Example - [Code sample](https://github.com/microsoft/teams-ai/tree/main/js/samples/03.ai-concepts/c.actionMapping-lightBot) - - [Sample code reference](https://github.com/microsoft/teams-ai/blob/main/js/samples/03.ai-concepts/c.actionMapping-lightBot/src/index.ts#L87) ```typescript - // Create AI components const model = new OpenAIModel({ // OpenAI Support @@ -529,13 +520,11 @@ app.ai.action('Pause', async (context: TurnContext, state: ApplicationTurnState, await new Promise((resolve) => setTimeout(resolve, parameters.time)); return `done pausing`; }); - ``` -# [Python](#tab/python3) +#### Python Example - [Code sample](https://github.com/microsoft/teams-ai/tree/main/python/samples/04.ai.c.actionMapping.lightBot) - - [Sample code reference](https://github.com/microsoft/teams-ai/blob/main/python/samples/04.ai.c.actionMapping.lightBot/src/bot.py#L35) ```python @@ -559,65 +548,59 @@ elif config.AZURE_OPENAI_KEY and config.AZURE_OPENAI_ENDPOINT: --- -### Message extension query - -Teams AI library provides a more intuitive way to create handlers for message extension query commands, working alongside the existing Teams Bot Framework SDK. +### Message Extension Query -The following is an example of how you can structure the code to handle a message extension query for the `searchCmd` command. +Teams AI library offers an intuitive way to create handlers for message extension query commands. This sample shows how to structure your code for handling a message extension query (e.g., `searchCmd`). -# [.NET](#tab/dotnet2) +#### .NET Example - [Code sample](https://github.com/microsoft/teams-ai/tree/main/dotnet/samples/02.messageExtensions.a.searchCommand) - - [Search actions sample code reference](https://github.com/microsoft/teams-ai/blob/main/dotnet/samples/02.messageExtensions.a.searchCommand/Program.cs#L47) - - [Search results sample code reference](https://github.com/microsoft/teams-ai/blob/main/dotnet/samples/02.messageExtensions.a.searchCommand/ActivityHandlers.cs#L39) ```csharp // Listen for search actions - app.MessageExtensions.OnQuery("searchCmd", activityHandlers.QueryHandler); - // Listen for item tap - app.MessageExtensions.OnSelectItem(activityHandlers.SelectItemHandler); +app.MessageExtensions.OnQuery("searchCmd", activityHandlers.QueryHandler); +// Listen for item tap +app.MessageExtensions.OnSelectItem(activityHandlers.SelectItemHandler); - return app; +return app; - // Format search results - List attachments = packages.Select(package => new MessagingExtensionAttachment - { - ContentType = HeroCard.ContentType, - Content = new HeroCard - { - Title = package.Id, - Text = package.Description - }, - Preview = new HeroCard - { - Title = package.Id, - Text = package.Description, - Tap = new CardAction - { - Type = "invoke", - Value = package - } - }.ToAttachment() - }).ToList(); - - return new MessagingExtensionResult - { - Type = "result", - AttachmentLayout = "list", - Attachments = attachments - }; +// Format search results +List attachments = packages.Select(package => new MessagingExtensionAttachment +{ + ContentType = HeroCard.ContentType, + Content = new HeroCard + { + Title = package.Id, + Text = package.Description + }, + Preview = new HeroCard + { + Title = package.Id, + Text = package.Description, + Tap = new CardAction + { + Type = "invoke", + Value = package + } + }.ToAttachment() +}).ToList(); + +return new MessagingExtensionResult +{ + Type = "result", + AttachmentLayout = "list", + Attachments = attachments +}; ``` -# [JavaScript](#tab/javascript2) +#### JavaScript Example - [Code sample](https://github.com/microsoft/teams-ai/tree/main/js/samples/02.teams-features/a.messageExtensions.searchCommand) - - [Sample code reference](https://github.com/microsoft/teams-ai/blob/main/js/samples/02.teams-features/a.messageExtensions.searchCommand/src/index.ts#L78) ```typescript - // Listen for search actions app.messageExtensions.query('searchCmd', async (context, state, query) => { const searchQuery = query.parameters.queryText ?? ''; @@ -629,12 +612,10 @@ app.messageExtensions.query('searchCmd', async (context, state, query) => { }).toString()}` ); - // Format search results const results: MessagingExtensionAttachment[] = []; response?.data?.objects?.forEach((obj: any) => results.push(createNpmSearchResultCard(obj.package))); - // Return results as a list return { attachmentLayout: 'list', @@ -647,24 +628,21 @@ And here’s how they can return a card when a message-extension result is selec // Listen for item tap app.messageExtensions.selectItem(async (context, state, item) => { - // Generate detailed result + // Generate detailed result card based on the selected item const card = createNpmPackageCard(item); - - // Return results + // Return the card as a list with a single attachment return { attachmentLayout: 'list', attachments: [card], type: 'result' }; }); - ``` -# [Python](#tab/python2) +#### Python Example - [Code sample](https://github.com/microsoft/teams-ai/tree/main/python/samples/02.messageExtensions.a.searchCommand) - - [Sample code reference](https://github.com/microsoft/teams-ai/blob/main/python/samples/02.messageExtensions.a.searchCommand/src/bot.py#L44) ```python @@ -701,32 +679,30 @@ async def search_command( @app.message_extensions.select_item() async def select_item(_context: TurnContext, _state: AppTurnState, item: Any): card = create_npm_package_card(item) - return MessagingExtensionResult(attachment_layout="list", attachments=[card], type="result") ``` --- -## Intents to actions +## Intents to Actions -A simple interface for actions and predictions allows bots to react confidently. Ambient presence helps bots learn intent, use prompts based on business logic, and generate responses. -With Teams AI library, the prompt outlines the bot's actions and provides examples. +This section explains how the Teams AI library uses a simple interface for actions and predictions, enabling bots to react with confidence. Ambient presence helps bots learn intent, use prompts based on business logic, and generate appropriate responses. -Conversation history enables natural dialogue, such as *add cereal to groceries list*, followed by *also add coffee*, indicating coffee should be added to the list. +For example, if a user says "add cereal to groceries list" and later "also add coffee", the AI assistant recognizes both commands and processes them accordingly. -The following is a conversation with an AI assistant. The AI assistant can manage lists and recognizes the following commands: +The following conversation sample shows how the AI assistant can manage lists. The supported actions include: - DO ` ` - SAY `` -The following actions are supported: - +Supported actions: - `addItem list="" item=""` - `removeItem list="" item=""` - `summarizeLists` -All entities are required parameters for actions. +All entities are required for actions. +Additional conversation context is provided through: - Current list names: ``` @@ -734,9 +710,7 @@ All entities are required parameters for actions. ``` ```text - Examples: - Human: remind me to buy milk AI: DO addItem list="groceries" item="milk" THEN SAY Ok I added milk to your groceries list Human: we already have milk @@ -753,7 +727,6 @@ All entities are required parameters for actions. AI: DO summarizeLists Human: show me all lists as a card and sort the lists alphabetically AI: DO summarizeLists - ``` - Conversation history: @@ -774,123 +747,119 @@ All entities are required parameters for actions. {{conversation.listNames}} ``` -- AI: The bot logic is streamlined to include handlers for actions such as `addItem` and `removeItem`. This distinction between actions and the prompts serves as a powerful tool as it guides AI to execute the actions and prompts. +The refined bot logic distinguishes between actions and prompts, guiding the AI to execute actions while providing clear feedback. - # [.NET](#tab/dotnet1) - - - [Code sample](https://github.com/microsoft/teams-ai/tree/main/dotnet/samples/04.ai.d.chainedActions.listBot) - - - [Sample code reference](https://github.com/microsoft/teams-ai/blob/main/dotnet/samples/04.ai.d.chainedActions.listBot/ListBotActions.cs#L40) +#### .NET Example - ```csharp - [Action("AddItem")] - public string AddItem([ActionTurnState] ListState turnState, [ActionParameters] Dictionary parameters) - { - ArgumentNullException.ThrowIfNull(turnState); - ArgumentNullException.ThrowIfNull(parameters); - - string listName = GetParameterString(parameters, "list"); - string item = GetParameterString(parameters, "item"); - - IList items = GetItems(turnState, listName); - items.Add(item); - SetItems(turnState, listName, items); - - return "item added. think about your next action"; - } - - [Action("RemoveItem")] - public async Task RemoveItem([ActionTurnContext] ITurnContext turnContext, [ActionTurnState] ListState turnState, [ActionParameters] Dictionary parameters) - { - ArgumentNullException.ThrowIfNull(turnContext); - ArgumentNullException.ThrowIfNull(turnState); - ArgumentNullException.ThrowIfNull(parameters); - - string listName = GetParameterString(parameters, "list"); - string item = GetParameterString(parameters, "item"); - - IList items = GetItems(turnState, listName); - - if (!items.Contains(item)) - { - await turnContext.SendActivityAsync(ResponseBuilder.ItemNotFound(listName, item)).ConfigureAwait(false); - return "item not found. think about your next action"; - } - - items.Remove(item); - SetItems(turnState, listName, items); - return "item removed. think about your next action"; - } +- [Code sample](https://github.com/microsoft/teams-ai/tree/main/dotnet/samples/04.ai.d.chainedActions.listBot) +- [Sample code reference](https://github.com/microsoft/teams-ai/blob/main/dotnet/samples/04.ai.d.chainedActions.listBot/ListBotActions.cs#L40) - ``` +```csharp +[Action("AddItem")] +public string AddItem([ActionTurnState] ListState turnState, [ActionParameters] Dictionary parameters) +{ + ArgumentNullException.ThrowIfNull(turnState); + ArgumentNullException.ThrowIfNull(parameters); - # [JavaScript](#tab/javascript1) + string listName = GetParameterString(parameters, "list"); + string item = GetParameterString(parameters, "item"); - - [Code sample](https://github.com/microsoft/teams-ai/tree/main/js/samples/03.ai-concepts/d.chainedActions-listBot) + IList items = GetItems(turnState, listName); + items.Add(item); + SetItems(turnState, listName, items); - - [Sample code reference](https://github.com/microsoft/teams-ai/blob/main/js/samples/03.ai-concepts/d.chainedActions-listBot/src/index.ts#L161) + return "item added. think about your next action"; +} - ```typescript - app.ai.action('addItems', async (context: TurnContext, state: ApplicationTurnState, parameters: ListAndItems) => { - const items = getItems(state, parameters.list); - items.push(...(parameters.items ?? [])); - setItems(state, parameters.list, items); - return `items added. think about your next action`; - }); - - app.ai.action('removeItems', async (context: TurnContext, state: ApplicationTurnState, parameters: ListAndItems) => { - const items = getItems(state, parameters.list); - (parameters.items ?? []).forEach((item: string) => { - const index = items.indexOf(item); - if (index >= 0) { - items.splice(index, 1); - } - }); - setItems(state, parameters.list, items); - return `items removed. think about your next action`; - }); - ``` - - # [Python](#tab/python1) - - - [Code sample](https://github.com/microsoft/teams-ai/tree/main/python/samples/04.ai.d.chainedActions.listBot) - - - [Sample code reference](https://github.com/microsoft/teams-ai/blob/main/python/samples/04.ai.d.chainedActions.listBot/src/bot.py#L96C1-L123C57) - - ```python - @app.ai.action("addItems") - async def on_add_items( - context: ActionTurnContext[Dict[str, Any]], - state: AppTurnState, - ): - parameters = ListAndItems.from_dict(context.data, infer_missing=True) - state.ensure_list_exists(parameters.list) - items = state.conversation.lists[parameters.list] - if parameters.items is not None: - for item in parameters.items: - items.append(item) - state.conversation.lists[parameters.list] = items - return "items added. think about your next action" - - @app.ai.action("removeItems") - async def on_remove_items( - context: ActionTurnContext[Dict[str, Any]], - state: AppTurnState, - ): - parameters = ListAndItems.from_dict(context.data, infer_missing=True) - state.ensure_list_exists(parameters.list) - items = state.conversation.lists[parameters.list] - if parameters.items is not None and len(parameters.items) > 0: - for item in parameters.items: - if item in items: - items.remove(item) - state.conversation.lists[parameters.list] = items - return "items removed. think about your next action" - ``` - - --- - -## Next step +[Action("RemoveItem")] +public async Task RemoveItem([ActionTurnContext] ITurnContext turnContext, [ActionTurnState] ListState turnState, [ActionParameters] Dictionary parameters) +{ + ArgumentNullException.ThrowIfNull(turnContext); + ArgumentNullException.ThrowIfNull(turnState); + ArgumentNullException.ThrowIfNull(parameters); + + string listName = GetParameterString(parameters, "list"); + string item = GetParameterString(parameters, "item"); + + IList items = GetItems(turnState, listName); + + if (!items.Contains(item)) + { + await turnContext.SendActivityAsync(ResponseBuilder.ItemNotFound(listName, item)).ConfigureAwait(false); + return "item not found. think about your next action"; + } + + items.Remove(item); + SetItems(turnState, listName, items); + return "item removed. think about your next action"; +} +``` + +#### JavaScript Example + +- [Code sample](https://github.com/microsoft/teams-ai/tree/main/js/samples/03.ai-concepts/d.chainedActions-listBot) +- [Sample code reference](https://github.com/microsoft/teams-ai/blob/main/js/samples/03.ai-concepts/d.chainedActions-listBot/src/index.ts#L161) + +```typescript +app.ai.action('addItems', async (context: TurnContext, state: ApplicationTurnState, parameters: ListAndItems) => { + const items = getItems(state, parameters.list); + items.push(...(parameters.items ?? [])); + setItems(state, parameters.list, items); + return `items added. think about your next action`; +}); + +app.ai.action('removeItems', async (context: TurnContext, state: ApplicationTurnState, parameters: ListAndItems) => { + const items = getItems(state, parameters.list); + (parameters.items ?? []).forEach((item: string) => { + const index = items.indexOf(item); + if (index >= 0) { + items.splice(index, 1); + } + }); + setItems(state, parameters.list, items); + return `items removed. think about your next action`; +}); +``` + +#### Python Example + +- [Code sample](https://github.com/microsoft/teams-ai/tree/main/python/samples/04.ai.d.chainedActions.listBot) +- [Sample code reference](https://github.com/microsoft/teams-ai/blob/main/python/samples/04.ai.d.chainedActions.listBot/src/bot.py#L96C1-L123C57) + +```python +@app.ai.action("addItems") +async def on_add_items( + context: ActionTurnContext[Dict[str, Any]], + state: AppTurnState, +): + parameters = ListAndItems.from_dict(context.data, infer_missing=True) + state.ensure_list_exists(parameters.list) + items = state.conversation.lists[parameters.list] + if parameters.items is not None: + for item in parameters.items: + items.append(item) + state.conversation.lists[parameters.list] = items + return "items added. think about your next action" + +@app.ai.action("removeItems") +async def on_remove_items( + context: ActionTurnContext[Dict[str, Any]], + state: AppTurnState, +): + parameters = ListAndItems.from_dict(context.data, infer_missing=True) + state.ensure_list_exists(parameters.list) + items = state.conversation.lists[parameters.list] + if parameters.items is not None and len(parameters.items) > 0: + for item in parameters.items: + if item in items: + items.remove(item) + state.conversation.lists[parameters.list] = items + return "items removed. think about your next action" +``` + +--- + +## Next Step > [!div class="nextstepaction"] > [Build a custom engine agent](../../../Teams-AI-library-tutorial.yml)