Message Formats

# Text

1
say "His palms are sweaty, knees weak, arms are heavy" // short form
2
say Text("There's vomit on his sweater already, mom's spaghetti") // long form
Copied!
The Text component of the Webapp channel also supports some basic Markdown:
1
say "He's _nervous_, but **on the surface** he looks [calm and ready](https://www.youtube.com/watch?v=_Yhyp-_hX2s)"
Copied!

# Typing, Wait

1
say Typing(1000)
Copied!
Obviously, Wait is also supported (it simply does not display a typing indicator or anything for the given duration).

# Image

1
say Image("https://images.unsplash.com/photo-1560114928-40f1f1eb26a0")
Copied!

# Question, Button

1
say Question(
2
"Hi! My name is:", // equivalent to title="Hi! My name is:",
3
buttons=[Button("What?"), Button("Who?")]
4
)
Copied!
If you need to retrieve a specific data when clicking on either button, use the payload argument of the Button component:
1
say Question(
2
"Hi! My name is:",
3
buttons=[
4
5
6
]
7
)
8
hold
9
say "user clicked on button with the {{event}} payload"
Copied!
The Webapp channel also supports single Button components. However, as cross-channel support for single buttons is not guaranteed, we encourage you to use the standard Question component instead, with a title.

Quick replies are similar to Questions, where the buttons are removed from view once the user has selected one of them. In a majority of scenarios, you should prefer QuickReplies over regular questions, especially when you don't want the user to be able to scroll up and select one of the buttons after they have made a first choice. Questions should be used when a button is used as a trigger to a given flow (as configured in the bot's AI Rules).
1
2
"Do you like cheese?",
3
buttons=[Button("Yes 🧀"), Button("Also yes 🫕")]
4
)
Copied!

# UserInput

In some cases it may be desirable to temporarily disable the user input to force the user to select one of the options without letting them type anything.
1
say UserInput(false) // disables the user input
2
say UserInput(true) // reenables the user input
Copied!
Please note that if the page is refreshed, the user input will go back to being enabled by default even if it was first disabled.

# Video, Audio

The Video component supports links to mp4 files, as well as Youtube, Vimeo and Dailymotion URLs. The Audio component supports links to mp3 files, as well as Spotify, Soundcloud and Deezer URLs.
1
Copied!
1
say Audio("https://open.spotify.com/track/1xB3YT8Rakvnfcc1dp2kzJ")
Copied!
Standard limitations apply: if the end user is not logged in to a valid spotify/deezer/soundcloud account, only 30s will be playable in the audio component.
For full control over the clip, prefer using a standard mp3 file URL.

# Url

The Url component will automatically retrieve the target's favicon if available. If a text parameter is present, it will be used as the component's title.
1
say Url("https://www.wikipedia.org/", text="Visit Wikipedia")
Copied!

# Carousel, Card

A Carousel is essentially a collection of Card elements A single Card will display as a Carousel of 1 element. Each Card can have a maximum of 2 Button elements.
1
do card1 = Card(
2
"The Marshall Mathers LP",
3
subtitle="Release date: May 23, 2000",
4
5
6
)
7
do card2 = Card(
8
9
subtitle="Release date: February 23, 1999",
10
11
12
)
13
do card3 = Card(
14
"The Marshall Mathers LP 2",
15
subtitle="Release date: November 5, 2013",
16
17
18
)
19
20
say Carousel(cards=[card1, card2, card3])
Copied!
The cards themselves can be made clickable by adding an optional default_action Url() parameter:
1
do card = Card(
2
"The Marshall Mathers LP",
3
subtitle="Release date: May 23, 2000",
4
default_action=Url("https://en.wikipedia.org/wiki/Eminem"),
5
6
7
)
Copied!
The carousel can also automatically navigate horizontaly by adding the optional autoplay parameter (which defaults to false):
1
say Carousel([ card1, card2, card3 ], autoplay=true)
Copied!

# Calendar

This component will display a rich calendar in the webapp. By default, when passed with no argument, a simple single-date datepicker will appear:
1
say Calendar()
Copied!
single mode
Optional parameters allow to set a min_date and/or max_date (by unix timestamp, in milliseconds) or an input_mode to accept single (the default) multiple or range inputs by the user:
1
say Calendar(
2
min_date=1617494400000, // April 4th, 2021
3
max_date=1623974400000, // June 18th, 2021
4
input_mode="range" // can also be "multiple" or "single"
5
)
Copied!
range mode
multiple mode
The event value of a Calendar input will be comma-separated values of all user inputs. Also, event.input_mode will be set to the mode of the requested calendar, so that you can differenciate between single, multiple and range modes when receiving values.
1
// given this sample CSML code
2
say Calendar(...)
3
hold
4
say "{{event.get_content()}}"
5
6
// example single mode
7
{
8
"input_mode":"single",
9
10
}
11
// example multiple mode
12
{
13
"input_mode":"multiple",
14
15
}
16
// example range mode
17
{
18
"input_mode":"range",
19
20
}
Copied!

# Input

To gain some control over what a user can enter in a form (for example, if you need to make sure they only enter an email address or a valid number when required), you can also use the Input component.
There are several variants of input fields: email, text, textarea, number. By default, inputs are type="text". All parameters are optional, and the basic usage is as follows:
1
say Input(
2
type="text", // default
3
title="What is this field?",
4
description="Some details about what is expected",
5
minlength=0, // for text/email/textarea inputs only
6
maxlength=100, // for text/email/textarea inputs only
7
required=false,
8
placeholder="This is an input",
9
default_value="This is set by default",
10
submit_label="Submit" // the text for the validation button, defaults to OK
11
)
Copied!
You can check this reference about the minlength and maxlength parameters: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/text#additional_attributes
A completely bare say Input() component will result in this simple, empty text input:
Inputs with type="number" can have some different parameters, just like HTML inputs (all are optional as well):
1
say Input(
2
type="number",
3
title="Enter a number",
4
min=-14.3,
5
max=42,
6
// the other parameters from the previous example also apply
7
)
Copied!
You can check this reference about the min and max parameters: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Input/number#additional_attributes

# Multiselect

If you want to let users select multiple options, the Multiselect() component is the solution. Users will be able to select any number of options in the given list. You can force a min and max number of choices, or if required=true, it means that at least one option must be selected to continue.
1
say Multiselect(
2
title="Why do you like CSML?",
3
description="Select all options that apply!",
4
min=2,
5
submit_label="Yes, that's it!",
6
options=[
7
8
9
10
11
Button("The mascot 🦜 is cool", payload="pako"),
12
]
13
)
Copied!
When several options are selected, you will receive a comma-separated list of the corresponding payloads (not necessarily the button's title!), in the order they were selected by the user. In the case above, you would receive:

# LaTeX

LaTeX is a popular language that lets you write (among other things) complex math formulas. The webapp and chatbox include KaTeX to support this language natively with a custom component:
1
start:
2
say LaTeX(
3
"$$x^2 + y^2 = z^2$$",
4
// If the user has "audio mode" enabled the tts parameter
5
// will be used as the basis for the speech synthesis
6
tts="This is the Pythagorean theorem!",
7
)
8
9
say LaTeX("\\def\\arraystretch{1.5}
10
\\begin{array}{c:c:c}
11
a & b & c \\\\ \\hline
12
d & e & f \\\\
13
\\hdashline
14
g & h & i
15
\\end{array}")
Copied!
You can find more examples of supported formats on the KaTeX documentation: https://katex.org/docs/supported.html. Please keep in mind that backslashes (\) must be escaped properly in your code!