Create custom triggers

APPLIES TO: Composer v2.x

In Bot Framework Composer, triggers are fired when events matching a condition occur.

This article demonstrates how to create a custom trigger named OnMembersAdded that will fire when members are added to the conversation.

Prerequisites

Complete sample

The complete code for this sample can be found in the Bot Framework samples repository on GitHub:

Setup the Bot Framework CLI tool

The Bot Framework CLI tools include the bf-dialog command for working with .schema files. If the Bot Framework CLI tool isn't already installed, open an elevated command prompt and run the following command to install the Bot Framework tools:

npm i -g @microsoft/botframework-cli

Setup the component project

To create a custom trigger (or any component), first setup a new project, and add the necessary package dependencies for working with adaptive dialogs and the Bot Framework SDK.

  1. Locate the solution (.sln) file for your bot, and open it in an editor (like Visual Studio or Visual Studio Code).

  2. Add a new project named MemberUpdates to your solution. In Visual Studio right-click on the solution in the Solution Explorer and select Add > New Project. Use the Class Library project template.

  3. Add a reference to the Microsoft.Bot.Builder.Adaptive.Runtime package. Use the same version as the bot depends on.

    <PackageReference Include="Microsoft.Bot.Builder.Dialogs.Adaptive.Runtime" Version="4.13.1" />
    
  4. Add a project reference from the bot project to the component project. Right-click on your bot project and select Add > Project Reference. Choose the MemberUpdates project and click OK.

  5. Build the entire solution to restore all packages and validate the dependency tree.

Create the custom trigger

Custom triggers extend the base OnActivity class, adding an expression in order to respond to specific events. This sample creates a trigger that fires when new members are added to a conversation. It responds to ConversationUpdate activities when the membersAdded array isn't null or empty.

In the MemberUpdates project, rename the Class1.cs file to OnMembersAdded and update the contents to:

using System.Collections.Generic;
using System.Runtime.CompilerServices;
using AdaptiveExpressions;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Builder.Dialogs.Adaptive.Conditions;
using Microsoft.Bot.Schema;
using Newtonsoft.Json;

public class OnMembersAdded : OnActivity
{
    [JsonProperty("$kind")]
    public new const string Kind = "OnMembersAdded";

    [JsonConstructor]
    public OnMembersAdded(List<Dialog> actions = null, string condition = null, [CallerFilePath] string callerPath = "", [CallerLineNumber] int callerLine = 0)
    : base(type: ActivityTypes.ConversationUpdate, actions: actions, condition: condition, callerPath: callerPath, callerLine: callerLine)
    {
    }

    protected override Expression CreateExpression()
    {
        // The Activity.MembersAdded list must have more than 0 items.
        return Expression.AndExpression(Expression.Parse($"count({TurnPath.Activity}.MembersAdded) > 0"), base.CreateExpression());
    }
}

Create the schema files

The .schema file for the component is a partial schema that will be merged into the main .schema file for the bot. Although it's possible to edit the main sdk.schema file for the bot directly, doing so isn't recommended. Merging partial schema files will isolate changes, allow for easier recovery from errors, and enable easier packaging of your component for reuse.

  1. Create a new file in the project named OnMembersAdded.schema and update the contents to the below:

    Important

    The name of the .schema file must match the Kind variable defined in the OnMembersAdded.cs file exactly, including casing.

    {
        "$schema": "https://schemas.botframework.com/schemas/component/v1.0/component.schema",
        "$role": [ "implements(Microsoft.ITrigger)", "extends(Microsoft.OnCondition)" ],
        "title": "On Members Added",
        "description": "Actions to perform on receipt of an activity with type 'ConversationUpdate' and MembersAdded > 0.",
        "type": "object",
        "required": [
        ]
    }
    
  2. Create another new file in the project named OnMembersAdded.uischema. This file tells Composer where to display the component.

    {
    "$schema": "https://schemas.botframework.com/schemas/ui/v1.0/ui.schema",
    "form": {
        "order": [
            "condition",
            "*"
        ],
        "hidden": [
            "actions"
        ],
        "label": "Members Added",
        "subtitle": "Members Added ConversationUpdate activity",
        "description": "Handle the events fired when a members have been added to a conversation.",
        "helpLink": "https://learn.microsoft.com/composer/how-to-define-triggers#activities"
    },
        "trigger": {
            "label": "Members Added (ConversationUpdate activity)",
            "submenu": "Member Updates"
        }
    }
    

Create the BotComponent class

The adaptive runtime will dynamically discover and inject components at startup time.

  1. Create a new file named MultiplyDialogBotComponent.cs in the project and update the contents to:

    using Microsoft.Bot.Builder;
    using Microsoft.Bot.Builder.Dialogs.Declarative;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    
    public class MultiplyDialogBotComponent : BotComponent
    {
        public override void ConfigureServices(IServiceCollection services, IConfiguration configuration)
        {
            // Anything that could be done in Startup.ConfigureServices can be done here.
            // In this case, the MultiplyDialog needs to be added as a new DeclarativeType.
            services.AddSingleton<DeclarativeType>(sp => new DeclarativeType<OnMembersAdded>(OnMembersAdded.Kind));
        }
    }
    
  2. In the appsettings.json file of the bot project (located at <mybot>\settings), add MultiplyDialogBotComponent to the runtimeSettings/components array.

    "runtimeSettings": {
        "components": [
            {
                "name": "MultiplyDialogBotComponent"
            }
        ]
    }
    
  3. Build the entire solution to validate everything was added correctly.

Merge schema files

The final step is to merge the partial schema file from the MemberUpdates project into the main sdk.schema file for the bot. This makes the custom action available for use in Composer.

Note

This step only needs to be performed when a new .schema file is added or updated.

  1. Navigate to the schemas folder in the myBot project. This folder contains a PowerShell script and a bash script. Use an elevated PowerShell terminal to execute the PowerShell script. You'll need to either copy/paste the contents of the script, or ensure your execution-policy allows for running unsigned scripts.

  2. To validate the script executed successfully, search for MultiplyDialog inside the MyBot\schemas\sdk.schema file and validate that the partial schema from the MultiplyDialog.schema file is included in sdk.schema.

Note

Alternatively, you can click-to-run the update-schema.sh file inside the MyEmptyBot\schemas folder to run the bash script.

Test

Open the bot project in Composer and you should be able to test your added custom trigger. If the project is already loaded, return to Home in Composer, and reload the project.

  1. Open the bot in Composer. Select a dialog to add this custom trigger with and select ....

  2. Select + Add new trigger to open the triggers menu. Choose the Member Updates trigger.

  3. Select Members Added (ConversationUpdate activity), then click Submit.

  4. Add a Send a response action to the newly created trigger, and enter some text. For example "Members added".

  5. Select Start Bot to test the bot in Web Chat. The bot will receive the appropriate Activity when the conversation initiates, and respond with the text entered in the previous step.

Additional information