Echo Dot (3rd Gen) - Smart speaker with Alexa - Charcoal

Use your voice to play a song, artist, or genre through Amazon Music, Apple Music, Spotify, Pandora, and others. With compatible Echo devices in different rooms, you can fill your whole home with music.

Buy Now

Wireless Rechargeable Battery Powered WiFi Camera.

Wireless Rechargeable Battery Powered WiFi Camera is home security camera system lets you listen in and talk back through the built in speaker and microphone that work directly through your iPhone or Android Mic.

Buy Now

Create Fulfillment Webhook Using Python + Django


Pragnakalp Techlabs

Dialogflow’s fulfillment feature is a very powerful feature which enables Dialogflow agent to communicate with our server. It comes in very handy when we want to use any data from our database or third party source in our Diagflow based chatbot.

To utilize Dialogflow Fulfillment, we need to create a webhook URL which will be a communication point for Dialogflow agent. There are multiple ways to create webhook and one we have already discussed in our previous blog: Dialoflow webhook tutorial using Python + Flask. Today, we are going to go through webhook creation using Python only but this time with Django. Django is a popular web framework in Python. It is being used by many big websites/organizations in the world and many developers prefer it due to its built-in development features.

So, let’s get started! We’ll start from the very basic.

Download and install python from here as per your supported OS.

Once Python is setup, installing Django is very easy. Though, the steps required for its installation depends on your operating system. It can be easily installed using PIP

pip install Django

After installation, we need to create a project.

Open terminal or cmd prompt and navigate to the place where you want to create a project, then run below command in terminal or cmd:

django-admin startproject djangotest

This will create “djangotest” project with following directory structure:


Now that your project is created, to make it work, you need to apply migrations for app. First browse to the “djangotest” directory by

cd djangotest

command and then run below command to apply them.

python migrate

You should get the result as below or similar on running the above code.

Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying admin.0003_logentry_add_action_flag_choices... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying auth.0009_alter_user_last_name_max_length... OK
Applying auth.0010_alter_group_name_max_length... OK
Applying auth.0011_update_proxy_permissions... OK
Applying sessions.0001_initial... OK

Project creation is done. A Django project can have multiple applications so we need to create an application for our webhook. To do that, navigate to “djangotest” directory in terminal or cmd and run below command to create an app.

python startapp myapp

“myapp” is the name of the application we created. You can provide a name whatever you want. This command creates a “myapp” folder with the following structure


Now we need to register our newly created app with our project “djangotest”. To do this open /djangotest/ file and add app name.


Let’s first create a normal page which will display Hello World! message.

To do that, we need to define a function in /djangotest/myapp/ file

from django.shortcuts import render 
# import HttpResponse to view result
from django.http import HttpResponse
# define home function
def home(request):
return HttpResponse('Hello World!')

Now, route needs to be defined in /djangotest/djangotest/ file.

