Embedding watsonx Assistant in Flutter web app
Background
IBM’s Watsonx Assistant, a powerful AI-driven conversational agent, offers robust capabilities for building intelligent chatbots that can enhance user engagement and streamline customer service. On the other hand, Flutter, an open-source UI software development kit by Google, has gained significant traction for its ability to craft natively compiled applications for mobile, web, and desktop from a single codebase.
Recently, during one of the partner engagements, we came across the requirement where we had to integrate the watsonx Assistant into the Flutter web app. Also, the assistant should show only when the user is logged in to the web app. It should disappear when the user logs out.
Prerequisites
- watsonx Assistant instance
- Flutter
Challenges
I recently encountered a need to integrate the Watsonx Assistant into a Flutter web app. There were a few more challenges:
- The chatbot should be accessible only to logged-in users. It should disappear upon logout.
- The chatbot should be a widget in the Flutter web app. It should open in the same screen, not a separate window.
Approach
To meet this need, we will use the approaches to integrate watsonx assistant and authentication in the web app and chatbot.
- In the login screen, user will be asked to enter the login credentials.
- Once the user is successfully logged in, the server will return the username and email address. In the
pre:send
event of assistant we can update variable calleduser_name
of logged-in user. - Another approach to enable web chat security is passing JWT token in the assistant. This is altogether a different approach and implementation. Click here for more information on securing the watsonx Assistant.
- As we need to open the assistant within the web page, we will use JavaScript to load the assistant. To show and hide the assistant widget, Dart language in Flutter provides flexibility to call JavaScript functions from Flutter’s screen file. This will work only for Flutter web apps and is not a recommended approach for iOS or Android apps.
Implementation
Assuming that you have already created flutter project. As we are developing a web application, you will find a folder named web in the project directory.
Create a new JavaScript file under the web
folder and name it wa_script.js . Copy the content of file from this GitHub link.
Here we have a function called loadWaInstance
with parameters showAssistant
and userName
. This loadWaInstance
will be called from the login screen’s dart file after user authentication.
The showAssistant
parameter is a flag value that determines whether to show or hide the assistant, and userName
is a parameter that holds the name of the logged-in user. This value of userName
parameter will be sent to assistant to populate the assistant’s variable user_name
.
The web page requires the code block in the wa_script.js to load the assistant.
window.watsonAssistantChatOptions = {
integrationID: "e7c442dd-15f3-4020-xxxx-xxxxxxxxx", // The ID of this integration.
region: "us-south", // The region your integration is hosted in.
serviceInstanceID: "33c5b784-0bec-xxxx-xxx-xxxxxx", // The ID of your service instance.
onLoad: function (instance) {
instance.render();
window.WebChatInstance = instance;
instance.on({ type: 'pre:send', handler: preSendHandler });
// https://cloud.ibm.com/docs/watson-assistant?topic=watson-assistant-web-chat-develop-set-context
function preSendHandler(event) {
if (event.data.input && event.data.input.text === '') {
event.data.context.skills['actions skill'] = event.data.context.skills['actions skill'] || {};
event.data.context.skills['actions skill'].skill_variables = event.data.context.skills['actions skill'].skill_variables || {};
event.data.context.skills['actions skill'].skill_variables.user_name = userName;
}
}
},
showLauncher: true, // Hide the web chat launcher, you will open the WebView from your mobile application
openChatByDefault: false, // When the web chat WebView is opened, the web chat will already be open and ready to go.
hideCloseButton: false // And the web chat will not show a close button, instead relying on the controls to close the WebView
};
You will need to update integrationID, region, and serviceInstanceID from your assistant. Click here for more information on embedding the assistant in a web page.
The function preSendHandler
will run when the user sends a message to the chatbot. By writing instance.on({ type: ‘pre:send’, handler: preSendHandler });
we register the function preSendHandler
on the assistant’s pre:send
event.
Click here to know more about the events and methods exposed by watsonx Assistant. You can use these events and methods for any customisation.
Till here, we are good with the JavaScript part. The next step is to add wa_script.js JS file in index.html to use it in the web application.
Open index.html
file under web
folder, and add below line in <head>
tag.
<!-- Watson assistant script -->
<script src="wa_script.js" defer></script>
Now we are all set from the JS side; the next step is to design a screen that contains a login button. Assume that clicking the login button calls a REST API to authenticate with static info. You can add input fields to get username and password information.
Copy the code from this link and replace the content of the main.dart
file.
Run the project; on running, you should see the main screen as in the screenshot below.
In the main.dart
file, the _login
function will trigger when the user clicks on the Login button on the page.
This function will store users’ name and email in shared preference.
We need to load the assistant once the user has successfully logged in. To do so, below line of code is responsible to call JavaScript method from dart file to JS file.
js.context.callMethod("loadWaInstance", [userLoggedIn, 'Test User']);
To use js.context.callMethod
, first you need to import dart:js
in your main.dart file by adding the line below.
import 'dart:js' as js;
js.context.callMethod
takes two arguments. They are: the name of the JS function, and an array of parameters for that function. We want to call loadWaInstance
. It should show/hide the assistant and use the logged-in user’s name.
After the Login button is clicked, we assume the user has logged in. We then call loadWaInstance
to show watsonx Assistant.
We click the Logout button, triggering the same function call. But this time we clear the session in shared preferences and set the False value in the flag to hide the assistant. In this, we also call the destroy function of watsonx Assistant.
js.context.callMethod("loadWaInstance", [false]);
In the actual scenario, you should take the user’s credentials in the Login function to make a REST API call for authentication.
Conclusion
This guide demonstrates how to integrate watsonx Assistant into a Flutter web app. watsonx Assistant offers great flexibility, allowing seamless integration across various channels and programming languages.
Full code can be downloaded from here.