Skip to content
FacebookYouTubeX (Twitter)

Tutorial 5 - Gracefully Handling Operating Hours During Handoff

Learn how to gracefully handle operating hours in bot-to-human handoff scenarios with Pingstreams.

We’ll start from Tutorial 1 - Dialogflow as external chatbot, building on the foundation and adding operating hours awareness.

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.

What happens if, while you switch to the human operator, your support team is outside of operating hours? The request will be placed in the unserved queue and will become served as soon as your team becomes available again. Meanwhile you should notify the user that the request will be taken in some hours, or probably the day after. So, telling “I’m putting you in touch with an operator” is not enough.

How can you write a handoff message that depends on operating hours? You can mix Dialogflow message fulfillment and Pingstreams APIs to reach your goal.

Open Dialogflow dashboard on your agent, then in the menu Fulfillment option enable “Webhook” option. In the URL field insert your heroku app url where you published your app followed by /dfwebhook and your project_id:

Webhook Configuration

This “webhook” endpoint is already provided in the script:

// Tutorial 5 - Webhook for Bot-to-Agent handoff message based on opening hours
app.post('/dfwebhook/:project_id', (req, res) => {
  const fulfillmentText = req.body.queryResult.fulfillmentText;
  console.log("fulfillmentText:", fulfillmentText);
  
  const languageCode = req.body.queryResult.languageCode;
  console.log("languageCode:", languageCode);
  
  // replace the following with your project id
  const project_id = req.params.project_id;
  const intent = req.body.queryResult.intent.displayName.toUpperCase();
  
  if (intent === "TALK TO AGENT") {
    const psClient = new PingstreamsClient();
    psClient.openNow(function(isopen) {
      var df_res = {};
      if (isopen) {
        df_res['fulfillmentText'] = "We are open! Switching to agent\\agent";
      } else {
        df_res['fulfillmentText'] = "I'm sorry but we are closed right now.";
      }
      res.status(200).send(JSON.stringify(df_res));
    });
  }
});

This endpoint uses a project_id in the webhook URL that you must replace with your own.

Re-train the ‘Talk to Agent’ Intent to Use Fulfillment

Section titled “Re-train the ‘Talk to Agent’ Intent to Use Fulfillment”

Fulfillment is not automatically active on the intents. You must activate it for each intent that you want to reply dynamically. We will re-train the ‘talk to agent’ intent to use our webhook to reply, instead of the static response.

Switch to the intent UI from Dialogflow dashboard, then go to the form bottom and switch to “on” the fulfillment button, as in the following picture:

Enable Fulfillment

Now go to your project in Pingstreams dashboard and activate operating hours, taking care to set offline the interval when you ask the bot to switch to human agents. If you try to switch to human operators during offline hours you will get the following message:

Offline Hours Response

You can enhance the basic operating hours check with more sophisticated logic:

app.post('/dfwebhook/:project_id', (req, res) => {
  const intent = req.body.queryResult.intent.displayName.toUpperCase();
  
  if (intent === "TALK TO AGENT") {
    const psClient = new PingstreamsClient();
    const userTimezone = req.body.queryResult.parameters.timezone || 'UTC';
    
    psClient.openNow(userTimezone, function(isopen, nextOpenTime) {
      var df_res = {};
      if (isopen) {
        df_res['fulfillmentText'] = "We are open! Connecting you to an agent now.\\agent";
      } else {
        const nextOpen = new Date(nextOpenTime).toLocaleString();
        df_res['fulfillmentText'] = `We are currently closed. Our next available time is ${nextOpen}. Would you like to leave a message?`;
      }
      res.status(200).send(JSON.stringify(df_res));
    });
  }
});
app.post('/dfwebhook/:project_id', (req, res) => {
  const intent = req.body.queryResult.intent.displayName.toUpperCase();
  
  if (intent === "TALK TO AGENT") {
    const psClient = new PingstreamsClient();
    
    psClient.getQueueStatus(function(queueInfo) {
      var df_res = {};
      
      if (queueInfo.isOpen && queueInfo.availableAgents > 0) {
        df_res['fulfillmentText'] = "Connecting you to an available agent now!\\agent";
      } else if (queueInfo.isOpen && queueInfo.queueLength < 5) {
        df_res['fulfillmentText'] = `We are open but all agents are busy. Current wait time is approximately ${queueInfo.estimatedWait} minutes.\\agent`;
      } else if (queueInfo.isOpen) {
        df_res['fulfillmentText'] = "We are experiencing high volume. Would you prefer to schedule a callback or continue waiting?";
      } else {
        df_res['fulfillmentText'] = "We are currently closed. Our support hours are 9 AM to 5 PM, Monday through Friday.";
      }
      
      res.status(200).send(JSON.stringify(df_res));
    });
  }
});
  • Always inform users about current status (open/closed)
  • Provide specific information about when agents will be available
  • Offer alternatives when agents are unavailable
  • Collect user information for follow-up when closed
  • Offer self-service options during off-hours
  • Provide clear escalation paths for urgent issues
  • Set appropriate expectations about response times
  • Provide multiple contact options when available
  • Maintain brand voice even in automated responses

You can further enhance this system by:

  1. Holiday schedules: Account for special business hours during holidays
  2. Department-specific hours: Different operating hours for different support teams
  3. Urgency detection: Route urgent requests differently even during off-hours
  4. Callback scheduling: Allow users to schedule callbacks during business hours
  5. Multi-language support: Provide operating hours messages in multiple languages

This approach ensures that users always receive appropriate and helpful responses, regardless of when they need assistance.

Enjoy Pingstreams!