BotreamDocs Website Türkçe v0.1.1

The task language (DSL)

Every Botream task can be read and written as text: one command per line, with --name:value parameters. The Code view of the editor shows this text, and the blocks view is the same task drawn as cards.

input --name:folder --type:string --default:"C:\Invoices"
set --name:count --type:number --value:0
loop --type:eachfile --folder:$folder$ --filter:*.pdf --variable:file
    log --message:"Processing $file.Name$"
    number --action:increment --name:count
endloop
log --message:"$count$ invoices processed"

Note: The text is a view of the task. Botream stores the task as structured commands and the agents run those; you never have to keep the text and the blocks in sync yourself.

Lines and commands

  • Each line holds one command: the command name, then its parameters.
  • Blank lines and indentation are ignored. The editor indents block contents by four spaces.
  • Command names are not case-sensitive (Log works like log). Parameter names are written in lowercase, as in the reference; only runtask mappings use the input and output names of the called task (--invoiceNo:$no$, --totalTo:total).
  • A parameter may appear only once per line.
  • There is no comment syntax: # or // at the start of a line is an error. Use the comment command, which does nothing when the task runs:
comment --text:"Log in with the service account"

See the command reference for every command and parameter.

Parameters

A parameter is written --name:value, with no space around the colon.

Unquoted values

An unquoted value runs to the end of the line or up to the next --name:; spaces at its end are dropped. Spaces inside are allowed, so conditions and JSON need no quotes:

if --condition:$count$ > 5 and $status$ = "ok"
    log --message:Status ok
endif
set --name:items --type:list --value:["a", "b", 3]

--name: followed by a space is an empty value.

Quoted values

Put a value in double quotes when it:

  • is empty (--text:""),
  • starts with a space or a double quote,
  • contains text that looks like another parameter ( --x:),
  • spans several lines or contains tabs.

The editor quotes values with spaces as well, which is always safe. After the closing quote there must be a space or the end of the line.

