Steps
Disclaimer
This is legacy documentation kept in place for a very specific audience. Please do not use these docs if you don't know the ins and outs of the Scripted Chatbot.
The newest version of the documentation can be found on Guru.
Specification
A CM Bot script consists of three properties on the top level of the
script. These are the 'id' property as well as the 'config' and
'flows' sections.
Below you'll find an example of the main skeleton of a script.
id: "0a532f29-422d-4e55-924a-809fd3a847fb"
config:
startPriority: 100
conversationOwners:
- identifier: 0031612345678
channel: WhatsApp
scriptLanguageVersion: 1
scriptVersion: 1
flows:
- id: flow1
description: "Entry flow"
steps:
- !entry
id: entry_step
matches: ["Hi", "hi"]
regexMatches: ["^(Hi|hi)$"]
isCaseSensitive: false
- !text
id: first_step
message: "First message"
Properties
- id This should be the same guid as the script id in the bot
configuration database/api. - config Configuration section where information is administered
on which number & channel the script will listen, versioning,
starting priority and predefined lists. - flows Section containing all the flows of the script. At least 1
flow with an EntryStep is needed to be able to start the script.
Config section
In the config section matters as script metadata, starting priorities
and (links to) dictionaries containing common words can be defined.
Below is a valid example for a complete config section:
config:
startPriority: 100
conversationOwners:
- identifier: 003197008101048
channel: WhatsApp
scriptLanguageVersion: 1
scriptVersion: 1
defaultDelay: 100
errorMessage: "Something unexpected occurred during the processing of this conversation."
sessionTimeout: 1440
lists:
positive-answers:
items:
- "qui"
- "top"
negative-answers:
source: negative-answers.yml
Properties
- startPriority Starting of a script is performed on a priority
basis where a lower number means a higher priority. The first script
that has a matching startSequence will be started. - conversationOwners This is the identifier for the host of the
conversation with the corresponding channel. This host can be an
MSISDN in case of SMS or WhatsApp or an arbitrary identifier like
with Apple Business Chat. - scriptLanguageVersion This integer number identifies the version
of the language that was used to create the script. For now this
should set to a fixed '1', because no multiple versions exist
yet. - scriptVersion This integer number defines the version of the
script, where the highest number is the most recent script. It
should match the version number as registered in the bot
configuration api. - defaultDelay This integer number specifies the number of
milliseconds to wait between handling steps. If your script runs too
fast, increase it. A very low number could have the side-effect of
messages not being in order on the end-user's side. - errorMessage This error message will be displayed to the end
user in case of a fatal error during processing of the script. - sessionTimeout Duration in minutes when the chat will be marked
as timed out. When exceeded the chat will start over when new input
is received. - lists This is a dictionary where named lists can be administered
either by defining the list itself as seen in the example, or by
referencing another yaml file with list entries. Working with
lists is NOT supported yet.
Flows
This section contains the actual script, which is divided into a
collection of flows. Each flow consists of a collection of steps of
different types.
A script will only be able to start if it contains at least one
so-called EntryStep. In this step you'll need to define which words or
sequences will start the script at that specific step. Although not
actively enforced, a flow should have at most one EntryStep. It's
perfectly fine to have a script with multiple flows containing a single
EntryStep. The script will start at the EntryStep that first (in order
of script appearance) matches the start sequence.
Below is an example of a skeleton for a flow with steps.
flows:
- id: flowX
description: "Flow x"
steps:
- !entry
id: entry_step
regexMatches: ["^(Hi|hi)$"]
isCaseSensitive: false
- !text
id: first_step
message: "First message"
Properties
- id This is a string identifying the flow.
- Use unique id's for every flow or the chatbot will fail
- do NOT use a dot '.' in the id. This isn't actively
enforced at the moment.
- description Small note for the script designer. Will not be
visible to end-users. - steps Section containing the steps that build up the script.
Steps
You can use a decent amount of different steps in your flows for
handling different messagetypes, script flow and other logic.
Properties for each type of Step
- id A value that uniquely recognizes that step within the script.
- It is currently not actively enforced that the 'id' value must
be unique. - Do NOT use a dot '.' in the id. This isn't actively
enforced at the moment.
- It is currently not actively enforced that the 'id' value must
- delay Integer value that specifies the waiting period in ms
before processing the next step. Currently this value is ignored and
the engine defaults to the script setting. - actions List of Action items specifying additional tasks to
perform. Actions will be discussed in the Actions paragraph.
Each of the supported steps will be explained in the following sections.
EntryStep
Object tag: !entry
The EntryStep is used to configure with which starting sequence (start
words) a script will start. The following applies:
- An EntryStep should be the first step of a Flow.
- Multiple EntrySteps in a single Flow are not allowed.
- A script could have multiple EntrySteps as long as each are in a
different Flow. - EntrySteps are matched in script order. The first one that matches
will be the starting point of the script.
To match a possible starting sequence, one or multiple regular
expressions can be configured which each allow the EntryStep to start
the script (so ANY of the regular expressions could match / concatenated
with OR).
steps:
- !entry
id: entry_step
regexMatches: ['^(Hi|hi)$']
isCaseSensitive: false
allowRestart: false
doCatchAll: false
Properties
- regexMatches A string array of possible regular expressions to
match. Named capture groups are allowed and will be available as
session variables on a succesful match. (todo: document capture
groups). - isCaseSensitive Will match the regular expression in a case
sensitive manner if true. - allowRestart Allows the script to restart the script in a new
session in case a previous session was already present. Defaults to
true. - doCatchAll Match on any input and does not restart a running
session (ignores regexMatches and isCaseSensitive)
A note on using regular expressions Using regular expressions in the
EntryStep opens the possibility to use so-called named capture groups: a
specific pattern within the matched sequence can be extracted or
'captured' and will be stored in a session variable that will have the
same name as the capture group. This will best be explained using an
example:
steps:
- !entry
id: entry_step
regexMatches: ['^Order (?<orderCode>\d{5})$']
isCaseSensitive: false
In the above example, all sequences starting with "Order", followed by
a space and exactly 5 digits will be matched. The named capture group is
specified between brackets (?<orderCode>
{=html}\d{5}) and the name of
the capture group is "orderCode". As a result, when the end-user
starts the chat with the text "Order 12345", a new session will be
started and a session variable 'orderCode' with value '12345' will
exist within the session.
The old (current) syntax below won't work with regular expressions but
by defining an array of starting words.
steps:
- !entry
id: entry_step
matches: ["Hi", "hi"]
isCaseSensitive: false
If you want to add an Catch All (other) flow in a script, add a flow to
the bottom of the flow list. And start with this entry step:
steps:
- !<!entry>
id: help_entry_step
regexMatches:
- '\s*\S[\s\S]*'
isCaseSensitive: false
allowRestart: false
ApplePayStep
Object tag: !apple_pay
steps:
- !apple_pay
id: ApplePayDemo010
merchantName: "CM.com for Dutch GP"
description: "Dutch GP Ticket Reservation"
orderReference: "b62d1014-1344-45ae-98cb-d876e8a4c1da"
recipientEmail: "[email protected]"
currencyCode: "EUR"
recipientCountryCode: "NL"
languageCountryCode: "nl"
billingAddressRequired: false
shippingContactRequired: false
lineItems:
- label: "DEMO EXPERIENCE FEE"
type: "final"
amount: 0.1
HandoverStep
Object tag: !handover
This step will actually send a message to the CM Bot Router to perform
some changes to the routing for this account. As a result messages from
and to the CmBot are cut off.
The following applies:
- Once a handover is performed, the bot itself lost control. In the
future we will support scenario's where a handover could be given
back to the bot. - The only currently supported scenario is a handover from cm bot to
Customer Contact. - Important For this to work the specific bot-account needs to be
whitelisted as well as mappings should be configured for the
channel-specific ChannelAccounts mappings for CustomerContact.
steps:
- !handover
id: handover_step
removeSources: ["CmBot"]
removeTargets: ["CmBot"]
routeTo: CustomerContact
Properties
- removeSources Array of string values indicating which routing
rules to remove based on the source component of the rule. - removeTargets Array of string values indicating which routing
rules to remove based on the target component of the rule. - routeTo String value indicating the component to forward the
handover message to.
RoutingMutationStep
Object tag: !routing_mutation
This is a small subset of the actual functionality but it is what's
needed to do handovers (it supercedes the !handover step). Please note
router internal event 'RoutingMutated' is fired on all routing
updates, but only the !disable_component and !enable_component rules
with componentId: CmBot are actually interpreted on the CustomerContact
adapter and signalling the handover call to CustomerContact.
steps:
- !routing_mutation
id: do_handover
mutations:
- !disable_component
componentId: CmBot
context:
var1: waarde1
var2: waarde2
var3: {someOtherVariable}
context: You can supply dictionary (key/value pairs) that will end
up in the router-session and will travel along with the (router
internal) RoutingMutated event, which will be available in the
ConversationalRouter adapter for CustomerContact / BMProxy. As a result
this context will be available to webcalls to CustomerContact and
BMProxy. It is possible to use variables as values as displayed for
'var3'.
Below is a full example of all supported options of the
RoutingMutationStep:
steps:
- !routing_mutation
id: update_routing_step_all_options
mutations:
- !disable_rules
targetComponentId: CmBot
- !enable_rules
targetComponentId: CmBot
- !remove_rules
targetComponentId: CmBot
- !add_rule
sourceComponentId: BusinessMessaging
targetComponentId: CmBot
rulePriority: 1
ruleId: "new-rule-id"
- !routing_mutation
id: update_routing_step_offload_cmbot
mutations:
- !disable_component
componentId: CmBot
- !enable_component
componentId: CmBot
- !remove_component
componentId: CmBot
context:
- var1: waarde1
var2: waarde2
CC skills/team based routing. Retrieve the ID of the team to which you
want to route the message to. Go to settings -> Teams -> Select a
team, the guid should show at the top. It is also important that under
the CuCo Routing settings, both the Bot router is routed to both Teams.
steps:
- !routing_mutation
id: do_handover
mutations:
- !disable_component
componentId: CmBot
context:
ccTeamGUID: {guid}
EndSessionStep
Object tag: !end_session
Will mark the current Chatbot session as Terminated. So-called
catch-all entry-steps that have allowRestart: false will be able to
run again. Optionally one could configure to reset the router-state as
well.
steps:
- !end_session
id: end_session_step
resetRouter: false
PositionStep
Object tag: !goto
Use the position step to navigate to a different step in the script.
steps:
- !goto
id: gotoStep
cursor: "flowId.stepId"
Properties
- cursor The field actually holding the namespaced (concatenated)
position in the script to go to.
IfStep
Object tag: !if
The IfStep has some very basic support for if..else scenarios and is
most commonly used directly after an InputStep. An IfStep will check the
supplied variable with the supplied value and if they are equal, the
(!position) action will be performed, effectively changing the flow of
the bot script.
Please adhere to these rules when using IfStep:
- The first IfStep (in script order) that satisfies the condition will
win and the remaining steps won't be processed. - Conditions are matched exactly as specified and are case
sensitive. Specify more IfSteps if you want to match case
insensitive or be tolerant to slightly off values. - If you want to process some list of menu choices, specify a separate
if for each choice. - When you allow for a default or fallthrough scenario, just add a
step after the last IfStep. If no IfStep has a matching condition,
that step after the last if will be performed. - Important Please be informed that a new step, the LogicStep is
being developed that allow for a single step to include all this
logic, as well as support for Regular Expressions.
steps:
- !input
id: ticketQuestionChoice
var: "ticketQuestionChoice"
- !if
id: if_ticketquestion_1
var: "ticketQuestionChoice"
value: "Gold Ticket Friday May 1st (€ 99,-)"
actions:
- !position
flowId: question_2Fri
stepId: question_2Fri
- !if
id: if_ticketquestion_2
var: "ticketQuestionChoice"
value: "Gold Ticket Sunday May 3rd (€ 396,-)"
actions:
- !position
flowId: question_2Sun
stepId: question_2Sun
- !text
id: ticketQuestionChoice_unknown
message: "I don't recognise the ticket you chose. Be aware that I'm a chatbot, so please enter the number of your choice (1, 2 or 3)."
actions:
- !position
flowId: if_else_flow
stepId: if_else_question
Properties
- var Session variable to match with the value.
- value Value to match to the supplied session variable.
InputStep
Object tag: !input
Use this step when you want to process a reply supplied by the end-user.
The following rules apply:
- No support for validation currently exists. Using the new LogicStep
one could perform some validation using Regular Expressions though. - !position actions on !input are not supported
steps:
- !text
id: "ask_for_email_text"
message: "What is your email address?"
- !input
id: emailaddress_input
var: "emailaddress"
vars:
myType: $$type
myText: $$text
Properties
- var Session variable name to store the input.
- vars Mapping from local variables to session variables based on
the provided input
Input Type | Local variable | Default value | Description |
---|---|---|---|
Text | $$type | text | Type of the input. Can be used in !logic |
$$text | "" | The text content of the message | |
Media | $$type | media | Type of the input. Can be used in !logic |
$$text | Media.Name='$$mediaName', Uri='$$mediaUri', MimeType='$$mediaMimeType' | Textual representation of the provided media input. The local variables are replaced with the given media data | |
$$mediaName | "" | A caption or title belonging to the media file | |
$$mediaUri | "" | A unique download URL for the file | |
$$mediaMimeType | "" | The mime type of the file as indicated by the channel | |
Location | $$type | location | Type of the input. Can be used in !logic |
$$text | Location.Label='$$locationLabel', Lat=$$locationLatitude, Long=$$locationLongitude | Textual representation of the provided location input. The local variables are replaced with the given data | |
$$locationLatitude | "" | Latitude of the location (can be negative) and is always formated with a "." notation (4.1234) | |
$$locationLongitude | "" | Longitude of the location (can be negative) and is always formated with a "." notation (4.1234) | |
$$locationLabel | Name of the location | ||
$$locationSearchQuery | "" | Address or search query of the location |
InputStep Media
steps:
- !input
id: text
var: media
vars:
myType: $$type
myMimeType: $$mediaMimeType
myName: $$mediaName
myUri: $$mediaUri
- !text
id: outputMedia
message: "{myType}: {myMimeType} {myName} {myUri}"
- !text
id: outputMediaAsText
message: media
InputStep Location
steps:
- !input
id: text
var: location
vars:
myType: $$type
myLatitude: $$locationLatitude
myLongitude: $$locationLongitude
mySearchQuery: $$locationSearchQuery
myLabel: $$locationLabel
- !text
id: outputLocation
message: "{myType} {myLatitude} {myLongitude} {mySearchQuery} {myLabel}"
- !text
id: outputLocationAsText
message: location
VarStep
Object tag: !var
This step sets variables the bot can use to make decisions or provide
information to another system.
steps:
- !var
id: set_var
set:
foo: "bar"
customVar: "example.{$chatId}"
Properties
- set Dictionary where the keys become available as variables in
the bot script with the assigned value. It is possible to
concatenate multiple existing variables into a new one like the
customVar example.
ListPickerStep
Object tag: !listpicker Channels: Apple Business Chat and
WhatsApp
This type of message offers a simpler and more consistent way for users
to make a selection when interacting with a business.
[Apple_listpicker_example.png]{.image} [Listpicker-whatsapp.png]{.image}
steps:
- !<!listpicker>
id: Listpicker-1
header: Welcome to Jaspers!
buttonTitle: Options
buttons:
- id: 'jaspers-claphan'
title: Jaspers Clapham
description: '11-13 Battersea Rise, SW11 1HG'
- id: 'jaspers-brixton'
title: Jaspers Brixton
description: '419 Coldharbour Ln, SW9 8LH'
- id: 'jaspers-shepherds-bush'
title: Jaspers Shepherd's Bush
description: '15 Goldhawk Rd, W12 8QQ'
body: Let us know how we can help you today by choosing your local store.
footer: ''
mediaUri: ''
Properties
- header The header of the listpicker.
- buttonTitle Title shown on the button to open the listpicker
itself. - buttons.id The description to show for the option.
- buttons.title The title of the option.
- buttons.description An optional description of the option.
- body Subheader on apple business chat body text on WhatsApp
- footer An optional footer text that will be rendered in a
smaller font. - mediaUri The location of the image to show.
ReplyButtonsStep
Object tag: !replybuttons Channels: WhatsApp
You can specify a ReplyButtonsStep if you want to render a pre-defined
list of options inside WhatsApp like the example below:
[Reply-buttons-whatsapp.png]{.image}
steps:
- !<!replybuttons>
id: ReplyButtons-1
header: ''
buttons:
- id: 'yes'
title: 'Yes'
- id: 'no'
title: 'No'
- id: visit-website
title: Visit Website
body: >-
Here's our 'Running Half-Zip Long-Sleeved Shirt'. Would you like to
order?
footer: We only have a medium left in stock
Properties
- header The header of the message (optional).
- buttons.id Text to identify the selected button with.
- buttons.title The title of the button.
- body Body of the message above the reply buttons
- footer An optional footer text that will be rendered in a
smaller font.
LocationStep
Object tag: !location
You can use a location step to communicate an exact location that will
render as a 'pin'.
steps:
- !location
id: "location_step"
latitude: 51.588928
longitude: 4.780410
label: "The Tosti Club Breda"
searchQuery: "Vlaszak 2, 4811 GR Breda"
Properties
- latitude Latitude of the location. Please make sure to use a dot
for the decimal part. - longitude Longitude of the location. Please make sure to use a
dot for the decimal part. - label The label to display next to the pin.
- searchQuery The address to display.
LogicStep
Object tag: !logic
steps:
- !logic
id: logic_id
entries:
- condition: !equals
var: "var1"
tests: ["1", "One"]
isCaseSensitive: true
position:
cursor: choice_1.choice_1
- condition: !startsWith
var: "var1.1"
tests: ["A", "B"]
isCaseSensitive: true
position:
cursor: "flow11.step11"
- condition: !and
conditions:
- !equals
var: "var2"
tests: ["2", "Two"]
isCaseSensitive: true
- !equals
var: "var2"
tests: ["Deux", "Zwei"]
isCaseSensitive: true
position:
cursor: choice_2.choice_2
- condition: !or
conditions:
- !equals
var: "var3"
tests: ["3", "Three"]
isCaseSensitive: true
- !equals
var: "var3"
tests: ["Trois", "Drei"]
isCaseSensitive: true
position:
cursor: choice_3.choice3
- condition: !not
condition: !equals
var: "var4"
tests: ["4", "Four"]
isCaseSensitive: true
position:
cursor: choice_4.choice4
- condition: !regex
var: "var5"
tests: ['Order (?<orderCode>)\d{5} for (?<personCount>\d{1}) persons.', "Order (?<orderCode>)\\d{5} for (?<personCount>\\d{1}) persons."]
isCaseSensitive: true
position:
cursor: choice5.choice5
- condition: !emailValidator
var: "var6"
position:
cursor: "correct.email"
- condition: !default {}
position:
cursor: "if_all_else_fails"
MediaStep
Object tag: !media
Use a mediastep to send a message containing a picture, movie or sound.
steps:
- !media
id: "media_step"
mediaName: "Race Engineer"
mediaUri: "https://cdn.cm.com/dgp/DGP-race-engineer.mp3"
mimeType: "audio/mpeg3"
Properties
- mediaName The name that will be displayed.
- mediaUri The location where the media file can be found.
- mimeType The mimetype of the media. Common types are:
- image/jpeg
- image/png
- image/gif (animated gifs are not supported at
BusinessMessaging/WhatsApp at the moment) - audio/mpeg3
- video/mpeg4
StepGroupStep
Object tag: !stepgroup Supported Channels: Apple Business Chat
Normally, every step that results in a message being sent, will be
communicated as a single message to Business Messaging. When some
messages are sent with little time in between, the messages might end up
in a different order at the end-user. Since BusinessMessaging supports
sending multiple messages in a single request, the StepGroupStep was
built.
Please note We've only had success with this solution on the Apple
Business Chat channel. It does work in WhatsApp as well, but we've
noticed messages in wrong order as well. The example is taken from a
live script that works on Apple Business Chat.
steps:
- !stepgroup
id: stepgroup_step
steps:
- !text_with_url
id: subflow_event_tvgo_url_link
textMessage: "Remek választás! Bővebb információért koppints ide:"
url: "https://www.tvgo.hu/cikk/25890886_universal_filmek_felaron_a_tv_go_n_advent_3"
urlLabel: "TVGO"
mediaName: "figure%20skating.png"
mediaUri: "https://d15k2d11r6t6rl.cloudfront.net/public/users/Integrators/371a907d-72a2-4e4e-8549-723bc6aba3dc/d7df6908-f9ac-41ac-91a5-f1e74e5a4085/1_TVGO_Link.JPG"
mediaMimeType: "image/png"
- !text
id: subflow_event_tvgo_url_msg
message: "Ha újra szeretnéd indítani a beszélgetést, akkor írd be, hogy „szia”"
Properties
- steps Array containing Steps to be sent in one go. Imporant
Only Steps that actually send a message will work here. This is
not actively validated.
TextStep
Object tag: !text
The TextStep is used to send a plain text message to the recipient. The
following applies.
- It is allowed to use unicode emoticons, like the text 'Hey
there👋!' - Use \n as a newline separator within a single yaml line.
- Use |- to start a block so newlines in yaml will be preserved.
This make the yaml more readable when using big text blocks. - You can have as many TextSteps as you want.
To match a possible starting sequence, one or multiple regular
expressions can be configured which each allow the EntryStep to start
the script (so ANY of the regular expressions could match / concatenated
with OR).
steps:
- !text
id: text_1
message: "This message will be sent to the recipient."
- !text
id: text_2
message: "It is allowed to interpolate variables here, like {$channel}" todo: document variable types.
- !text
id: text_3
message: "First line \n Second line"
- !text
id: stext_4
message: |-
This will be the first line.
This will be the second line.
Properties
- message Content of the text-message that will be sent.
TextWithUrlStep
Object tag: !text_with_url Supported Channels: Apple Business
Chat
This message feels somewhat hacky and was built to solve an Apple
Business Chat problem, where we had to send a text message, that comes
with a so-called 'rich link'. The rich link translates as a Suggestion
in the Business Messaging connector and sending a message with solely a
Suggestion is not supported. The Business Messaging client (CM.Text
nuget) doesn't support a text message with suggestion on the correct
level so we had to hack something to made it work. As a result, the
TextWithUrlStep was born.
Please note Please refrain from using this component, unless you
can't.
steps:
- !text_with_url
id: subflow_event_tvgo_url_link
textMessage: "Remek választás! Bővebb információért koppints ide:"
url: "https://www.tvgo.hu/cikk/25890886_universal_filmek_felaron_a_tv_go_n_advent_3"
urlLabel: "TVGO"
mediaName: "figure%20skating.png"
mediaUri: "https://d15k2d11r6t6rl.cloudfront.net/public/users/Integrators/371a907d-72a2-4e4e-8549-723bc6aba3dc/d7df6908-f9ac-41ac-91a5-f1e74e5a4085/1_TVGO_Link.JPG"
mediaMimeType: "image/png"
Properties
- textMessage The text that goes along with the rich link.
- url The actual url to go to when the rich link is clicked.
- urlLabel The label that comes with the url.
- mediaName The name of the preview picture of the page where the
link points to. - mediaUri The uri where the preview picture can be found.
- mediaMimeType The mime type of the preview picture.
WebRequestStep
Object tag: !webrequest
A webrequest can be used to have the script-engine send or gather
information from an external webrequest. It requires the third party to support at least TLS 1.2.
If you use IP whitelisting, our IP address is 34.141.248.107
.
The following applies for a WebRequestStep:
- The webrequest is performed during script execution and might slow
down script execution. - If the script execution needs information from the reply in the following steps, set waitForResponse to true. If you just want a fire-and-forget webhook scenario: set waitForResponse to false.
- If the WebrequestStep fails (after 10 retries with an exponential backoff between 1 and 10 sec),
the script continues, if configured, from the failPosition.
steps:
- !webrequest
id: webrequest_step
waitForResponse: true
failPosition:
flowId: "failedFlow"
stepId: "TalkToAHuman"
request:
url: "https://some.cool.api.cm.com/coolapi/v1/resources/"
method: POST
timeout: 60
headers:
X-CM-PRODUCTTOKEN: "5c93c6e0-d13b-11e8-8b40-11086b70fb08"
queryParameters:
skip: 50
take: 50
body: |
{
"customer_data": {
"first_name": "",
"last_name": "",
"email": "",
"mobile": ""
},
"ticket_types": [
{
"uuid": "cc8632f8-6d17-4c48-a8a0-1acfa8a9130f",
"amount":
}
]
}
response:
extracts:
- var: "order_id"
source: "@body.json"
selector: "order_id"
Properties
- waitForResponse Should be set to 'true' if the script execution needs information from the reply in the following steps, otherwise 'false'.
- failPosition Position to continue from when the webrequest
failed - request Block containing all specific information about the
request. - response Block containing configuration on what to do with the
response.
Request properties
- request.url The url for the request. Supports interpolating
variables by enclosing them in . - request.method HTTP Method for the request.
- request.headers Key-value collection to specify headers.
- request.body The (json) body that goes with the request.
Supports variable interpolation using . - request.timeout Any number, this value is ignored because of the addition of our exponential backoff. Removing it from the JSON will be done towards the future.
Response properties
- response.extracts A collection of so-called extracts, that will
enable pulling information from the response. - response.extracts.var The session variable name to store the
extracted value. - response.extracts.source The source of the extract. One could
specify the following options:- @body.json The response body, handled/casted as json. You
can specify a json path query as 'selector'. - @body.xml The response body, handled/cased as xml. You can
specify an xml path query as 'selector'. - @body.text The plain text value of the response body.
- @status_code Numeric HTTP response code of the request.
- @is_success Boolean indicating success or failure of the
request. - @retries Number of times the request was retried.
- @body.json The response body, handled/casted as json. You
- response.extracts.selector The json/xml path query to perform on
the response.
Scalar types
In case the response body contains only a scalar type then it's
possible to extract that value using the selector "."
steps:
- !webrequest
id: webrequest_step
waitForResponse: true
failPosition:
flowId: "failedFlow"
stepId: "TalkToAHuman"
request:
url: "https://some.cool.api.cm.com/coolapi/v1/resources/"
method: POST
headers:
X-CM-PRODUCTTOKEN: "5c93c6e0-d13b-11e8-8b40-11086b70fb08"
queryParameters:
skip: 50
take: 50
body: |
{
"customer_data": {
"first_name": "",
"last_name": "",
"email": "",
"mobile": ""
},
"ticket_types": [
{
"uuid": "cc8632f8-6d17-4c48-a8a0-1acfa8a9130f",
"amount":
}
]
}
response:
extracts:
- var: "order_id"
source: "@body.json"
selector: "."
Type conversions
Type Value Becomes
boolean false "False"
boolean true "True"
null null ""
string any string same string value
int (i.e 1) "1"
float (i.e 1.01) "1.01"
WaitStep
Object tag: !wait
The wait step is used to wait a certain amount of time before continuing
the chat flow. This interval can be interrupted by sending a new start
sequence as defined in the entry step.
- !wait
id: Wait-1
actions: []
clientActions: []
interval: 30
Properties
- interval Time to wait for (in seconds) before continuing the
flow
CommandStep
Object tag: !command
The CommandStep is used to invoke a command.
- !<!command>
id: Command-1
actions: []
clientActions: []
name: Handover
context:
team: '10'
Properties
- name The name of the command that should be invoked
- context You can supply dictionary (key/value pairs) that will
end up in the router-session and will travel along with the (router
internal) RoutingMutated event, which will be available in the
ConversationalRouter adapter for CustomerContact / BMProxy. As a
result this context will be available to webcalls to CustomerContact
and BMProxy. It is possible to use variables as values as displayed
for 'var3'.
MenuStep
Object tag: !menu
The MenuStep is used as an aggregate of the steps you'd normally use
for asking the customer for feedback (text, listpicker or replybuttons),
waiting for the answer and doing logic based on that answer. This is
such a common pattern that using this step will save a lot of screen
space providing a better overview of the open flow.
The MenuStep uses an InputStep under water of which you can access the
input from the user in the context variable
'@session.menuStepId.UserInput' where you should substitute
'menuStepId' with the id of the MenuStep of which you want to use the
user's input.
- !<!menu>
id: Menu-1
actions: []
clientActions: []
displayType: Text
header: header text
interactiveMessageBody: ''
buttonTitle: ''
footer: footer text
options:
- key: '1'
keyAliases:
- een
- one
contentType: PlainText
displayedText: '1: get in contact with a sales agent'
cursor: sales-flow.Text-1
- key: '2'
keyAliases:
- two
- twee
contentType: PlainText
displayedText: '2: Get in contact with management'
cursor: management-flow.Text-1
fallback: fallback text
timeoutInSeconds: '50'
timeoutCursor: fallback.Text-1
Properties
- displayType The visual representation you want the options to be
displayed as. Possible options are text (all channels), listpicker
(Apple Business Chat or WhatsApp) or reply buttons (WhatsApp) - header Small piece of text to display at the top. Will be a
separate text message if the displayType is text - interactiveMessageBody Body of the visual representation when
choosing listpicker or reply buttons. Mostly used for clarification
of the provided options - buttonTitle Title of the button that opens up the listpicker
(not applicable to other display types) - footer Small piece of text useful for concluding text about the
options. Will be a separate text message if the displayType is text - fallback The text message that will be sent if none of the user
input matches the options (only applicable to displayType text) - timeoutInSeconds Time to wait for user input before navigating
to the location of the timeoutCursor (optional) - timeoutCursor The namespaced (concatenated) position in the
script to go to when the input timeout is hit (optional)
Option properties
- key Identifier/piece of text that should be matched by the
user's input for the option to be selected - keyAliases Similar input that should also match this option
(only applicable if displayType is text) - contentType Representation of option. Currently only supports
text with a possible addition of an image in the future - displayedText The body of the option that's shown to the user
with the selected displayType. This represents what they can select
visually - cursor The namespaced (concatenated) position in the script to
go to when the option is matched
ClientActions
Some channels like Apple Business Chat and RCS support so-called client
actions or suggestions (as they're called in Business Messaging slang).
These client actions will render as buttons or options in the app and
allow for easy replies, instant meeting requests and others. Below is an
example of a common scenario where a question is asked and one should
reply using one of the two reply buttons.
steps:
- !text
id: question_hamburgers
message: "Do you like hamburgers?"
clientActions:
- !reply
label: "Yeah!"
replyText: "YES"
- !reply
label: "Nope!"
replyText: "NO"
- !input
id: question_hamburgers_input
var: "LikesHamburgers"
Create Calendar Event
Object tag: !create_calendar_event
Use the Create Calendar Event client action to have option added to
instantly add a calendar event.
clientActions:
- !create_calendar_event
label: "Option 1"
replyText: "calendar_event_created"
title: "Calendar Event Title"
description: "Calendar Event Description"
startTime: "2020-02-02T22:22:22Z"
endTime: "2020-02-02T22:23:22Z"
Properties
- label The text displayed on the button / option.
- replyText The actual text to send back.
- title Title of the window that shows the datepicker.
- description Description to be displayed when using the
datepicker - startTime Starting date/time of the calendar item.
- endTime End date/time of the calendar item.
Dial
Object tag: !dial
With the Dial client action a button will be displayed that will call
the number you assign to it.
clientActions:
- !dial
label: "Bel op!"
replyText: "dialed"
phoneNumber: "+31612345678"
Properties
- label The text displayed on the button / option.
- replyText The actual url text that is sent back.
- phoneNumber The MSISDN to dial.
Open Url
Object tag: !open_url
This action will open a url.
clientActions:
- !open_url
label: "Bel op!"
replyText: "url_opened"
uri: "http://www.cm.com"
Properties
- label The text displayed on the button / option.
- replyText The actual text to send back.
- uri Web address to open.
Reply
Object tag: !reply
Can be used to create a set of fixed replies. Please note that the label
of the option can be different from the actual text being sent.
clientActions:
- !reply
label: "Option 1"
replyText: "option_1"
Properties
- label The text displayed on the button / option.
- replyText The text to send back.
View Location
Object tag: !view_location
Use the View Location client action to open a map interface to display
the location.
clientActions:
- !view_location
label: "View Location of CM HQ"
replyText: "view_location_clicked"
latitude: 51.603719
longitude: 4.770777
locationLabel: "CM HQ"
Properties
- label The text displayed on the button / option.
- replyText The actual text that is sent back.
- latitude Latitude of the location.
- longitude Longitude of the location.
- locationLabel Text displayed next to the location.
Actions (Deprecated)
Actions can be defined on a Step to let the script engine know to
perform some action, like calling a webhook or going to a specific part
of the script.
The following rules apply:
- No guarantees will be given for the order in which actions run.
- Exception on the rule above is that PositionalActions, like
PositionAction and CursorAction, will be performed after all
other types of actions.
Below is an example of common usage of an action (PositionAction) when
checking a menu choice.
steps:
- !input
id: input_menuchoice_step
var: "menuChoice"
- !if
id: menuChoice_equals_1
var: "menuChoice"
value: "1"
actions:
- !position
flowId: menu_choice_1_flow
stepId: some_step_in_flow
CursorAction (Work in Progress)
The CursorAction is a close relative of the PositionAction. The
difference is that a CursorAction works with a single property pointing
to a specific item in the script and the PositionAction does not.
Please note the following:
- The dot '.' is reserved for concatenating (namespacing) of the
cursor. Refrain from using a '.' in the 'id' of a Flow as well
as a Step.
steps:
- !input
id: input_menuchoice_step
var: "menuChoice"
- !if
id: menuChoice_equals_1
var: "menuChoice"
value: "1"
actions:
- !cursor
cursor: menu_choice_1_flow.some_step_in_flow
Properties
- cursor The field actually holding the namespaced (concatenated)
position in the script to go to.
PositionAction
The positionaction is the older relative of the CursorAction. The
PositionAction has separate properties to point to a Flow and a Step and
the CursorAction uses a single string.
Below is an example of a common usage for the PositionAction. Please
note that the preferred way of pointing to a part of the script will
be the cursor, because it allows for more flexibility.
steps:
- !input
id: input_menuchoice_step
var: "menuChoice"
- !if
id: menuChoice_equals_1
var: "menuChoice"
value: "1"
actions:
- !position
flowId: menu_choice_1_flow
stepId: some_step_in_flow
Properties
- flowId Id of the flow to go to.
- stepId Id of the step (within the flow) to go to.
Session Variables
Session variables are name/value pairs that can be stored in a few ways.
First of all there are fixed/system variables, variables either obtained
by user input or processed by means of regular expressions.
Fixed/System variables
When a session starts the following system variables will be
automatically added to the session variables collection.
- $startSequence This is the literal text that was sent to start
the current session. - $conversationClientId This is the identification number
(msisdn, apple chat id, etc) of the end-user. - $conversationClientIdNormalized Normalized (00) version of the
conversationClientId - $conversationHostId This is the identification number of the
party that hosts the chat. - $conversationClientName This is the identification name of the
end-user (not supported by all parties). - $channel The channel that was used of the message that started
the session. - $chatId Fixed hashed Guid of the combination of channel,
conversationClientId and conversationHostId. Can be safely used for
external communication from within the chatscript.
Obsolete
- $recipient See conversationClientId
- $chatIdGuid Implementation of $chatId when the latter was
still the concatenation of
'Channel#conversationClientId#conversationHostId'.
Dynamic Variables/System Functions
Dynamic variables are similar to Fixed/System variables, however, the
output of these variables is changeable. The use of parameters allows
the end-user to form the desired output. The following Dynamic variables
are available for use whenever a session is started:
$GetNow() Gets the current time according to the parameters. The
following parameters are supported:
- TimeZone is required, and allows you to specify the TimeZone for which to get the time. You can use any timezone supported by the tz database.
- Format is required, and allows you to specify the format to apply to the time. For example, using "yyyy-MM-dd hh:mm:ss" will get you the current year, month, day, hour, minute and seconds. All the
possible formatting options can be found here. - Language is an optional third parameter, which allows you to specify the language to apply to the output. If you get the weekday and supply "it-IT", for example, you will get the weekday in Italian. You can see a list of supported language tags here. If you omit this value the output will default to "en-US".
An example of this would be getting the current date and time in the timezone of our HQ in Breda: $GetNow("Europe/Amsterdam", "yyyy-MM-dd hh:mm:ss")
.
It might also be helpful to get the current day. Let's make it more exciting by getting the italian variant: $GetNow("Europe/Amsterdam", "dddd", "it-IT")
Variables by input
When using an InputStep the literal value that is sent by the end-user
will be stored in the variable name as specified by the 'var'
property. For an example please see InputStep
Variables from regular expressions
It is also possible to extract variables from regular expressions when using an EntryStep or LogicStep with !regex condition. See the InputStep and LogicStep for more information and examples.
Updated 9 months ago