For any Freshworks product that allows its users to automate their workflows, developers can now define their custom logic amidst this workflow. We call it Custom Actions. This feature will allow the app to be the central component of Action defined by the user.
Typical examples of custom actions in the workflow are,
Freshcaller has Call Workflows built-in for users to automate tasks by interconnecting actions. Automating Call Routing is something we are going to look at today. We will accomplish this by defining custom actions that are suitable to each use case.
Run the following command to create a boilerplate serverless app.
fdk create --products freshcaller --template your_first_serverless_app
The project files required for the serverless app are created. For more information, refer to the documentation. Let's start defining the actions that need to be performed.
The actions that can be included as part of an automated workflow must be defined as an action in the actions.json file. The action names are keys to callback functions.
actions.json
. The file content must follow the JSON schema.validateVIPPhoneNumber
and respondOrderStatus
actions and the corresponding attributes. Refer to the documentation for the format. For now, you can copy and paste the following code into the file.{
"validateVIPPhoneNumber": {
"display_name": "validate VIP users based on phone numbers",
"description": "Validates if the input phone number is in the VIP list of contacts",
"parameters": {
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"input": {
"type": "string"
}
},
"required": [
"input"
]
},
"response": {
"type": "string"
}
},
"respondOrderStatus": {
"display_name": "to send the message to be played as a dynamic message in Freshcaller",
"description": "Responds with the order status from third-party system",
"parameters": {
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"input": {
"type": "string"
}
},
"required": [
"input"
]
},
"response": {
"type": "string"
}
}
}
We have listed two properties in the actions.json file.
Each property is a description of inputs and outputs of a serverless callback that we will define in our app.
When the user configures these properties as part of Call Workflows within Freshcaller, the callback defined within the "server.js
" is invoked.
Navigate to the "server.js
" file and define the callback functions corresponding to the actions defined in the actions.json
file.
As an acknowledgment of the automated workflow, the actions should return a result. In the server.js
file, use the renderData()
method to return the result of the callback function to the workflow from where the function is triggered, through actions. If the callback function succeeds, it returns a response data object as the second argument of the renderData() callback. Otherwise, it returns an error object with a status and message as the first argument of the renderData()
callback.
In the callback functions, we will do the following operation before returning the results.
This function will validate if the incoming phone number is a VIP number and return the result if it's valid or invalid.
This function will validate if the appropriate product is chosen from IVR and return an error if proper input is not received.
Upon receiving the right product input, it will return the status of the respective product. In our case, we will always send it as "in progress".
Use the following code to define these functions in the "server.js
" file.
exports = {
validateVIPPhoneNumber: function (request) {
let validVIPNumbers = ['+15684561239','+12587419632'],
response = validVIPNumbers.includes(request.input) ? 'valid': 'invalid',
data = {
response,
"app_variables": {}
};
return renderData(null, { data });
},
respondOrderStatus: function (request) {
const productIndex = request.input
const productName = ['Freshcaller', "Freshdesk", "Freshsales", "Freshchat", "Freshservice"];
if (productName(productName) === -1) {
const error = { status: 404, message: "The selected product is not found. Choose a valid product." };
return renderData(error)
}
return renderData(null, {
success: true, data: {
response: request.input, "app_variables": { "name": productName[productIndex], status: "in progress" }
}
});
}
}
After your app is published and integrated with Freshcaller, when you design a Call Workflow using the routing automation, the custom actions configured in the app are listed as functions when the app is selected.
We will test the custom actions separately by simulating the actions and check the actual results from the app with the expected results.
You can simulate a workflow trigger and test your app from the testing page (http://localhost:10001/web/test).
fdk run
command. A message with the test URL is displayed.actions.json
file are displayed in the Select action drop-down list.Positive : Note: You can modify the payload values before clicking on the Simulate button to validate the app thoroughly. You can test the app with various test scenarios such as, adding a user whose account does not exist, adding a user to an organization that does not exist, and so on.
For more information on how to test the workflow actions, refer to the documentation related to testing.
Yes, we all want to test the app once in production to make sure everything works when the environment changes. Also, this app requires configuration in Freshcaller to make the app work coordinated.
We are not going to cover the steps required to configure the workflow in Freshcaller. To test in a production environment by publishing the app as a custom app, configure the workflow in Freshcaller to run custom actions from a custom app.
We have learned to use custom actions in Routing Automation to automate some of the mundane tasks that would usually take valuable time and efforts of agents working at the other end of the user.
Here's what we learned in this tutorial,
See the final source code of the app.
If you are excited to use custom actions to automate certain tasks, play with the same app to achieve different things.