Skip to main content

Expressions

Botgami expressions are bare and type-checked as you type. You write them directly — no quotes, no wrapper function, no special syntax.

when user.age >= 18 {
send.text("Welcome!")
}
warning

Never wrap an expression in expr(...) — that's legacy syntax and isn't needed. Just write the expression. The editor type-checks it live and underlines mistakes (unknown function, wrong argument count, member access on a non-object, type mismatch).

Operators

Arithmetic

flow.total = flow.price * flow.qty
flow.avg = flow.sum / flow.count
flow.rest = flow.n % 10

+ - * / %. + also concatenates strings: "a" + "b" is "ab".

Comparison

user.score > 100
user.role == "admin"
user.plan != "none"
flow.n <= flow.max

== != < > <= >=.

Logical

when user.verified && user.balance > 0 {
send.text("Ready to spend.")
}
when (!user.banned) || user.is_admin {
send.text("Allowed.")
}

&& || !. && and || short-circuit.

Membership: in

when user.id in shared.admin_ids {
send.text("Hello, admin.")
}

Ternary

set { flow.label = user.premium ? "Pro" : "Free" }

condition ? whenTrue : whenFalse. Great for conditional button slots:

user.cart_count > 0 ? { text: "Checkout", callback_data: "checkout" } : null

Member and index access

flow.first = flow.user.first_name // member access
flow.head = flow.items[0] // index access
flow.deep = flow.order.items[2].price // chained

Literals

set { flow.n = 42 }
set { flow.s = "hello" }
set { flow.b = true }
set { flow.nothing = null }
set { flow.list = [1, 2, 3] }
set { flow.obj = { id: 1, name: "Sam", active: true } }

Object keys may be bare identifiers or strings: { "callback_data": "x" }.

Template literals

Use backticks with ${...} to build strings:

send.text(`Hi ${user.first_name}, you have ${user.points} points.`)
warning

Inside ${...}, use simple references only — a variable or a dotted/indexed path like user.points or flow.items[0]. Do not put arithmetic or function calls inside ${...}. Precompute them in a set { } block first.

// WRONG — arithmetic inside ${}
send.text(`Total: ${flow.price * flow.qty}`)

// RIGHT — compute first, then reference
set { flow.total = flow.price * flow.qty }
send.text(`Total: ${flow.total}`)

Calling builtins

Builtins are called in expressions, namespaced by category:

set { flow.name = str.lower(str.trim(user.name)) }
set { flow.n = util.len(user.todos) }
when array.includes(shared.admins, user.id) { send.text("Hi admin") }

See Builtins for the complete catalog.

Next