Native CSML Functions

Native CSML Functions

CSML functions are a simple way to define simple functional code that can be reused across all of your flows. They are defined in any flow file and use the same CSML syntax that is available in any other steps.

Conceptually, they can be viewed as simple placeholders that you can insert at any place in any flow, to perform repetitive tasks.

Declaring a function is similar to declaring a step with some minor differences:

  • the name of the function is preceded by the keyword fn ,

  • there is a list of parameters between parentheses after the name of the function,

  • but also, like a step declaration, it ends with a semicolon : or is surrounded by braces {...} (new syntax introduced in v1.10.0)

// v1.10.0+ syntax
fn my_function_name(param1, param2, param3, ...) {
    /** do something **/
    return some_val

// old syntax, but still supported in newer versions!
fn my_function_name(param1, param2, param3, ...):
    /** do something **/
    return some_val

Here is an example of a simple my_double_add() function, that takes 2 parameters, multiplies each of them by 2, then adds those numbers together, and returns the result:

fn my_double_add(x, y) {
  do dbl_x = x * 2
  do dbl_y = y * 2
  return dbl_x + dbl_y

  do value = my_double_add(1, 2)
  say "The result is: {{value}}" // 6
  goto end

There is no limit on how many functions a flow can have, and of course you can call a function from within another function. The above example could be rewritten as:

fn my_double(num) {
  return num * 2

fn my_add(a, b) {
  return a + b

fn my_double_add(x, y) {
  do dbl_x = my_double(x)
  do dbl_y = my_double(y)
  return my_add(dbl_x, dbl_y)


CSML native functions are isolated from the bot itself and can't interact with the memory or display messages. They have only access to non-state-binding keywords: do, if, foreach and return.

// Forbidden
fn my_func(a) {
    say "hello"
    remember something = 42
    goto somestep

However, other builtins can be used!

// Accepted
fn my_func(a) {
    do x = 0
    foreach (item) in a {
        do x = x + item.value
        if (x > 42) break
    do HTTP("").post().send()
    return x

Importing Functions From Other Flows

Functions are by default attached to the flow where they are written. However, you can import functions from other flows to reuse them elsewhere!

// import this function specifically from this flow
import my_function from flow_2

  do value = my_function(1, 2)
  say value
  goto end

You can also use a global import by not defining the flow from which a function can be imported.

// import a function with this name from any other flow
import my_function

Warning! If there is more than one flow defining a function with the same name, it will just import one of them randomly.

Don't use the same name on several functions, or specify which flow you want to import from

Advanced usage

You can import multiple functions at once, and even rename them:

// import several functions at once
import {my_function, other_function} from flow_2

// you can rename a function
import my_function as better_name from flow_2

  do value = better_name(42)
  say "The result is {{value}}"


introduced in CSML v1.10.0

CSML Modules are an easy way to reuse CSML Functions across multiple chatbots or to provide access to your own services to other chatbot developers. You can create functions in separate flows that you can host on a repository to ease access.

A module at its core is simply a valid CSML flow, that exposes one or several functions, which can be imported into other flows without needing to copy the flow multiple times in multiple bots. An other benefit of using modules is that it makes it easier to replicate changes across multiple changes.


To use a module, you must first declare it as a dependancy to your chatbot. This is done in the modules section of the body when creating a new version of a chatbot or chatting with an unversioned chatbot.

Some example modules are given in this repository:


Let's import the buttons module into a flow to access the YesNoButtons function and make it easier to display Yes/No types of buttons.

The module specification is as follows:

name: buttons url: auth: none

Then you can simply import it in your CSML script as you would any other function, the only difference being the modules/ prefix that tells CSML that it should look for this function in the buttons module and not in the bot's other flows.

import YesNoButtons from modules/buttons

  say Question("Do you like strawberries?", buttons=YesNotButtons("Yes, of course", "Not really"))
  say "Your answer was: {{event}}"

Last updated