Dialogflow Python webhook tutorial

One of the things that I have mentioned before is that you need to have a programmer on your team if you would like to build a non-trivial Dialogflow bot. At the same time, all Dialogflow bot makers would still benefit from understanding the basics of webhooks.

This tutorial will be helpful if you are technical, but not a programmer. I will explain just enough about Dialogflow webhooks to make you dangerous. 😉

If you are a programmer, this guide will still be helpful if you are new to Dialogflow.

Hello World

Let us start with a simple Hello World program.

First, sign up for a free account at Repl.it.

Why repl.it?
I would like to take a small detour and explain why I am using repl.it and the things you should know before using the service.
Replit allows you to "run" your Python program without having to go through the process of "installing" Python on your local machine. If you haven't installed a programming language and all the associated tools on your local computer, you should know that this is a bigger barrier for most non-programmers than actually writing code. I wish I were joking, but I am not.
The link I have provided is a referral link, which will provide me with credits towards their service if you decide to ever upgrade.
An important thing to note is that you almost certainly wouldn't have to upgrade when you are in the learning mode.
Public vs private repls
All the repls are public by default on replit.
This means you should never, never, ever, even accidentally write any code which uses secret keys (e.g. Airtable API keys) in repl.it unless you know how to use the environment file. Because the second you write the code and click save, the entire code is publicly accessible to the rest of the world.
So one reason to upgrade would be to have private repls which no one can read. That way you can safely experiment with the code and even if you accidentally copy/paste your real secret keys into the repl, no one can read it.
Always-on repls
All publicly accessible repls automatically "go to sleep" after some period of inactivity. That is, they don't instantaneously load as they would if they don't go to sleep. This is why you can see that the page takes quite a long time to load.
When you upgrade, you get "always on" repls which don't go to sleep. This means they will load and serve your requests quickly.
In other words, if you use always-on repls, your Dialogflow webhook will never time out. :-) If you use the free repls, your webhook may time out when you access it the first time. By the time you access it the second time, usually your webhook code has "woken up" from its sleep and will work fine.
The "always-on" feature has not yet been implemented (the service is fairly new), but I heard from the repl.it team that they will be implementing it soon.
What this means for non-programmers
If you are building a tiny demo bot, and you don't mind if the code goes to sleep, you can actually use replit as a place to host your webhook code.

You can use your Google account to sign in.

Create a new Repl within your account. (For now, just think that a “repl” is basically a block of code – no need to overcomplicate it).

And select Python as the programming language.

Paste the following code into your Repl.

from flask import Flask
app = Flask(__name__)
@app.route('/') # this is the home page route
def hello_world(): # this is the home page function that generates the page code
    return "Hello world!"
    
@app.route('/about')
def welcome():
  return "Welcome to my Flask site, ©2018"
   
if __name__ == '__main__':
  app.run(host='0.0.0.0', port=8080) # This line is required to run Flask on repl.it

Alternatively, you can just fork (i.e. copy into your account) my code.

0 Make sure you are logged in to your Repl.it account

1 Click on the “Fork button” at the top of the page

2 Open the browser link you see on the top right. The URL generated for you will be based on your own Google account and will look different. I will refer to this as your page URL.

3 You should see the Hello World message show up in the browser window.

For example, in the example below, the page URL would be https://helloworld.soonerblog.repl.co

Did you see the “Hello, world” message?

You can do a further confirmation. Now append “/about” at the end of the page URL. You should see the message “Welcome to my Flask site, ©2018” like below.

Does it work as expected? Good, you have completed the first step!

Static response

Now, you are going to modify this repl.

You will be adding a response message which will be invoked by your Dialogflow agent.

First, create a Dialogflow agent and add this intent called add.numbers.

Use this checklist to make sure everything is fine:

  • when you type the training phrase add 3 and 4, Dialogflow should automatically “annotate” the two numbers (indicated by their color highlights)
  • there are two parameters called number and number1 created right below the training phrase with Resolved value 3 and 4
  • now add an action called add.numbers inside the Actions and Parameters section
  • verify there are the two parameters number and number1 in the Parameter table
  • make sure you select the “Enable webhook call for this intent” toggle at the bottom of the intent

Copy paste the entire code below into your repl. That is, replace all the existing code with the code below. Here is the code for reference. Notice that the page URL for my repl has become the following:

https://staticresponse.aravindmohanoor.repl.co/languages?embed=true#?secret=cTLOpj4LPR

Now, find your page URL and make a note of it.

from flask import Flask
app = Flask(__name__)
@app.route('/') # this is the home page route
def hello_world(): # this is the home page function that generates the page code
    return "Hello world!"
    
@app.route('/webhook', methods=['POST'])
def webhook():
  return {
        "fulfillmentText": 'This is from the replit webhook',
        "source": 'webhook'
    }
   
if __name__ == '__main__':
  app.run(host='0.0.0.0', port=8080) # This line is required to run Flask on repl.it

