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:
- 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.
- 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:
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:
-
To maintain the sequence of the responses note the usage of return. This will ensure synchronous and sequential responses.
-
The
data.overrideMessagePayload
only needs to be used along withisTemplate: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 usedata.overrideMessagePayload
with the override object. Rather overridedata.message
-
If you try to override both
data.message
and usedata.overrideMessagePayload
, thedata.overrideMessagePayload
will take precendence. But you will need to ensure you useisTemplate:true
-
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\"}",
tobody: "{\"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)
-
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) : "")
);
}
- For simplicity, Kore.ai text template has been used.
Thanks @yesu.chiratanagandla for technical guidance.