Inside quotes, the backtick (`) starts an escape:

Write To get
`" a double quote
`n a line break
`t a tab
`r a carriage return
`` a backtick

A backtick followed by any other character stays a backtick. Backslashes are always literal, so Windows paths and regular expressions are written as they are. Outside quotes nothing is escaped.

log --message:"Line one`nLine two"
messagebox --message:"Click `"Continue`" when you are ready"
file --action:write --path:C:\Out\report.txt --content:$text$

Switching a command off

Any command can carry --disabled:true. It stays in the task but does not run (a disabled block takes its contents along). This is what Ctrl+/ in the editor writes.

Variables in values

Variables are written between dollar signs. Anything else with a $ is plain text, so US$ 5 or a lone $ stay as they are.

Reference Reads
$name$ The variable
$order.Total$ A field of a record or dictionary (or a property of a window, file, response…)
$items[0]$ An item of a list (0 is the first)
$table[2].Name$ A cell: row 2, column Name of a data table
$row.Items[1].Sku$ Any combination of fields and indexes
$items.Count$, $text.Length$ Number of items (rows, keys) / number of characters
  • Variable names start with a letter or _ and contain letters, digits and _. They are not case-sensitive when the task runs.
  • A field after a dot must be a name of the same kind (no spaces); field names are matched without regard to case.
  • When a value is exactly one reference (--list:$items$), the command receives the variable itself, with its type: a list stays a list, a number a number. When a reference is part of a longer text ("Total: $sum$ EUR"), its value is put into the text.
  • Parameters that name a variable to write to (--output, set --name, loop --variable) take the bare name: --output:total, not --output:$total$.

See Variables and data types for the types and their literals.

Formulas in values

A value that starts with = is a formula, calculated when the command runs, as in Excel: --value:=$price$ * 1.2, --message:="Order " & $id$ & " is ready", --value:=round($total$ * 0.18, 2). Formulas need no quotes around them, even with spaces. See Formulas for the operators and functions. To write text that starts with =, put an apostrophe in front: --message:'=== done === (the apostrophe is removed when the task runs).

Older $name syntax

Tasks written before this syntax used an open form ($name without the closing $). They are upgraded to $name$ automatically when they are opened; you do not need to change them. If you type $name for a variable the task has, the editor shows a warning, because without the closing $ it is plain text.

Declarations come first

input and output declare the task's parameters (see task inputs and outputs). They must be at the top of the task; only comment lines may come before them. A name can be declared only once.

comment --text:"Books one invoice"
input --name:invoiceNo --type:string
input --name:retries --type:number --default:3 --required:false
output --name:bookingNo --type:string

Blocks

Block commands enclose other commands and end with their own end line. End lines take no parameters.

Block Sections End
if elseif (any number), then else (at most one) endif
loop – endloop
try catch and/or finally (at least one, in that order) endtry
switch case (at least one), then default (at most one) endswitch
retry – endretry
step – endstep

if / elseif / else

if --condition:$total$ > 1000
    log --message:"Needs approval"
elseif --condition:$total$ = 0
    throw --message:"Invoice $no$ has no total"
else
    log --message:"Booking directly"
endif

Instead of an expression, if and elseif can take a typed condition with --type:

--type Parameters True when
expression (or no --type) --condition The expression is true (see below)
string --left, --operator, --right, --ignorecase Text comparison: equals, notequals, contains, notcontains, startswith, endswith, matches (regex), isempty, isnotempty
number --left, --operator, --right Number comparison: =, !=, >, <, >=, <=
boolean --value, --is The value is true (or false with --is:false)
fileexists, filenotexists --path A matching file exists / does not exist (* and ? allowed in the last part)
folderexists, foldernotexists --path Same for folders
windowexists, windownotexists --window, --timeout The window is open / closed, waiting up to --timeout seconds
elementexists, elementnotexists --dompath (Capture), --frame, --browser, --timeout The web element is shown on the page / is hidden or missing
desktopelementexists, desktopelementnotexists --window, --by, --target (Capture), --timeout The desktop element is in the window / is not
imageexists, imagenotexists --image (Capture picture), --window, --similarity, --timeout The picture is on the screen (or in the window) / is not
if --type:string --left:$subject$ --operator:contains --right:invoice --ignorecase:true
    log --message:"Invoice mail"
endif
if --type:fileexists --path:C:\In\*.xlsx
    log --message:"New workbooks are waiting"
endif

The element and picture conditions check what is on the screen in one block, instead of reading capture --action:exists into a variable and testing it with if --type:boolean. In the editor, Capture fills in the element (with its object properties table) and Capture picture marks the picture, just as for capture, desktop and image. --timeout waits up to that many seconds for the element or picture to appear (…exists) or to go away (…notexists) before deciding; without it the screen is checked once. A missing element, window or picture never fails the task: the condition is simply false (or true for the not forms).

if --type:elementexists --dompath:"//div[@class='error']" --timeout:3
    capture --action:gettext --dompath:"//div[@class='error']" --output:problem
    throw --type:business --message:"The portal refused the invoice: $problem$"
elseif --type:desktopelementexists --window:$erp$ --by:name --target:"Saved"
    log --message:"Saved in the ERP"
elseif --type:imagenotexists --image:"C:\Pictures\spinner.png" --window:$citrix$ --timeout:30
    log --message:"The remote screen is ready"
endif

Older agents (installed before these conditions existed) run them too: the server sends them as a wait into a hidden variable followed by if --type:boolean (the log then shows a "Gave up" warning when the answer is no). Only imagenotexists with a --timeout needs the current agent.

switch / case / default

switch runs one of several sections by a value: the first case whose --value equals the switch's --value runs; when none does, the default section runs (if there is one). Values are compared as text; with --ignorecase:true, Approved and APPROVED are the same. A number case of a switch on a variable compares as a number, so 1 also matches 1.0.

switch --value:$status$ --ignorecase:true
case --value:Approved
    log --message:"Book the invoice"
case --value:Rejected
    log --message:"Send it back"
default
    log --message:"Unknown status $status$" --level:warning
endswitch

The commands go inside the sections: a switch needs at least one case, and default comes last. In the editor, add sections with Add case and Default in the block's properties or on its End line, and select a case to type its value. Every agent runs a switch: the server sends it as if / elseif / else, keeping the line numbers of the switch and its cases for the log and the debugger.

loop

--type chooses what the loop goes over: range, times (a fixed number of rounds), list, datatable, condition (while), excelrows, eachfile, eachfolder, queue or mail (each e-mail of a mailbox folder; see Looping over e-mails). Every type except times and condition names a loop variable with --variable; the variable of a range loop is a number.

loop --type:range --from:1 --to:10 --variable:i
    log --message:"Round $i$"
endloop
loop --type:times --times:3
    log --message:"Three times"
endloop
loop --type:list --list:$customers$ --variable:customer
    log --message:"Customer $customer$"
endloop
loop --type:condition --condition:$pending$ > 0
    number --action:decrement --name:pending
endloop

--index (times, list, datatable, excelrows, eachfile, eachfolder, queue and mail loops) names a number variable that receives the round's position, starting at 0 like $list[0]$. A condition loop tests its condition before every round; with --check:after it runs the body first and tests after every round (a do-while: the body always runs at least once).

loop --type:list --list:$customers$ --variable:customer --index:i
    log --message:"Customer $i$: $customer$"
endloop
loop --type:condition --condition:"$hasNext$ = true" --check:after
    capture --action:click --dompath:"//a[@rel='next']"
    capture --action:exists --dompath:"//a[@rel='next']" --output:hasNext
endloop

--index and --check:after need the current agent: an older one is not sent such a task (the run is refused with a message to update the agent).

break leaves the innermost loop, continue goes on with its next round. Both are allowed only inside a loop.

loop --type:datatable --table:$orders$ --variable:row
    if --condition:$row.Status$ = "cancelled"
        continue
    endif
    if --condition:$row.Id$ = $lastId$
        break
    endif
    log --message:"Order $row.Id$"
endloop

try / catch / finally

browser --action:open --url:"https://portal.example.com" --output:portal
try
    capture --browser:$portal$ --action:click --dompath:"#export"
catch --error:err
    log --message:"Export failed at line $err.CommandLine$: $err.Message$" --level:error
finally
    browser --action:close --browser:$portal$
endtry

See Error handling and retries.

retry

retry runs its commands again when one of them fails: up to --times attempts in all (default 3), waiting --interval seconds (default 1) between them. With --until, it also tries again while that condition is false after the commands ran. After the last attempt the error goes on, so a try around it can catch it.

retry --times:3 --interval:5
    browser --action:open --url:"https://portal.example.com" --output:portal
    capture --browser:$portal$ --action:click --dompath:"#login"
endretry

See Error handling and retries.

step

step groups commands under a description. It changes nothing about how they run.

step --description:"Read the input file"
    csv --action:read --file:C:\In\orders.csv --output:orders
endstep

Condition expressions

--condition of if, elseif and loop --type:condition is an expression:

Element Written as
Comparison =, !=, >, <, >=, <=
Text tests contains, startswith, endswith, matches (regular expression)
Combination and, or (and binds first), parentheses
Negation ! before a value or a parenthesis
Values $variable$ references, numbers, "quoted text", true, false, null, and bare words (read as text)
if --condition:$amount$ >= 100 and ($country$ = "DE" or $country$ = "AT")
    log --message:"EU invoice above limit"
endif
if --condition:$customer$ != null and $customer.Name$ startswith "ACME"
    log --message:"ACME order"
endif
if --condition:!$isApproved$
    log --message:"Not approved yet"
endif

How values are compared:

  • Two numbers compare as numbers, two dates by time; anything else compares as text, case-sensitive.
  • contains, startswith, endswith and matches are case-sensitive. Use a typed condition (--type:string --ignorecase:true) to ignore case.
  • null equals a missing value and empty text; it can only be used with = and !=.
  • A value on its own is true unless it is false, 0, empty text, an empty list or null.
  • and and or stop as soon as the result is known, so $x$ != null and $x.Name$ = "a" never reads the field of a missing value.
  • Keywords (and, or, contains…) are not case-sensitive.
  • Quoted text in an expression has no escapes; references inside it are filled in ("INV-$no$").

Tip: Write the condition unquoted. If you do put the whole --condition value in quotes, every double quote inside it must be written as `".

How the editor checks the text

The Code view marks problems as you type, and the same checks run in the blocks view:

  • unknown commands and parameters (with a "did you mean" hint), missing required parameters, values of the wrong kind (a number, true/false, one of a list of choices, a variable name, a $variable$ reference);
  • blocks that are not closed, end lines that do not match, sections in the wrong place;
  • input/output below other commands, break/continue outside a loop, throw without --message outside a catch section;
  • typed values that do not fit their type (for example set --type:number --value:abc);
  • warnings for a $name without its closing $, and for a --browser:$page$ whose variable is never opened by browser --action:open.

A task with errors cannot be saved. Warnings do not block saving.

Botream 0.1.1 · Generated 2026-10-14