Understand fulfillment by integrating Dialogflow with Calendar

1. Before you begin

In this codelab, you'll learn how Dialogflow connects with backend systems to provide rich and dynamic responses to users' questions.

Prerequisites

Before proceeding, you need to complete the following codelabs:

  1. Build an Appointment Scheduler with Dialogflow
  2. Integrate Dialogflow with Actions on Google
  3. Understand entities in Dialogflow

You also need to understand the basic concepts and constructs of Dialogflow, which you can glean from the following videos found in the Build a chatbot with Dialogflow pathway.

What you'll learn

  • What is fulfillment
  • How to set up a service account for Calendar
  • How to set up Calendar
  • How to enable fulfillment in Dialogflow
  • How to test fulfillment

What you'll build

  • Fulfillment using Cloud Functions
  • An integration between Dialogflow and Calendar

What you'll need

  • A web browser and an email address to log into Dialogflow console
  • A Google Account to access Calendar

2. What is fulfillment?

Fulfillment is code that's deployed as a webhook that lets your Dialogflow agent call business logic on an intent-by-intent basis. During a conversation, fulfillment allows you to use the information extracted by Dialogflow's natural-language processing to generate dynamic responses or trigger actions on your backend. Most Dialogflow agents make use of fulfillment.

The following are some examples of when you can use fulfillment to extend an agent:

  • To generate dynamic responses based on information looked up from a database
  • To place orders based on products that a customer asked for
  • To implement the rules and winning conditions for a game

3. Enable Calendar API

  1. In the Dialogflow console, click d7d792687e597dd5.png.
  2. In the General tab, scroll to Project ID, then click Google Cloud f2bffd4fcdb84fa9.png.

34be16fcd4c5aeff.png

  1. In the Google Cloud Console, click Navigation menu ☰ > APIs & Services > Library.
  2. Search for "Google Calendar API," then click Enable to use the API on your Google Cloud project.

4. Set up service account

  1. Click Navigation menu ☰ > APIs & Services > Credentials.
  2. Click Create Credentials > Service account.

86f51af0e7886fdd.png

  1. In the Service account details, enter "appointment-scheduler" as the Service account name, then click Create.

845d25f3e07ff770.png

  1. Where it says Grant this service account access to project, click Continue to skip it.
  2. Where it says Grant users access to this service account (optional), click Create Key, then select JSON and click Create.

A JSON file will download to your computer, which you'll need in the following setup sections. a424cec60144d707.png

5. Calendar setup

  1. Navigate to Calendar, then click Main menu ☰ > Add other calendars fbc354048b0a2c6c.png> Create new calendar.

d6ec2fcf0bd2ae22.png

  1. Enter "Appointment Calendar" as the name of the calendar and click Create calendar.
  2. Reload the page, then click Appointment Calendar, scroll to Share with specific people, then click Add people.
  3. Copy the client_email from the JSON file that you downloaded as a part of the service account setup and paste it into the dialog.

7927f6fa675e3e87.png

  1. Click the Permissions drop-down list, then click Make changes to events > Send.

2ee99d3d15eed97b.png

  1. While still in Settings, scroll to Integrate calendar and copy the Calendar ID.

df8a731f0713c52.png

6. Set up fulfillment in Dialogflow

Add service account and Calendar ID to fulfillment

  1. Navigate to the AppointmentScheduler Dialogflow agent and click Fulfillment.
  2. Enable the Inline Editor.

c8574c6ef899393f.png

  1. Update the index.js file with the following code:
'use strict';

// Import the Dialogflow module from Google client libraries.
const functions = require('firebase-functions');
const {google} = require('googleapis');
const {WebhookClient} = require('dialogflow-fulfillment');

// Enter your calendar ID below and service account JSON below
const calendarId = "<INSERT YOUR CALENDAR ID>";
const serviceAccount = {<INSERT CONTENTS OF YOUr JSON FILE HERE>}; // Starts with {"type": "service_account",...

// Set up Google Calendar Service account credentials
const serviceAccountAuth = new google.auth.JWT({
 email: serviceAccount.client_email,
 key: serviceAccount.private_key,
 scopes: 'https://www.googleapis.com/auth/calendar'
});

