Server Actions
Notice the turquoise node in the image above: it is a placeholder for what we call a "Server Action". It triggers a piece of code that lets your conversational model connect to any other service in the world (e.g. Slack, Google Sheets or your own server) as soon as your user's conversation reaches the server action node. You could use this to forward specific requests to your email account or send open request tickets to a dedicated support system.
Popular services like Slack or Mailchimp have already been implemented and are ready to use off-the-shelf. You can hook them up in your execution tree by simply selecting "Add Action" in the node menu.
If you are missing a popular integration, let us know. We are happy to help!
Using state with Server Actions
Let's say you want to forward a contact request to a Slack Channel in your Slack Workspace. How would you go about to send the user information (e.g. the email address)? The solution is straight forward. The message text can be defined as follows:
new contact request from #name (#email): #message
Assuming you have email
, name
and message
defined as state keys the slack message will be rendered with the user's state information. An example could be:
new contact request from John (john.doe@example.com): Your website looks amazing :)
PS: You can use this technique to interpolate state keys for all kinds of different service integrations and also in the Node Editor.
Development and Production
When defining server actions you'll notice two different modes: 'development' and 'production'. You are supposed to fill out fields in both modes. Often, the definitions (i.e. what you type into the fields) of both modes are equal. However, sometimes you might want to distinguish between a development setup and a production setup. For example, at Zircel we use dev-channels to test and develop our Slack integrations. And maybe you'll need to distinguish between development and production systems.
In the user interface, you'll find a button to trigger both a 'development-test' and a 'production-test'. Other than that, the 'production' mode is used once you release your conversational model. In the preview, server actions will use the 'development' definitions.
Writing Custom Webhooks
Not finding the right service integration? Write your own!
Defining a custom server action
- Webhook URL: the url of your service endpoint
- Private Secret: a private secret that lets you authenticate a real webhook call from a fake one.
- Configuration: A dictionary to add private key-value pairs that you can use to configure your endpoint. You can place in here API keys, email addresses or other private properties you want to propagate to the endpoint without it being visible to your users.
- Exit Nodes: simple string labels/identifiers that are used by the conversational model to determine where to continue a users' conversation. A popular choice for an exit node is 'success' to indicate the webhook call went well or 'error' when the connection failed or another error occurred.
Webhook Request
If everything is defined correctly in the previous step you should be able to receive a json object in the request payload of the following form at your endpoint:
{ state, secret, mode, config }
Property | Definition |
---|---|
state | An object dictionary with the state of the user conversation. |
secret | the generated secret |
mode | either 'production' or 'development' |
config | An object dictionary comprising the key-value pairs defined in the UI before. |
Webhook Response
Let's say you have defined two exit nodes 'success' and 'error'. You can continue the conversation after the webhook call has been processed by specifying where the conversation should go next. It can either go to 'success' or to 'error'. Simply return a json response with a goto
property (here a Node.js/Express example):
res.send({ goto: 'success' })
One can update/import state with server actions too:
res.send({ goto: 'success', state: { name: 'Max', age: 41 } })
Notice the state
property in the returned json object: it contains a dictionary of state keys. In the above example we update/set two keys: name and age. Keep in mind that you cannot add arbitrary state keys to your state dict. Every key you want to import must be reflected by a state key definition.