from django.urls import path 
from myapp import views
urlpatterns = [
# define a route for home
path('home/', views.home, name='home'),

We are all set! Time to kickoff the application executing below command:

python runserver

You should get the result as below or similar on running the above code.

System check identified no issues (0 silenced). 
May 16, 2019 - 20:28:26
Django version 2.2.1, using settings djangotest.settings'
Starting development server at
Quit the server with CTRL-BREAK.

Open the browser and access You should see output as below.

Congratulations! Our Django app is working now. But as it is on a local system it can not be accessed from the outside world. To integrate it as webhook for Dialogflow, we need to make it live/online. For that, we will use ngrok.

Ngrok is a web tunneling tool that can be used to call webhook from your local server. You can download Ngrok from

After installing ngrok, use the following command: ngrok http <port number>

In our case, django app is running on port 8000 so port number will be 8000

ngrok http 8000

It will have output as below

Ngrok generates a random URL for the local server. To run a local server by this URL we need to add this URL in ALLOWED_HOSTS in /djangotest/djangotest/


After adding this URL we can access a local server from the outside world.

First, we need to create a /webhook URL which we’ll provide as a Fulfillment URL in Dialogflow. To do that, let’s add a “webhook” route in the /djangotest/djangotest/ file so file would look like below:

from django.urls import path 
from myapp import views
urlpatterns = [
# define a route for home
path('home/', views.home, name='home'),
path('webhook/', views.webhook, name='webhook'),

Dialogflow expects a response from webhook in particular JSON format which will be parsed and proper output will be displayed to user.

We are going to build some responses in python using these formats. Types of available responses are: Simple Response, Basic Card, Suggestions, List Card, Browse Carousel, Carousel Response.

Below code will prepare a simple JSON response with fulfillment text for Dialogflow. The user will receive “This is Django test response from webhook.” as a response when webhook will be called.

We need to edit /djangotest/myapp/ file and add the code to handle requests coming on /webhook url.

The file should look like below.

from django.shortcuts import render 
from django.http import HttpResponse, JsonResponse
from django.views.decorators.csrf import csrf_exempt import json
# define home function
def home(request):
return HttpResponse('Hello World!')
def webhook(request):
# build a request object
req = json.loads(request.body)
# get action from json
action = req.get('queryResult').get('action')
# return a fulfillment message
fulfillmentText = {'fulfillmentText': 'This is Django test response from webhook.'}
# return response
return JsonResponse(fulfillmentText, safe=False)

NOTE: CSRF_exempt is required by Django to provide easy-to-use protection against Cross-Site Request Forgeries.

Dialogflow provides an option on the left sidebar known as Fulfillment. Just enter your webhook url generated by ngrok on fulfillment page and you are done.

Make sure you are adding url /webhook not just ngrok URL. So, it should look like

Now, we need to enable the webhook for intents that needs to communicate with our server data. To do that, open the intent for which you want to enable webhook, scroll down to the end and enable the “Enable webhook call for this intent” switch.

Whenever this intent is invoked, it will send a request to your webhook and respond as per the response set from the webhook.

Training phrases are the sentences that help the agent to identify/invoke the particular intent.

Action can be used in our webhook to process request. We have multiple intents that invoke webhook in this case we use an action to identify intent and based on this we prepare responses.

Using console on the right side of the window, we can invoke the intent and check the response. For our example, the response will be as below:

Clicking on “DIAGNOSTIC INFO” button, we can view all detail about the request being sent from Dialogflow and response being sent from our webhook. “DIAGNOSTIC INFO” can also be very useful for debugging, if you have any error in your webhook.

Simple webhook is created. Now if you want to add other types of responses in webhook then, you can create JSON as per your requirement. Refer to this response samples for more details.

We have created Python Library to simplify building the JSON responses for Dialogflow. We will explain here how to integrate this library with Django and easily create different types of responses quickly.

Apart from Simple Response there are other types of responses possible for Google Assistant as listed below:

  • Suggestion chips
  • Basic card
  • List
  • Link out suggestion
  • Carousel card

Let’s explore Suggestion Chips.

Create intent for suggestion chips. In our example, we have created intent “Suggestion chips example”. In the intent, add training phrases which will be used to invoke this intent.

Then enable “Enable webhook call for this intent” option. And set action “get_suggestion_chips” which will be used in webhook code to differentiate response.

Now our intent is ready. Next, we need to prepare a JSON response for suggestion chips.

As we are going to use Dialogflow webhook response library to generate a JSON response. Download this library and put it in /djangotest/library/ directory.

In our example we prepare responses in /djangotest/myapp/ so the code would be as below in file.

from django.shortcuts import render 
from django.http import HttpResponse, JsonResponse
#import csrf from CSRF protection
from django.views.decorators.csrf import csrf_exempt
#import df_library
from library.df_response_lib import *
#import json to get json request
import json
def webhook(request):
# build request object
req = json.loads(request.body)
#get action from json
action = req.get('queryResult').get('action')
# prepare response for suggestion chips
if action == 'get_suggestion_chips':
# set fulfillment text
fulfillmentText = 'Suggestion chips Response from webhook'
aog = actions_on_google_response()
aog_sr = aog.simple_response([
[fulfillmentText, fulfillmentText, False]
#create suggestion chips
aog_sc = aog.suggestion_chips(["suggestion1", "suggestion2"])
ff_response = fulfillment_response()
ff_text = ff_response.fulfillment_text(fulfillmentText)
ff_messages = ff_response.fulfillment_messages([aog_sr, aog_sc])
reply = ff_response.main_response(ff_text, ff_messages)
# return generated response
return JsonResponse(reply, safe=False)

Now, we need to run server using following command in terminal or cmd prompt.

python runserver

Using console on right side of the window, we can invoke the intent and check the response. For our example, the response with Suggestion Chips from webhook will be as below:

In this blog, we are going to cover Suggestion Chips only. We have created a github repository with code for all other types of responses. You can download the code from there and modify it as per your requirement.

Read More


Please enter your comment!
Please enter your name here