We have added a new method called webhook() and it just returns a static response. The response is the same regardless of what is sent to the webhook.

Now go to the Fulfillment section and add a fulfillment URL. The fulfillment URL should be your page URL followed by “/webhook”, as you can see below.

In the Dialogflow simulator, type the phrase

add 3 and 4

You should see one of two things:

If the response is

This message comes from the Dialogflow console.

then your webhook isn’t working yet.

On the other hand, if the response is

This is from the replit webhook

then your webhook is working.

If your webhook isn’t working, retrace your steps and make sure you haven’t made any mistakes.

If your webhook is working, then you have completed Step 2!

Just to confirm, now type add 5 and 6 into the Dialogflow simulator and verify that you get the response below:

In other words, the response coming back from the webhook should be the same, but the parameters shown under the ACTION section should be 5 and 6.

Dynamic response – sum of two numbers

So you are wondering – what is the use of calling a webhook if I just get the same response over and over?

For one thing, you have now established that your webhook is actually reachable from your Dialogflow agent. That might seem a trivial thing (once you have it working), but there are a lot of folks who don’t get the end to end flow working. And then they try and figure out what is wrong with their webhook code. They are often looking in the wrong place.

Second, once you get the webhook to respond to your Dialogflow agent with a static response, it isn’t a lot more work to get a dynamic response.

Copy the entire code into your repl:

from flask import Flask, request
app = Flask(__name__)
@app.route('/') # this is the home page route
def hello_world(): # this is the home page function that generates the page code
    return "Hello world!"
    
@app.route('/webhook', methods=['POST'])
def webhook():
  req = request.get_json(silent=True, force=True)
  sum = 0
  query_result = req.get('queryResult')
  num1 = int(query_result.get('parameters').get('number'))
  num2 = int(query_result.get('parameters').get('number1'))
  sum = str(num1 + num2)
  print('here num1 = {0}'.format(num1))
  print('here num2 = {0}'.format(num2))
  return {
        "fulfillmentText": 'The sum of the two numbers is: '+sum,
        "source": "webhookdata"
    }
    
   
if __name__ == '__main__':
  app.run(host='0.0.0.0', port=8080) # This line is required to run Flask on repl.it

You can check the code sample here to see if everything looks OK, but don’t fork the code. Because when you do, you will create a new repl and a new page URL, which you don’t want to do now. You want to keep using the old webhook URL in the fulfillment section.

Try to add two numbers in your Dialogflow simulator now:

You can see in the ACTION section that it extracted the two numbers just as you had expected. More importantly it calculated the correct sum and sent the information back to your Dialogflow agent.

If you have come this far, you already have an actual working webhook, where you are already doing real stuff.

Now, there is another question: what if I want to do two different types of calculations? What if I also want a webhook which can multiply two numbers?

Handling multiple intents in your webhook

So first of all, we need to define a new intent which is meant for multiplication.

Create a new intent called multiply.numbers with the following information:

Now copy the following code and paste it into your repl:

from flask import Flask, request
app = Flask(__name__)
@app.route('/') # this is the home page route
def hello_world(): # this is the home page function that generates the page code
    return "Hello world!"
    
@app.route('/webhook', methods=['POST'])
def webhook():
  req = request.get_json(silent=True, force=True)
  fulfillmentText = ''
  sum = 0
  query_result = req.get('queryResult')
  if query_result.get('action') == 'add.numbers':
    num1 = int(query_result.get('parameters').get('number'))
    num2 = int(query_result.get('parameters').get('number1'))
    sum = str(num1 + num2)
    print('here num1 = {0}'.format(num1))
    print('here num2 = {0}'.format(num2))
    fulfillmentText = 'The sum of the two numbers is '+sum
  elif query_result.get('action') == 'multiply.numbers':
    num1 = int(query_result.get('parameters').get('number'))
    num2 = int(query_result.get('parameters').get('number1'))
    product = str(num1 * num2)
    print('here num1 = {0}'.format(num1))
    print('here num2 = {0}'.format(num2))
    fulfillmentText = 'The product of the two numbers is '+product
  return {
        "fulfillmentText": fulfillmentText,
        "source": "webhookdata"
    }
    
   
if __name__ == '__main__':
  app.run(host='0.0.0.0', port=8080) # This line is required to run Flask on repl.it

Once again, here is a link to the code. And once again, it is for reference and you shouldn’t fork the code unless you want to also change the fulfillment URL.

Now try to add two numbers in the Dialogflow simulator:

Now multiply two numbers.

Did you get it to work?

That’s it! You now know enough about Dialogflow webhooks to be dangerous. 

Code walkthrough


Note: This is my old website and is in maintenance mode. I am publishing new articles only on my new website. 

If you are not sure where to start on my new website, I recommend the following article:

Is Dialogflow still relevant in the era of Large Language Models?

Leave a Reply