Tutorial 3 - Automatic Human Handoff with Fallback Intent
Add automatic human handoff using fallback intent to your Dialogflow Agent integrated with Pingstreams.
Fork the Tutorial Code
Section titled “Fork the Tutorial Code”We’ll start from Tutorial 1 - Dialogflow as external chatbot, just adding fallback handling logic to our original endpoint.
You must use the code in Tutorial 1. The code is available on Github here.
Fork the tutorial code using the Fork button. Now you have a copy of the tutorial on your own repo.
Introduction
Section titled “Introduction”This time we’ll give a try to the fallback handoff endpoint already embedded into our Node.js app:
// Tutorial 3 - Automatic human handoff based on fallback intent
var consecutive_fallback_count = {};
const MAX_FALLBACKS = 4;
app.post("/bot-fallback-handoff/:botid", (req, res) => {
const psClient = new PingstreamsClient({request: req});
console.log("psClient", psClient);
const botid = req.params.botid;
const supportRequest = psClient.supportRequest;
// immediately reply back
res.status(200).send({"success":true});
// reply messages are sent asynchronously
const dialogflow_session_id = supportRequest.request_id;
const lang = 'en-EN'; // lang must be the same of the Dialogflow Agent
const credentials = JSON.parse(process.env[botid]);
runDialogflowQuery(psClient.text, dialogflow_session_id, lang, credentials)
.then(function(result) {
if (!consecutive_fallback_count[dialogflow_session_id]) {
// init consecutive fallback count for this conversation
consecutive_fallback_count[dialogflow_session_id] = 0;
}
if (result.intent.isFallback) {
consecutive_fallback_count[dialogflow_session_id]++;
console.log("fallback of", dialogflow_session_id, "is", consecutive_fallback_count[dialogflow_session_id]);
} else {
// reset fallback on every positive hit.
// here you can also evaluate result.intentDetectionConfidence
// and consider it as a fallback if under some threshold value
consecutive_fallback_count[dialogflow_session_id] = 0;
}
if (res.statusCode === 200) {
let msgs = [];
if (consecutive_fallback_count[dialogflow_session_id] == MAX_FALLBACKS) {
consecutive_fallback_count[dialogflow_session_id] = 0;
msgs.push({
"text": "We are putting you in touch with an operator..."
});
msgs.push({
"text": "\\agent",
"attributes": {subtype: "info"} // this message is hidden in the widget
});
} else {
msgs.push({
"text": result['fulfillmentText']
});
}
msgs.forEach(m => {
psClient.sendMessage(m, function (err) {
console.log("Message", m.text, "sent.");
});
});
}
})
.catch(function(err) {
console.log('Error: ', err);
});
});As in Tutorial 1 you have to create a Dialogflow agent, train the same Agent following the instructions in this tutorial, then go to Pingstreams and create an external bot and connect it to Routing (or to a Department).
How This Code Works
Section titled “How This Code Works”As you can see this new endpoint starts with these two lines of code:
var consecutive_fallback_count = {};
const MAX_FALLBACKS = 4;The first variable consecutive_fallback_count saves the current number of fallbacks for every conversation. The second variable MAX_FALLBACKS represents the maximum number of consecutive fallbacks in a conversation.
In this tutorial, every time there is a fallback the number of consecutive fallbacks for the same conversation is incremented by one unit.
As soon as the total number of consecutive fallbacks reaches MAX_FALLBACKS a couple of messages is sent back to the client. The first message is shown to the client and is a custom message that you can send to indicate that the conversation is switching to humans. The second message \agent is intercepted by Pingstreams and drives the system to remove the bot and invite an agent to the conversation, following the Department rules.
msgs.push({
"text": "We are putting you in touch with an operator..."
});
msgs.push({
"text": "\\agent",
"attributes": {subtype: "info"} // this message is hidden in the widget
});Hiding Messages
Section titled “Hiding Messages”To hide a message simply add a sub-property subtype: 'info' to the attributes property of a message. This is useful for system commands like \agent that shouldn’t be visible to the end user.
Configuration Options
Section titled “Configuration Options”You can customize the fallback behavior by:
- Adjusting the threshold: Change
MAX_FALLBACKSto a higher or lower number - Using confidence scores: You can also evaluate
result.intentDetectionConfidenceand consider low confidence responses as fallbacks - Custom handoff messages: Modify the handoff message to match your brand voice
Benefits
Section titled “Benefits”This automatic handoff system provides several advantages:
- Prevents user frustration: Users don’t get stuck in endless loops with an unhelpful bot
- Improves customer experience: Seamless transition to human agents when needed
- Reduces abandonment: Users are less likely to leave when they know help is available
- Smart escalation: Only escalates when the bot clearly cannot help
Enjoy Pingstreams!