const calendar = google.calendar('v3');
process.env.DEBUG = 'dialogflow:*'; // enables lib debugging statements

const timeZone = 'America/Los_Angeles';
const timeZoneOffset = '-07:00';

// Set the DialogflowApp object to handle the HTTPS POST request.
exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
 const agent = new WebhookClient({ request, response });
 console.log("Parameters", agent.parameters);
 const appointment_type = agent.parameters.appointment_type;
 function makeAppointment (agent) {
   // Calculate appointment start and end datetimes (end = +1hr from start)
   const dateTimeStart = new Date(Date.parse(agent.parameters.date.split('T')[0] + 'T' + agent.parameters.time.split('T')[1].split('-')[0] + timeZoneOffset));
   const dateTimeEnd = new Date(new Date(dateTimeStart).setHours(dateTimeStart.getHours() + 1));
   const appointmentTimeString = dateTimeStart.toLocaleString(
     'en-US',
     { month: 'long', day: 'numeric', hour: 'numeric', timeZone: timeZone }
   );
    // Check the availability of the time, and make an appointment if there is time on the calendar
   return createCalendarEvent(dateTimeStart, dateTimeEnd, appointment_type).then(() => {
     agent.add(`Ok, let me see if we can fit you in. ${appointmentTimeString} is fine!.`);
   }).catch(() => {
     agent.add(`I'm sorry, there are no slots available for ${appointmentTimeString}.`);
   });
 }

// Handle the Dialogflow intent named 'Schedule Appointment'.
 let intentMap = new Map();
 intentMap.set('Schedule Appointment', makeAppointment);
 agent.handleRequest(intentMap);
});

//Creates calendar event in Google Calendar
function createCalendarEvent (dateTimeStart, dateTimeEnd, appointment_type) {
 return new Promise((resolve, reject) => {
   calendar.events.list({
     auth: serviceAccountAuth, // List events for time period
     calendarId: calendarId,
     timeMin: dateTimeStart.toISOString(),
     timeMax: dateTimeEnd.toISOString()
   }, (err, calendarResponse) => {
     // Check if there is a event already on the Calendar
     if (err || calendarResponse.data.items.length > 0) {
       reject(err || new Error('Requested time conflicts with another appointment'));
     } else {
       // Create event for the requested time period
       calendar.events.insert({ auth: serviceAccountAuth,
         calendarId: calendarId,
         resource: {summary: appointment_type +' Appointment', description: appointment_type,
           start: {dateTime: dateTimeStart},
           end: {dateTime: dateTimeEnd}}
       }, (err, event) => {
         err ? reject(err) : resolve(event);
       }
       );
     }
   });
 });
}
  1. Replace <INSERT YOUR CALENDAR ID> with the Calendar ID that you copied in the previous section.
  2. Replace <INSERT CONTENTS OF YOUR JSON FILE HERE> with the contents of your JSON file.
  3. (Optional.) Change the const timeZone and const timeZoneOffset as per the timezone for Appointment Calendar.
  4. Click Deploy.

Enable fulfillment response

  1. Navigate to the Dialogflow console and click Intents.
  2. Click Schedule Appointment Intent.
  3. Scroll down to Fulfillment and turn on Enable webhook call for the intent.

a5b41336b5249e44.png

  1. Click Save.
  2. Click Deploy.

7. Test your chatbot

You can test your chatbot in the Actions simulator, or use the web or Google Home integration that you previously learned about.

  1. User: "Set an appointment for vehicle registration at 2 PM tomorrow."
  2. Chatbot: "Ok, let me see if we can fit you in. April 24, 2 PM is fine!"

96d3784c103daf5e.png

  1. Calendar books the response.

b7da9da814271db8.png

8. Clean up

If you're planning to complete other Dialogflow codelabs, then skip this section for now and return to it later.

Delete the Dialogflow agent

  1. Click dc4ac6f9c0ae94e9.png next to your existing agent.

520c1c6bb9f46ea6.png

  1. In the General tab, scroll to the bottom and click Delete This Agent.
  2. Type Delete into the dialog and click Delete.

9. Congratulations

You created a chatbot in Dialogflow and integrated it with Calendar. You're now a chatbot developer!

Learn more

To learn more, check out the code samples on the Dialogflow Github page.