Formulas
Two formula languages: short {{= }} expressions and the advanced formula with functions and Russian aliases, the Compute action, and the tester.
In questa pagina
GetMyBot has two formula languages, each with its own place:
- Expressions: a short language for arithmetic, comparisons, and simple strings. It works in
{{= expression}}directly in text, in the "Formula" mode of the "Compute" action, and in decision-table conditions. - Advanced formula: the full spreadsheet-style language with dozens of functions (lists, JSON, dates, hashes,
LAMBDA) and Russian function name aliases. It works in the "Advanced formula" mode of the "Compute" action, in answer validation by formula, and in the tester.
Advanced-formula functions do not work inside {{= }}: {{= ROUND(total) }} is not evaluated and the construct stays in the text as is. For such calculations, compute the value with the "Compute" action and insert the result with {{ctx.key}}.
Where formulas work
| Where | Language |
|---|---|
{{= expression}} in message text | expressions |
"Compute", "Formula" mode (expr) | expressions |
"Compute", "Decision table" mode (rules) | expressions in "when" conditions; "then" and the default value are plain text with {{...}} substitutions |
"Compute", "Advanced formula" mode (formula) | advanced formula |
| Answer validation "Matches formula" | advanced formula |
Formula tester (test_formula) | advanced formula |
The "Compute" action
The action has three modes, and exactly one is used per action:
- Formula (
expr): a single expression. - Decision table (
rules+default): a list of "when → then" rules. The value of the first rule whose condition is true is returned, otherwise the default value. - Advanced formula (
formula): a formula in the full language.
The result is saved to ctx (the "Save to ctx" field, save_to_ctx) and/or to a subscriber parameter ("Save to parameter", save_to_param): at least one is required. Limits: an expression, a rule condition, and a rule value up to 4096 bytes each, an advanced formula up to 16384 bytes (a Cyrillic letter takes 2 bytes), at most 64 rules.
Example action parameters with an advanced formula:
{"type":"compute","params":{"formula":"IF({total} > 1000; \"wholesale\"; \"retail\")","save_to_ctx":"segment"}}
Expressions
Syntax
- Operators: arithmetic
+ - * / %, comparisons== != < > <= >=, logic&& || !, ternarycondition ? yes : no, parentheses( ). - Literals: numbers (
42,3.14), quoted strings ("hello"or'hello'), booleans (true,false). - Data: a name is written without braces and is looked up in subscriber parameters and
ctx:price * qty,ctx.total,param.total. An unknown name yields an empty string. - Function call:
name(argument1, argument2), arguments separated by commas.
Functions
Only these, and only in lowercase: len, upper, lower, trim, concat, round, floor, ceil, abs, min, max. min and max take exactly two arguments, concat takes any number. len and LEN in an advanced formula count characters the way a reader sees them: an accented letter, a flag or an emoji built from several code points (for example, the family 👨👩👧👦) is one character.
Expressions have no Russian aliases. If {{= }} contains an unknown function, the construct stays in the text unchanged.
Advanced formula
Syntax
- Arguments are separated by semicolons:
IF({total} > 1000; "wholesale"; "retail"). - Operators: arithmetic
+ - * /, string concatenation&, comparisons= != <> < > <= >=(equality is a single=). Logic is done with theAND,OR, andNOTfunctions. - Strings go in double or single quotes.
""inside a string is not an escaped quote: if you need a quote inside the text (for example, in an HTML attribute), use the other kind of quotes:"<a href='tg://user?id=" & r.user_id & "'>profile</a>". - Data is substituted in single braces:
{key}is a value fromctx(and{text}or{answer}is the incoming message text),{user:key}is a subscriber parameter,{global:key}is a bot-wide global parameter. - LAMBDA:
LAMBDA(r; expression)defines a function forFILTER,FOREACH,ARRAYFIND, andREDUCE. JSON object fields are read with a dot:r.user_id. - The result is converted to text. Store a list with
TOJSONand read it back in the next formula withFROMJSON. - Function names are case-insensitive and understand Russian aliases.
Functions
Names are given in their canonical (English) form. Many functions also accept a Russian alias; case is not significant. These functions are available only in the advanced formula.
Math
SUM, AVERAGE, MAX, MIN, MOD, POW, SQRT, PI, ROUND, CEIL, FLOOR, TRUNC, ABS, RANDBETWEEN.
Text
LEN, LEFT, RIGHT, MID, LOWER, UPPER, UPPERFIRST, REPEAT, CONCAT, SUBSTITUTE, FIND, SEARCH, FIELD, TRIM, LTRIM, RTRIM, PADLEFT, PADRIGHT, SPLIT, JOIN, STARTSWITH, ENDSWITH, CONTAINS, NL.
Logic
IF, AND, OR, NOT, EMPTY, ISNUMBER, COALESCE.
Lists
SORT, RSORT, UNIQUE, FILTER, FOREACH, REDUCE, INDEX, SLICE, COUNTA, COUNTUNIQUE, ARRAYADD, ARRAYREMOVE, ARRAYREPLACE, ARRAYFIND.
Date and time
TODAY, NOW, DATEADD, DATESUB, DATEDIF, DATEFORMAT, DATEVALUE, WEEKDAY.
JSON
TOJSON, FROMJSON, JSONPATH, JP, JSONOBJECT, JSONARRAY, KEYS, VALUES.
Cryptography and encoding
HASH, TOBASE64, FROMBASE64, FROMJWT, FROMJWK.
Parameters
PARAMID, PARAMREPLACE, PARAMREMOVE.
Examples
Expressions in text:
- Order total:
{{= price * qty}}. - A third of the total, rounded:
{{= round(total / 3)}}. - Condition:
{{= param.total > 1000 ? "wholesale" : "retail"}}. - String assembly:
{{= concat("Order #", ctx.order_id)}}.
Advanced formula in the "Compute" action:
- 10% discount:
ROUND({user:total} * 0.9). - Size of a list from
ctx:COUNTA(FROMJSON({items})). - A stable pseudo-random order of the records that the "Find records" action put into
ctxunder therowskey: the order stays the same between runs until you change the "salt".
{"type":"compute","params":{"formula":"TOJSON(SORT(FOREACH(FROMJSON({rows}); LAMBDA(r; HASH(\"sha256\"; r.user_id & \"-salt\") & \"|\" & r.user_id))))","save_to_ctx":"order"}}
Answer validation "Matches formula": the formula returns the error text, and an empty result means the answer is accepted. For example, IF(ISNUMBER({answer}); ""; "Enter a number").
Formula tester
The tester checks an advanced formula and returns the result or a syntax error without saving anything:
- in the editor: in the "Matches formula" answer-validation block, enter a sample in the "Sample answer" field and click "Test";
- via the API:
POST /api/bots/{botID}/reactions/test-formulawith the body{"formula": "…", "sample_text": "…"}; - via MCP: the
test_formulatool with thebot_id,formula, andsamplefields.
Response: ok (the formula evaluated), result, error, and matches (true when the result is empty, i.e. the answer would pass validation).
The formula is evaluated in an empty context: ctx, subscriber parameters, and global parameters are empty, so {key} and {user:key} yield an empty string. Only the sample text is available: {text}, {answer}, or {received_message}. Expressions ({{= }}, the "Formula" mode, decision tables) are not checked by the tester.
What's next
- Substitutions and Formulas:
{{...}}variables,ctxcontext, and parameters. - Actions: the "Compute" action and decision tables.
- Messages and Buttons: formulas in texts and answer validation in dialog steps.
- Collections and Data: the data that formulas operate on.