I’ve described in a previous post why Facebook Messenger is a great front-end for Rasa chatbots. Rasa provides a decent interface to communicate with Facebook Messenger and hooking up Facebook Messenger as a front-end is relatively straightforward with help from ngrok.
Facebook Messenger provides a clean, streamlined interface for your chatbot. The downside is that as a developer you only get a small set of native controls and display options, including:
What if you need to give your users a richer experience than you can get with vanilla Facebook Messenger? You can take advantage of webview to display full-blown web pages in the context of a Messenger session.
Webview is powerful, but it takes several steps to get the round trip working from Rasa through Facebook Messenger to webview. This article reviews a simple example that shows how you can exploit webview in a Rasa chatbot with Facebook Messenger. You can find the code associated with this example in this repo.
To demonstrate the steps required to take advantage of webview with a Rasa chatbot, we’ll create a very simple “province flag” chatbot that follows this flow:
- Ask the user which province they want to see. The chatbot accepts variations on one of two responses from the user: Ontario or Quebec.
- Once the user provides a response, the chatbot shows a button with the province’s name.
- When the user clicks on the button, webview opens showing a web page with the flag of the province and a brief description.
This is a very simple user experience, but there’s a lot happening behind the scenes, as shown in the following diagram:
The Rasa model uses a Python custom action file that:
- Reads in a config file that contains the details that will be shown in webview (province name, link to flag image, description of flag)
- Reads the slot that contains the province, builds a URL string from the contents of the config file associated with this province, and sends a payload to Facebook Messenger to create a button that will launch a webview.
Ngrok, specifically Pro or Business package, is central to the whole solution:
- First, ngrok makes the port that Rasa is listening on accessible to Facebook Messenger (as described in this article).
- Second, ngrok provides a fixed https URL associated with the localhost port used by the Flask server. This is essential — the button to launch webview won’t work unless it is associated with an https URL.
I tried various schemes to get Flask to serve an https URL, but the only thing that worked was getting a paid ngrok license. The paid ngrok license solved several problems by allowing me to have two active ngrok sessions (one for Rasa to Facebook Messenger, and one for Flask) and to have Flask serve the https URL demanded by Facebook Messenger.
The Flask module contains simple code that reads the parameters from the URL that was built in the custom action and uses them to generate the parameters needed in the web page that is displayed in webview:
Finally, the web page itself contains simple HTML that uses the parameters to show the province’s name, flag, and flag description:
This article has described a simple example of how you can take advantage of the flexibility of webview to augment the user experience of a Rasa chatbot in Facebook Messenger. The end-to-end example uses parameter values read in by the Python custom action to ultimately generate a dynamic web page served by Flask with formatted text and graphics displayed in webview, all without leaving the context of Facebook Messenger. The solution depends on ngrok to provide two tunnels to localhost (one for Rasa to Facebook Messenger communication, and one for Flask to serve the web page as https).
You can find all the code described in this article in this repo. Note that you will need to update the following two files:
verify: <your verify token>
secret: <your secret>
page-access-token: <your page access token>
- custom_action_config.yml — update wv_url to the URL for your own web page — as mentioned above this needs to be https or Facebook Messenger won’t allow it to be displayed in webview.
wv_url: <your https-enabled URL for Flask>