[[TOC]]
1. Use ngrok to expose your server
- Download and Install ngrok
- Use the command ngrok http <server port to expose> in terminal or cmd
- Note the HTTPS Forwarding URI
- Login to IntelAgent
- Go to Settings -> Webhook
- Set Endpoint to the forwarding URI from ngrok
- Note JWT Secret
- Initialise instance of
WebhookClient
from the sdk, providing JWT Secret as argument, to authenticate - Find handler-name from function block in IA
- handleRequest from Client, with the body of the event from the function block as stringified json, as well as the token
- Return response from handleRequest
- Using Visual Bot Builder in IntelAgent, add new Choice using plus buttons to the far left or right of the existing choices, or add to existing choice by using the plus button on said choice
- Choose New Block and then Function Block
- Give block a name, and pick module if applicable
- If function has not been implemented, leave Todo field ticked, and add Temporary Text, usually a description of function implementation, and add button to simulate response. If you want your webhook to receive an event when this block is hit by a user, "Todo" must be unchecked
- Pick Form from dropdown if applicable
- Pick Handler Name, note this as it is used when adding handlers to the
WebhookClient
- In IntelAgent go to the Forms tab
- Click add new form, and give form a descriptive title
- Add new question, or pick one from the question bank
- Give descriptive title to question
- Write question text, to be displayed when question is asked
- Pick input type given to the user, followed by data type
- A question can also be added to the question bank from the Question Bank tab
- Create instance of
WebhookHandler
- Add logic to handler
- Add handler to Client using addHandler(<handler-name>, handler)
A Handler is a container for logic, which is run when the Client receives a request for the specified function One handler is usually equivalent to one function
This is an example of a Handler implementation, final implementation can be found in the divide example project
For this case, the handler takes two number values from a Form created in IntelAgent, divides one with the other, and sends a block with the answer to the ChatBot
First a WebhookClient
is instantiated, using the JWT Secret. This is used to call the handler function
export const whClient: WebhookClient = new WebhookClient('secret');
Then a new WebhookHandler
is initiated
export const divisionHandler: WebhookHandler = async (
webhookReq: WebhookRequest,
responseBuilder: ResponseBuilder
): Promise<void> => {
// Logic goes here
}
The WebhookHandler
has two argument values, the WebhookRequest
and the ResponseBuilder
The WebhookRequest
is where information and data from the request is found, such as FormValues, if a form was used.
In this case there are two values from a Form
const {value: baseNumber} = webhookReq.formValue.baseNumber;
const {value: divisionNumber} = webhookReq.formValue.divisionNumber;
The above FormValues are structured as the following interface:
{
baseNumber: {
title: string,
value: string
},
divisionNumber: {
title: string,
value: string
}
}
Generally all Forms are structured similarly, containing the title and value of the question
Then the logic is implemented, in this case the result is the baseNumber divided by divisionNumber
const resultNumber = baseNumber / divisionNumber;
The ResponseBuilder
is how responses are sent back to the chat bot.
The ResponseBuilder
takes two different response types, Blocks and BlockPointers
A BlockPointer
points to an already existing Block using the Block Id, found in IA
Where possible this method should be used as it allows for block content to be edited easily without having to deploy changes to your code.
To use a BlockPointer
, the pushBlockPointer
function is used, with a BlockPointer
object, containing the id of a block, found on IntelAgent. This block can be a basic block, or a function block.
With the logic and result in hand, a BlockPointer is added to the responseBuilder, this points to a block containing the message "Ah, the result is...", to be displayed before the result is shown to the user
responseBuilder.pushBlockPointer({
id: "60db2d02d19a13bc109c5bd4"
});
Blocks can otherwise be built at run-time, using a subclass of BlockBuilder
these classes can be found within the sdk and are suffixed with BB e.g. BasicBB
Initialise a new instance of BasicBB
to start building a block.
const basicBB = new BasicBB();
Add text with the addText function, specifying a Language with the Languages Enum, if the text needs to be translated to different languages, do addText for each language. Here the text added is the result of the calculation done earlier
basicBB.addText(Languages.ENGLISH, `${resultNumber}!`);
A block can also contain buttons, or Choices. These can be added using the pushChoice function to push a ChoiceBuilder Block, of which there are several, depending on need. UrlCB links to a URL, BlockCB points to a BlockId. Here a button, that leads points back to the Menu, is added to the BasicBB with the result string
basicBB.pushChoice(new BlockCB("60e2b7f2ba7625f3fb73dd56").addTitle(Languages.ENGLISH, "Back to Menu"));
Some Choices that are used quite often, including the one above, has been pre-built so there is no need to build it repeatedly.
basicBB.pushChoice(backToMenu());
The UrlCB
works similarly to the BlockCB as a choice, however rather than point to a Block, it contains a URL.
basicBB.pushChoice(new UrlCB()
.addTitle(Languages.ENGLISH, "Google")
.addUrl(Languages.ENGLISH, "https://www.google.com/"));
The GalleryBB is used to show a list of elements, such as an array of products, or when info should be displayed in a particular way Each item in the GalleryBB is built using the ItemBuilder
const complexBB = new ComplexBB();
const ib = new ItemBuilder();
The ItemBuilder is used similarly to the BasicBB, in that a title, text, and Choices can be added They differ in the additional features, such as being able to contain an image, from a URL, and adding a subtitle
ib.image(<url>)
ib.addSubtitle(Languages.ENGLISH, "subtitle text")
complexBB.pushItem(ib)
If multiple items are added, each of these Items are be displayed in a Carousel, letting the user flip through them like a book, to find what they are looking for
The main functions used
The ResponseBuilder
can store multiple Blocks
and BlockPointers
, to be displayed in the Chat Bot, in the order they were added to the response.
If a Form was used, it may be necessary to unset it once finished, letting the user trigger the function again, with different input
responseBuilder.unsetFunctionForm();
If an input is invalid, or another error is caught, the responseBuilder
can return a functionFailure
,
responseBuilder.functionFailure(failureParams);
In the division handler one such case of invalid input, is a divisionNumber set to 0, a number that cannot be divided by as of yet, so that number is checked early in the function, before further logic
if (divisionNumber.value === 0) {
responseBuilder.functionFailure(failureParams);
return;
}
The failureParams object is a particular type used to indicate how to handle the error. It contains an error BlockPointer, pointing to a block with an error message, as well as two optional fields, resetForm
and tryAgain
, defaulting to true.
resetForm
indicates that the form should be unset, similarly to the unsetFunctionForm
function
tryAgain
offers a button to try again if true
const failureParams: FunctionFailureParams = {
errorBP: <error BlockPointer>,
};
Once Handler has been set up, add the handler to the WebhookClient
, when starting the server
whClient.addHandler('division-handler', divisionHandler);
Finally, call handleRequest with the request body, and the token and return the body with the status code from the client,
const { status, body } = await whClient.handleRequest(
req.body,
getToken(req)
);
res.status(status).send(body);
Code status | Stage | Rule | Example version |
---|---|---|---|
Backward compatible bug fixes | Patch release | Increment the third digit | 1.0.1 |
Backward compatible new features | Minor release | Increment the middle digit and reset last digit to zero | 1.1.0 |
Changes that break backward compatibility | Major release | Increment the first digit and reset middle and last digits to zero | 2.0.0 |
Changes to models involving both sdk and webuildbots changes require a major release as changing the sdk model will break the main repo.
##Making a pre-release (You might want to make a prerelease to test your SDK changes in another repo)
-
Make commit
-
npm version prerelease --preid <prelease identifier>
-
npm publish
-
Install on the other repo
npm i <npm identifier>
##Making a release
-
Create PR, make any necessary changes, verify PR
-
npm version <major | minor | patch>
-
Version command automatically commits, make sure to push new version to PR
-
Verify & Merge PR
-
git push upstream --tags
-
npm login
#only first time -
npm publish