How to override user or bot response and send multiple messages to a bot user from the BotKit

Problem statement:
Due to some channel constraints, a long message from the platform may not be accepted (although most channels, like SMS, would take care of the chunking internally). So, the user would like to override the response, chunk the long message, and send multiple messages to the user using Kore.ai BotKit. These overridden messages may be of plain text type or JSON templates.

Scope of solution:
The actual chunking of the message is expected to be taken care of by the bot developer. The below solution will encompass below two scenarios:

  1. How to detect a user’s message in the BotKit, and without sending the message to the bot, respond back to the user with multiple messages directly from the BotKit.
  2. How to detect a particular response from the Bot in the BotKit, and without directly sending it to the user, override it and send multiple messages instead.

Note: The solution does not consider any particular channel. The solution will need to be tweaked for sending any message or template suitable to a channel and adjust other channel-related responses accordingly.

Scenario 1:
Detecting a user’s message in the BotKit, and without sending the message to the bot, respond back to the user with multiple messages directly from the BotKit.

Under on_user_message the following code will help detect if the user sent “MYTest 321” in the utterance and help send responses back. Note the usage of return (sdk.sendUserMessage(data, callback). This will send the message to the USER and NOT THE BOT. Before this statement, the data.message or data.overrideMessagePayload will need to be overriddeden.

    on_user_message: function (requestId, data, callback) {
        var overrideMessagePayload = {};

        consoleLog(data, "on_user_message");

        if (data.message === "MYTest 321") {
            //data.message = "Response 1";
            overrideMessagePayload = {
                body: "{\"text\":\"Response1\"}",
                isTemplate: true
            };
            data.overrideMessagePayload = overrideMessagePayload;
            return (sdk.sendUserMessage(data, callback)
                .then(function () {
                    //data.message = "Response 2";
                    overrideMessagePayload = {
                        body: "{\"text\":\"Response2\"}",
                        isTemplate: true
                    };
                    data.overrideMessagePayload = overrideMessagePayload;
                    return sdk.sendUserMessage(data, callback);
                })
                .then(function () {
                    //data.message = "Response 3";
                    overrideMessagePayload = {
                        body: "{\"text\":\"Response3\"}",
                        isTemplate: true
                    };
                    data.overrideMessagePayload = overrideMessagePayload;
                    return sdk.sendUserMessage(data, callback);
                })

            );

        } else {
            return sdk.sendBotMessage(data, callback);
        }
    }

Output:
image

Scenario 2:
Detecting a particular response from the Bot in the BotKit, and without directly sending it to the user, override it and send multiple messages instead.
Assume the Bot responds with a particular message: $$MY_ENCODED_MESSAGE$$.


The below code under on_bot_message will help achieve detect the response and then override it.

    on_bot_message: function (requestId, data, callback) {
        consoleLog(data, "on_bot_message");
        if (data.message === "$$MY_ENCODED_MESSAGE$$") {
            overrideMessagePayload = {
                body: "{\"text\":\"Bot Response 001\"}",
                isTemplate: true
            };
            data.overrideMessagePayload = overrideMessagePayload;
            //data.message = "Response 1";
            consoleLog(data, "*** Resp 1 ***");
            return sdk.sendUserMessage(data, callback)
                .then(function () {
                    overrideMessagePayload = {
                        body: "{\"text\":\"Bot Response 002\"}",
                        isTemplate: true
                    };
                    //data.message = "Response 2";
                    data.overrideMessagePayload = overrideMessagePayload;
                    consoleLog(data, "*** Resp 2 ***");
                    return sdk.sendUserMessage(data, callback);
                })
                .then(function () {
                    overrideMessagePayload = {
                        body: "{\"text\":\"Bot Response 003\"}",
                        isTemplate: true
                    };
                    //data.message = "Response 3";
                    data.overrideMessagePayload = overrideMessagePayload;
                    consoleLog(data, "*** Resp 3 ***");
                    return sdk.sendUserMessage(data, callback);
                })

            
        } else {
            return sdk.sendUserMessage(data, callback);
        }

    }

Here are a few important things to note:

  1. To maintain the sequence of the responses note the usage of return. This will ensure synchronous and sequential responses.

  2. The data.overrideMessagePayload only needs to be used along with isTemplate:true when you are overriding a message and sending a JSON/any other template as a response (VXML, XML also can be sent this way). Please refer to Intercept VXML BotKit - #3 by swagata.sengupta for further reference on how to send VXML. If you are simply trying to override the message, do not use data.overrideMessagePayload with the override object. Rather override data.message

  3. If you try to override both data.message and use data.overrideMessagePayload, the data.overrideMessagePayload will take precendence. But you will need to ensure you use isTemplate:true

  4. If you are testing this on the bot-builder/Kore.ai Web-SDK UI, if the template is not known, the UI may not render the template correctly. It will try to render the message body instead. Say, for on_bot_response code, the first two responses are as is, and if you change body: "{\"text\":\"Bot Response 003\"}", to body: "{\"Atext\":\"Bot Response 003\"}" for the third response, which is not known to Kore.ai channel/bot-builder, the builder will show what is found in the message body (under WebSocket messages)

  5. The consoleLog is a custom function I have used.

//custom console log function
function consoleLog(data, customMsg) {
    console.log(new Date() + "=> " +
        customMsg + " => " +
        JSON.stringify(data.message) + 
        (data.overrideMessagePayload? "data.overrideMessagePayload => "+JSON.stringify(data.overrideMessagePayload) : "")
    );
}
  1. For simplicity, Kore.ai text template has been used.

Thanks @yesu.chiratanagandla for technical guidance.