Statements
say¶
Sends the given message to the user.
say "Hello! Great that you're here."
Next to normal text you can also send any UTF-8 characters, including emojis.
say "😂 Very funny!"
You can also use string interpolation to create dynamic messages:
time_of_day = "morning"
say "Good #{time_of_day}!"
Will say "Good morning!".
Message formatting¶
URLs in text are automatically linked. Newline characters (\n
) can be used
to create a line break:
say "Click this link:\n https://nu.nl"
When using web-based chat, you can use Markdown formatting for bold, italic, etc.
say "**bold text**"
say "*italic text*"
say "`monospace text`"
say "This is a [link](https://nu.nl/)"
Tooltips¶
On web channels you can create a tooltip in a chat bubble by using the following Markdown link syntax:
say "Please enter your [VAT](## \"Value Added Tax\") number."
Message formatting for voice actions¶
On the voice channels, Google Assistant and Alexa, we convert markdown tags to SSML speech output.
The following conversions take place:
**emphasized speech**
→ <emphasis level="strong">emphasized speech</emphasis>
**moderate speech**
→ <emphasis level="moderate">moderate speech</emphasis>
_reduced speech_
→ <emphasis level="reduced">reduced speech</emphasis>
Furthermore, certain punctuations are converted to pauses in the
speech. The use of a ,
corresponds to a pause of 200ms; ...
and
…
correspond to a pause of 500ms.
Options¶
class:¶
Use the class:
option to specify a specific presentation for the
message. The class
attribute will become part of the rendered HTML
in the chat bubble. Combined with custom CSS rules, the class:
option
can be used to create a customized presentation for certain messages.
For example, this sets the class "large" on the message:
say "string", class: "large"
The predefined classes in Web client are:
large
- font size 2x as large as normalsystem
- gray, smaller text, no bubble around text
as:¶
To let the bot impersonate another person, it is possible to specify the as:
option, with a given user object.
The object needs to have at least a user_id
and a first_name
attribute. profile_picture
can be used to specify the avatar.
@person [user_id: "arjan", first_name: "Arjan", profile_picture: "http://..."]
dialog main do
say "Hello my name is Arjan", as: @person
end
Messages like this will still appear on the left side of the chat window, and thus are meant for simulating persons other than the current user, e.g. for a group chat.
@arjan [user_id: "alice", first_name: "Alice", profile_picture: "https://static.guim.co.uk/sys-images/Guardian/Pix/pictures/2014/7/2/1404313767243/Invisible-Woman-selfie-001.jpg"]
@faye [user_id: "pete", first_name: "pete", profile_picture: "https://s3.eu-west-1.amazonaws.com/bsqd-out/image/00d0513e-d96c-4511-abf8-c4163bd702a6-1280x1280.jpg"]
dialog main do
say "Hi there, in the web chat this looks like Alice is saying it.", as: @alice
say "Cool huh.", as: @alice
pause 2
say "Hi there i'm Pete :-)", as: @pete
say "bybye", as: @pete
say "Now Alice is talking again", as: @alice
end
as: :user¶
To let the bot impersonate the current user:
say "Hello from yourself", as: :user
These messages will appear on the right side of the chat window.
typing_indicator:¶
To specify how long (in seconds) the typing indicator should show before displaying
the message in the say
statement.
say "This takes long", typing_indicator: 20
The given value is specified in seconds.
delay:¶
To specify how long the delay should be before showing the message:
say "one ", delay: 0
say "two", delay: 0
say "three", delay: 0
Note that with delay: 0 you will still see the typing indicator. However,
delay: 0
can be combined withtyping_indicator: 0
if you require so.
ask¶
ask
presents a text message to the user, and waits for the response
from the user. This response can be stored in a variable. When no
variable name is given, the response of the user is stored in the
variable named answer
.
ask "how old are you?"
say answer
When used in an assignment, it is possible to store the response in another variable, like in the next example:
age = ask "how old are you?"
say age
Options¶
expecting:¶
When the expecting:
option is set with a list of strings, entities or
intents, the bot will repeat the question until the message is matched against
the value(s) in the expecting
option. This is used for validation purposes,
when you need the user to type something specific to continue. The items in the
expecting
will also be displayed as quick-replies if they
have a label attribute. If a media file is expected, expecting
can be used
to create a quick reply button which immediately triggers a file upload.
The most simple case for using expecting
is to present a list of
quick reply buttons below the question, like this:
ask "Did you laugh?", expecting: ["Yes", "No"]
The bot does not continue until the user literally types the
string "Yes"
or "No"
. So this form does not use any form of
fuzziness or intent matching.
To be a bit more "loose" in what is accepted, you can define Yes and No intents (either in the code or in the Intent Manager:
# define intents which use fuzzy string matching.
@yes intent(match: "yes|yep|sure|indeed", label: "Yes")
@no intent(match: "no|nope", label: "No")
dialog main do
ask "Did you laugh?", expecting: [@yes, @no]
branch do
answer == @yes ->
say "You laughed!"
answer == @no ->
say "Apparently you did not laugh."
end
end
In above example, two intents are defined, with a label. These labels
will be shown when the intents are given to the expecting
clause of
the ask.
expecting
can also be used to present a specialized input widget
or form control to the user.
ask "Please choose an item",
expecting: input_method("item_picker", items: ["One", "Two"])
expecting
can also be used to extract an entity from the user using Duckling entity, for instance, to ask for a date:
ask "When do you need the package?",
expecting: entity(duckling: "time")
In above example, the answer.value
variable will contain a valid ISO
date based on what the user says ("tomorrow", etc).
Some other builtin validators for expecting
are the following:
:file
:image
:location
:video
:text
:email
# Expect an image from the user
ask "Please upload a selfie", expecting: :image
# Match on any text input (same as when you omitted 'expecting')
ask "Where are you currently?", expecting: :text
# E-mail regular expression
ask "What is your email?", expecting: :email
# Trigger a file upload
ask "Which file do you want to upload?", expecting: :file
# Trigger a location picker
ask "Where are you currently?", expecting: :location
The built-in validators can also be combined in a list as follows:
# Ask the user to send some information about themselves
ask "Can you send me a picture or your location?", expecting: [:image, :location]
This will show both input widgets to the user.
expecting: with DTMF¶
Explicit DTMF choices can be added to the expecting clause by wrapping the expecting option with an intent
and adding the DTMF option:
dialog __main__ do
ask "Yes or no", expecting: [intent(label: "Yes", dtmf: "0")]
end
When no DTMFs are explicitly added, they are implicit on the
expecting, the first choice being DTMF 1, the second DTMF 2,
etc. Either none or all of the 'expecting' options need to have
an dtmf
property, mixing implicit with explicit DTMFs is not
possible.
help_dialog:¶
The help dialog is invoked when a user enters something that does not match the expected input:
dialog asking do
ask "Did you laugh?", expecting: [@yes, @no], help_dialog: help
end
dialog help do
say "You said: #{message}."
say "Please answer yes or no instead."
end
The variable message
is available in the help_dialog which contains
the last utterance of the user.
An alternative to help_dialog
is to define an inner dialog called
__unknown__
to catch anything
that does not match the expectation:
dialog asking do
dialog __unknown__ do
say "Please answer yes or no."
end
ask "Did you laugh?", expecting: [@yes, @no]
end
This is usually clearer than the help_dialog
option and also allows you to
give a more fine-grained reply.
Note that this __unknown__
will not trigger when another trigger that is placed
outside the scope of this dialog. For instance:
dialog asking do
dialog __unknown__ do
say "Please answer yes or no."
end
ask "Did you laugh?", expecting: [@yes, @no]
end
dialog trigger: "maybe" do
say "You said maybe"
end
If you now answer the question with maybe, you will trigger the dialog trigger "maybe"
instead of the __unknown__
. If you want to keep the resolving of triggers inside
the dialog where the ask is, you can use the :text
trigger.
dialog main do
dialog trigger: :text do
say "Please answer yes or no."
end
ask "Did you laugh?", expecting: [@yes, @no]
end
dialog trigger: "maybe" do
say "You said maybe"
end
quick_replies:¶
Quick-replies provide the user with answers to choose from. However, these
options are mere hints, they are not used for validation unless specified with
the expecting
option.
# Only the quick-replies
ask "Did you laugh?", quick_replies: ["Yes", "No"]
# `quick-replies` with expecting as validation
ask "Did you laugh?", quick_replies: ["yep", "nah"], expecting: [@yes, @no]
# The `quick_replies:` are shown but `expecting:` is matched:
ask "What's your email?", quick_replies: ["no thanks"], expecting: [@email, @no]
It is possible to combine
expecting:
andquick_replies:
; in that case, the given quick_replies are used but the validation is done on the expecting clause.
Small icon-sized images can be embedded in the quick replies like this:
ask "Please choose your option", quick_replies: [
[title: "option 1", image_url: "http://via.placeholder.com/40x40"],
[title: "option 2", image_url: "http://via.placeholder.com/40x40"] ]
When using specification method, the following options are available:
title:
, the text shown to the user,image_url:
, the url of an image to use,
append_quick_replies:¶
An extra list of quick replies which are appended after the normal
quick replies. These quick replies do not participate in the
:cycle
and :exhaust
quick replies modes.
prepend_quick_replies:¶
An extra list of quick replies which are prepended before the normal
quick replies. These quick replies do not participate in the
:cycle
and :exhaust
quick replies modes.
timeout:¶
Sometimes, the user might not want to respond or forgets to respond to your
question. For these cases you can add a timeout
to the ask, so that the
script continues after a short while. To prevent a script from "hanging", you
can let the ask
expire by supplying a timeout value which is then used as the
answer.
@ask_timeout 30
# the ask dialog now overrides the timeout set as a constant
ask "How are you?", timeout: 4, timeout_value: :yes, expecting: [@yes, @no]
if answer == :yes do
# this ask will have a timeout of 30 seconds
ask "..."
end
If no timeout_value
is given, the builtin dialog __ask_timeout__
will be
triggered on a timeout:
ask "How are you?", timeout: 4
dialog __ask_timeout__ do
say "Hey, wake up!"
ask "Do you want to continue?"
end
When using
ask
from within a__ask_timeout__
dialog (without a timeout value), it will not trigger a new ask timeout dialog, but that ask will block infinitely.
To set a global timeout on all ask
s, use the @ask_timeout
constant:
@ask_timeout 4
dialog main do
ask "How are you?", timeout: 4
end
dialog __ask_timeout__ do
say "Hey, wake up!"
ask "Do you want to continue?"
end
max_unknown:¶
The max_unknown option to ask ensures that the user can hit the __unknown__
inner dialog only N times.
@ask_max_unknown 3
# the ask dialog now overrides the max_unknown set as a constant
# if we say something other than yes or no for more than 3 times, the ask continues, assuming '@yes'.
ask "How are you?", max_unknown: 3, max_unknown_value: @yes, expecting: [@yes, @no]
If no max_unknown_value
is given, the builtin dialog __ask_max_unknown__
will be
triggered on a max_unknown:
ask "How are you?", max_unknown: 4
dialog __ask_max_unknown__ do
say "I am sorry I really dont get what you want."
end
To set a global max_unknown on all ask
s, use the @ask_max_unknown
constant:
@ask_max_unknown 3
dialog main do
ask "How are you?", expecting: ["Good"]
end
dialog __ask_max_unknown__ do
say "I dont get it.."
end
training_labels:¶
If an ask or prompt is labelled with `training_label:``, then any messages in response to that interaction are tagged with that training_label, even if they end up triggering another dialog (match_global).
prompt¶
A prompt is a special form of ask. It presents an automatic
quick-replies menu based on its labeled inner dialogs. Paired with the
continue
statement, the prompt
construct is an easy way to create
an automatic navigational structure in your bot.
dialog simple_prompt do
dialog label: "Tell a joke" do
say "Here comes the joke…"
end
dialog label: "Order a pizza" do
say "Please wait while ordering…"
end
dialog label: "Stop" do
say "Alright"
continue
end
prompt "What would you like to do?"
say "See you next time"
end
The inner dialogs can be combined with intent trigger:
arguments to
make the prompt matching more fuzzy.
Using the continue
statement in an inner dialog will cause the
interpreter to continue the execution right after the last prompt
statement that was encountered. In the example above, this is used to
provide the "stop" option from the prompt
.
Options¶
quick_replies_mode:¶
It is possible to let the quick replies be different every time the ask is displayed, while the ask is being repeated. This is typically used in a prompt to vary the quick replies slightly each time.
quick_replies_mode: :static
— the default; just show the same quick
replies each time.
quick_replies_mode: :cycle
— each time the ask returns, the quick
replies get cycled; the one that was the first in the previous prompt
is now the last.
quick_replies_mode: :exhaust
— each time the ask returns, the quick
replies that was clicked last will have disappeared from the quick
replies.
dialog:¶
With the dialog
option, you can specify another dialog that will be invoked
whenever the prompt is called. This dialog has access to a local variable
_quick_replies
in order to display the quick replies through a say or
something else.
Example:
dialog main do
dialog label: "Bananas" do
say "I like bananas!"
end
dialog label: "Kiwis" do
say "Kiwis are the best!"
end
dialog label: "Oranges" do
say "Never liked oranges..."
end
prompt dialog: display_choices, quick_replies_mode: :exhaust
say "We are done"
stop
end
dialog display_choices do
branch length(prompt.labels) do
0 ->
continue
1 ->
say "The last fruit opinion you can ask of me", quick_replies: prompt.labels
else
say "I can tell you what I think about these fruits", quick_replies: prompt.labels
end
end
goto¶
The goto
statement is used to jump to a different dialog. It can be compared
to the "goto" statement of languages like Basic. When the target dialog is
done, execution will not return to the dialog that the goto
was
originally called from.
goto mydialog
Options¶
:replace¶
goto mydialog, :replace
This is the default behaviour of goto
. goto
will not to return to the
calling dialog, it will replace the current dialog on the stack.
:reset¶
goto mydialog, :reset
After finishing the dialog in the goto
, the stack will be empty and the bot
will become idle, or the __root__
dialog will be automatically invoked, if it
exists.
invoke¶
Invoke is used to switch (temporarily) to a different dialog. It can be
compared to a function call in a normal programming language. After the invoked
dialog is finished, the original dialog will be continued after the invoke
statement.
invoke mydialog
An invoke normally pushes the dialog on top of the current dialog stack, returning there after finishing.
Note that you can not use expressions in the name of the dialog, they always need to point to an existing dialog in one of the bot's scripts. The studio will show an error message when you have an invoke which points to a non-existing dialog.
invoke
and goto
can be used interchangably; they only differ in their
default behaviour. For example, the following two calls are equivalent:
invoke mydialog, :replace
goto mydialog
Options¶
message:¶
By invoking message:
, you can internally simulate the sending of a
user message.
It will cause the entered message (which can be an expression) to be handled by
the global dialog message matching system, as if a user had typed it. So in this
example, the main
dialog will output "Hi Pete!" when executed:
dialog main do
invoke message: "my name is Pete"
end
dialog trigger: "pete" do
say "Hi Pete!"
end
Invoke dialog with message trigger, resetting the stack¶
Resets the stack (just like invoke dialog, :reset
would), and then
performs the message matching just like `invoke message: "message"
would.
dialog main do
invoke reset: "my name is Pete"
end
event:¶
By invoking event:
, you can internally simulate the sending of a
user event.
dialog main do
invoke event: "button_click"
end
dialog event: "button_click" do
say "You clicked!"
end
And with a payload:
dialog main do
n = 5
invoke event: "button_click", payload: n
end
dialog event: "button_click" do
say "You clicked #{event.payload} times!"
end
attachment:¶
By invoking attachment:
, you can internally simulate the sending of an image
or file.
dialog main when attachment do
invoke attachment: attachment
end
dialog attachment: :image do
say "Thank you for the image"
end
location:¶
By invoking location:
, you can internally simulate the sending of an image
or file.
dialog main when location do
invoke location: location
end
dialog __unknown_location__ do
say "Thanks for the location pin"
end
These
invoke
withmessage
,attachment
andlocation
variants are especially important on whatsapp becausemain
is invoked after the starting of a bot, even if the user types a message first. (user-initiated conversation).
show¶
show
is the generic way of showing any media, other than plain text,
to the user. For example, the following shows an image:
show image "http://via.placeholder.com/150x150"
See the UI elements section to see all the kinds of media that can be presented to the user.
stop¶
Instantly stops the interaction with the bot. The bot will not continue talking until the user starts talking again.
On some platforms, for instance on telephony, stop
causes the conversation to
end (see: close
).
dialog trigger: "bye" do
say "Thank you for your time."
stop
say "This line is never executed"
end
close¶
Stops the interaction with the bot, and closes the conversation. The user cannot interact with this conversation ever again.
On some platforms, for instance on telephony, close
causes line to hang up. On
others, it hides the chat input, and/or shows a control that indicates that the
conversation is over.
On channels that do not support any close controls, but are "single conversation", e.g. Whatsapp, Facebook messenger, etc, the next time a user starts chatting, a new conversation with the user is opened.
dialog trigger: "bye" do
say "Thank you for your time, I hope it helped."
close
end
__closed__
dialog¶
When close
is invoked, a dialog __closed__
is invoked, as the
final dialog of the conversation. This dialog should only be used
for displaying a final message or a "conversation closed" user
interface. At this point, the user is not supposed to interact with
the conversation again.
dialog __closed__ do
show input_method("closed",
caption: "Conversation closed",
description: "Thank you for your time! See you later."
)
end
__closed__
task¶
When close
is invoked, a dialog __closed__
is invoked if it
exists, as described below. After the closed dialog finishes, the
conversation is over. However, after close the __closed__
task
gets called to perform any cleanups, conversation summarization,
etcetera. These can be potentially long-lasting tasks.
All tasks called
__closed__
are executed (given their guards). So skills can defined their own cleanup mechanisms.
task __closed__ do
perform some_summarization_task
create_conversation_note("Conversation summary: " + summary)
end
switch_language¶
Switch the language of the user based on the input and the modifiers in the opts. If no modifiers are given, the modifiers that are present will be added to the new language.
user.locale = "en.FORMAL"
switch_language "nl"
log user.locale # "nl.FORMAL"
If a locale has any modifiers, they will overwrite any existing modifiers:
user.locale = "en.FORMAL"
switch_language "nl.SSML"
log user.locale # "nl.SSML"
reset¶
Stops the current dialog and clears the dialog stack. When a
__root__
menu is defined, it is invoked.
dialog trigger: "bye" do
say "Thank you for your time."
reset
end
await¶
The await
statement works similar to ask
, except that no prompt or
quick replies are shown while awaiting.
The first argument to await
is the argument you would give to
expecting:
in an ask.
For example, the following waits for a valid email address and stores
the global variable answer
.
await @email
The following blocks until an event with the name "click" has been fired:
await event("click")
Like ask
, the result can also be stored in a variable:
email = await @email
say email
emit¶
The emit
statement sends an event to the runtime that is executing the bot. These
events can be used for instance to trigger backchannel events or trigger events on the
website. Emits an event to the client, or to another chat process. An event consists of
a named message (a string), plus an optional payload.
The event itself is a string; it can have an optional extra parameter which will be sent as payload.
dialog status_update do
emit "status_update", text: "#{user.first_name} started using the bot"
end
dialog main do
emit "start"
say "Hello!"
emit "end", [user_id: user.id]
end
See the documentation on events and scheduling how events can be used on the platform.
pause¶
Will pause the execution of the dialog for the given amount of time, in seconds.
pause 3 # pause the dialog for 3 seconds
type¶
Shows the typing indicator for the given amount of time, in seconds.
type 3 # pause for 3 seconds, while showing typing indicator
random¶
A block that will choose a line within the do..end and execute that once.
say random 10
returns a random number (int) between 0 and 10
say random [1,2,3,4]
returns a random element from the list
random do
say "Hi!"
say "Hello!"
say "Howdy!"
end
once¶
With once you can say things 'only once' stepping down a statement on every invocation.
once do
say "Hi!"
say "Hi again!"
after
say "We meet again"
end
This can be used to only say 'Hi' the first time and second time say 'Hi again' for instance. Every iteration once will select the next statement down.
When there is an after
present the statement after will be invoked on every successive iteration. Without after the once block will not do anything (when exhausted).
You can provide a name to the variable that is used to store the counter. This can be used to reset it so that the once block cycles instead of getting exhausted.
once i do
say "Hi!"
say "Hi again!"
after
say "We meet again"
dialog.once.i = nil # reset this once block to start again (cycle)
end
reset_once¶
Resets a once
block by name.
dialog __main__ do
once example do
say "Hi!"
say "Hi again!"
end
end
dialog trigger: "bye" do
reset_once "example"
end
remember / forget¶
remember
is the way to persist information for a user or
conversation in the platform's builtin contacts database (the
CRM). All information stored by remember
is saved with the bot's
user and can be viewed in the studio. In a next conversation, these
variables will be set again when new session starts. This way, you
only have to ask a user his name once, for example.
variable = 123
remember variable
forget variable
NOTE: variables can be deep 'object maps':
car.brand = "Volvo"
car.engine.hp = 200
remember car
This remembers the object car
and its nested values.
tag / untag¶
Sets a tag or clears a tag on the current conversation. Tags are a handy way to organize conversations, they can be used for filtering and finding users and conversations in the studio.
tag "lead"
untag "lead"
Tags are stored on two places: for the current conversation, the tags
are collected in the conversation.tags
variable; at the same time,
tags are also collected in the user.tags
variable. The difference
between these is that the user
variable is shared between all the
conversations that the user is involved in, while conversation.tags
are local to the current conversation.
Do not manipulate the
conversation.tags
oruser.tags
directly, always usetag
anduntag
.
To display the tag counts in the same graph in analytics (for funnel analysis) you can use a namespace:
tag "funnel:1-signup"
All tags in the "funnel" namespace will be shown in the Analyze seection of the studio, in a separate section. To order the tags according to the funnel steps its best to number them.
log¶
Prints a message, for debugging purposes:
log "This is a log message"
Log messages can contain any valid expression and are logged in the Console tab in the Botsquad studio, and in the conversation's history of the inbox.
if¶
Make a decision, based on an expression
if exits != "Yes" do
say "Lets continue"
end
else
is supported as well:
if exits != "Yes" do
say "Lets continue"
else
say "Ok lets quit"
end
branch¶
As an extended version of the if
statement, branch
allows you to
switch over multiple conditions. As soon as the first condition
matches, the corresponding block is invoked, while the other blocks
are skipped.
ask "What is your name?"
branch answer do
"Steve" -> say "Hi Steve!"
"Pete" -> say "Hello Peter"
end
See the full Branch reference
unset¶
When called on a single variable, erases the variable from the global scope:
name = "joe"
unset name
# here the name variable no longer exists
When called on a map key, the map key is deleted from the variable:
person = %{"name" => "joe"}
unset person.name
# the 'person' variable is now an empty map
perform¶
Analogous to invoke
, a task can be executed by using the perform
statement:
perform calculate
Tasks do not have arguments. As the DSL has a global scope, any
parameters that are required inside the task should be defined just
before the perform
statement.
buttons¶
buttons "What do you want to do next?" do
"Open CNN" ->
url "http://cnn.com"
"Say hello" ->
postback "say_hello"
end
NOTE: though buttons are similar to
quick_replies
they invoke dialogs via a postbackevent:
rather thantrigger:
and are not displayed as user message in the conversation.
test¶
A statement that starts a test block. Use normal bubblescript statements inside of the block to
test a bot. The string after the test
statements is the name of the test. The name is usually a
description of what the test is supposed to check.
Options¶
dialog:¶
This option can be used to invoke a specific dialog when the test is run.
# Bot script
dialog not_main do
say "This is not the main dialog"
end
# Test script
test "a different dialog is invoked", dialog: not_main do
expect "This is not the main dialog"
end
context:¶
Context can be added to override certain variable values in the dialog, or to supply variables to a dialog that would otherwise be set in a previous dialog. This is helpful because it allows you to setup an environment for the test.
Example
# Bot Script
dialog main do
say "Hii #{name}!"
end
# Test Script
test "say name", context: %{name: "Test"} do
expect "Hii Test"
end
expect¶
Use this statement to express what you expect a bot to say at a certain
moment. At the moment, only the say
and ask
statements of a bot are
supported, we intend to support show
in the future. Whatever is put into
expect from the side of the bot, can be stored in a variable as well by using
assignment. If no variable is given, the expected is stored in the variable
"message". This can be useful in combination with assert.
test "arithmatic" do
say "1 + 1"
expect "2"
end
test "bot says my name" do
expect "What is your name?"
say "Tester"
greeting = expect "Hi Tester!"
assert greeting == "Hi Tester!"
end
assert¶
To make sure that a variable contains a certain value, we can use assert to make sure that
an expression validates to true. The operators that are supported by the assert statement are
the following: == != > < <= >=. assert
is mainly useful for testing task
s. If a task
sets the value of a variable, this value can be asserted using assert
.
test "something" do
assert 11 == 11
a = "b"
assert a == "b"
assert 10 > 20
end
assert
only works for variables that are available in the test script. It is not possible to test the (internal) variables of your bot. An exception for these are tasks; in a test script it is possible toperform
a task; and thenassert
on the variables that the task has set. See Testing bots for more information.
redirect¶
The redirect
statement forwards the current conversation to another bot.
redirect bot: bot_id
This redirects the conversation, stopping the current bot and the new bot will
continue the conversation, starting with the main
dialog like normal (unless
other options are given, see below).
In the new bot, the variable conversation.referrer.bot
holds the bot ID of the
original bot. This can be used to redirect the conversation back.
All remembered user and conversation data is passed into the new conversation.
Effort is taken to align the locale of the conversation to the original locale, if the target bot supports the locale.
Redirect options¶
tag:
- By providing the tag:
option, you can set a tag in the new conversation to
indicate that the conversation has been redirected.
message:
- The message:
can be used to use the given string as the
starting message in the new conversation. This allows you to create "empty" bots
that only forward their conversation to another bot:
dialog __unknown__ do
emit "$redirect", [bot: bot_id, tag: "redirected", message: message.text]
end
location:
- Similar to the message:
option, sends the given location to the
new bot upon redirect.
attachment:
- Similar to the message:
option, sends the given attachment to the
new bot upon redirect.
Redirects do not work on Slack and Discord.
It is not possible to pass any other information to the new conversation; however all
remember
ed conversation/user variables will persist.
continue¶
The continue
statement is used to break out of the current ask
or prompt
statement. The conversation continues after the prompt or ask,
filling the answer
variable with either :continue
or an explicit
return value, if given.
dialog trigger: "help" do
continue
end
dialog main do
ask "What would you like to do?", expecting: ["Sleep"]
if answer == :continue do
say "We have continued"
end
end
Or with an explicit continue
value:
dialog trigger: "help" do
continue :help_requested
end
dialog main do
ask "What would you like to do?", expecting: ["Sleep"]
if answer == :help_requested do
say "We have continued"
end
end
fatal¶
Throw an error in the current bot process, with the given message.
Can be used for error handling, when it does not make sense to continue the current conversation due to an API call failing for instance.
fatal
will cause the __error__
dialog to be triggered, to be
able to guide the user onto a new track.
dialog __main__ do
perform my_task
end
task my_task do
http_get "https://httpbin.org/status/500"
if http.status_code == 500 do
fatal "Internal server error!"
end
end
dialog __error__ do
say "Sorry, something went wrong: " + error.message
stop
end
submit¶
The submit
statement can be used in tests to submit data.
submit message("hello", data: "hello_data")
submit location(lon: 70, lat: -30)
submit attachment(url: "https://example.com", type: "image")
This can be used to send data to an ask
:
# script: main
dialog main do
location = ask "Where are you?", expecting: :location
say location.lon
end
# script: test_main
test "sending a valid location" do
expect("Where are you?")
submit location(lon: 50, lat: 40)
expect("50")
end
react¶
React to a previously sent message in the form of an emoji.
Bu default, the reaction appears on the last message that was sent by the user.
The following sets a thumbs-up emoji to the user's message whenever the user says "thanks":
dialog trigger: "thanks" do
react "👍"
end
It is also possible to send a reaction to a specific user message by
specifying the to:
option:
dialog main do
msg1 = ask "How do you do?"
msg2 = ask "Are you sure?"
react "❤️", to: msg1.id
end
Or react to a message that the bot sent itself:
dialog main do
say "Hello"
react "❤️", to: dialog.last_action_id
end
return¶
Return a value from a function.
function identity(_value) do
return _value
end