Control actions
Loops, branches, error handling, routines, signals between clients, and stopping.
Twelve actions that decide what runs, what stops, and how clients of one account talk to each other.
Three limits apply across this page. Nesting of loops and branches is capped at
10 levels deep. A while runs at most 1000 iterations unless you raise
maxIterations. And every firing has a total action budget, so a loop cannot run
forever even if its condition never turns false. When the budget runs out the firing stops
with the warning "stopped after 1000 steps (the per-run limit)" and the step fails.
repeat
Runs a block of actions a fixed number of times.
| Field | Type | Required | Notes |
|---|---|---|---|
count | integer, 1–1000 | no | Number of passes. See the warning below. |
children | array of actions, max 200 | yes | The body. |
Inside the body, {{round}} is the current pass (1-based) and {{round0}} the same
0-based.
Omitting count means one pass, not "forever". The editor always writes a count,
so this only comes up if you drive the API directly, and the worker logs a warning
when it has to make that assumption.
while
Runs a block for as long as a condition holds.
| Field | Type | Required | Notes |
|---|---|---|---|
cond | condition | yes | Re-tested before each pass. |
children | array of actions, max 200 | yes | The body. |
maxIterations | integer, 1–10000 | no | Default 1000. A hard safety cap. |
A loop that reaches maxIterations while its condition still holds stops there, warns in
the console and counts as a failed step.
if
Runs one block or another depending on a condition.
| Field | Type | Required | Notes |
|---|---|---|---|
cond | condition | yes | The test. |
then | array of actions, max 200 | yes | Runs when the condition holds. |
else | array of actions, max 200 | no | Runs when it does not. |
try
Runs a block, and at the first action in it that fails, stops the block and runs a fallback block instead.
| Field | Type | Required | Notes |
|---|---|---|---|
body | array of actions, max 200 | yes | What to attempt. |
onFail | array of actions, max 200 | no | What to do when it fails. |
"Fails" covers both a hard error and a step that reports it could not do its job, such as a
container action with no window open, or a
wait_until that timed out with
failOnTimeout. The steps after the one that failed do not run, also when it failed inside a
loop or an if in the body. For a single central alert instead of a try around everything,
use the flow_error trigger.
To the step after it, the whole try is one step. It counts as failed when onFail ran and
its last step failed, or when the body failed and there is no onFail. A try whose
onFail recovered counts as a success, so
last_action_failed right after it is
not set. A try inside another try that ends failed stops the outer body too.
break
Leaves the nearest enclosing repeat or while early.
No fields.
Outside a loop it does nothing: the flow goes on, the step does not count as a failure
(a try around it does not run its fallback), and the console notes it once per run. It
exits one loop, not all of them. To end the whole firing, use stop_flow.
call_routine
Runs the actions of a routine trigger in the
same flow, then continues.
| Field | Type | Required | Notes |
|---|---|---|---|
name | routine name | yes | [a-z0-9_]{1,40}. Must match a routine trigger in this flow. |
The unit of reuse: write a login sequence or a "dump into the chest" block once and call it from several triggers. A routine that calls itself is a stack, not a loop: recursion is capped at runtime, and the firing's action budget still applies.
stop_flow
Ends this firing and leaves the client online.
No fields.
The middle option of the three: break leaves one loop, stop_flow ends the firing,
stop_client disconnects.
cancel_goal
Ends every goal the client is working on, such as obtain or farm. Each one fails with
"cancelled", and none of them resumes.
No fields.
This is the hard stop. stop_moving only
pauses a goal: it holds where it is until the next movement or goal step has run, then
carries on. stop_flow and stop_client also end every goal.
stop_client
Stops the client entirely. It disconnects and gives its plan slot back.
No fields.
A stop fires the before_stop trigger
first, so a "dump into a chest before going" flow still runs. Restarting the client is
then a manual action, or a schedule.
reconnect
Disconnects and connects again.
No fields.
The client already reconnects on its own after an unexpected disconnect. Use this when you want a reconnect on your own terms, to clear a stuck server-side state, or to rejoin a queue.
The rest of the flow does not run after it, even from inside a loop: reconnect ends the firing, then the client reconnects.
signal
Tells the account's other clients something. Only clients whose flow is listening react.
| Field | Type | Required | Notes |
|---|---|---|---|
channel | lowercase name, [a-z0-9_]{1,40} | yes | What it is about: raid, regroup, ready. |
message | string, up to 256 chars | no | Free text for the listeners. Variables are expanded, as in chat. |
to | array of client names, max 50 | no | Only these clients. Leave out for every listener. |
reach | world | server | account | no | Default world. See below. |
A listener is a client whose flow has an
on signal trigger or a
wait_signal step for that channel. Every other
client ignores the signal without a trace, not even a console line.
reach picks who can hear:
world: clients in the sender's actual world, the same server and the same dimension.server: clients on the same server address, on any backend or in any dimension.account: every running client of the account.
A signal never leaves the account that owns the sending client, and clients shared into your
account with you never receive it. to uses client names, case does not matter, and a name
reaches every client that has it.
Limits: 2 signals a second and 60 a minute per sending client. Over that, the step fails and nothing is sent. Signals are events, not state: a client that starts after one never sees it.
Known limits:
reach: serverspans every backend of a Bungee or Velocity network, since they share one address. Useworldto keep a signal to one backend.reach: worldtells worlds apart by the world's seed and dimension. Before game version 1.15 there is no seed, so it falls back to server address and dimension. Two backends cloned from the same world count as one world.
In Try it no real signal is sent; the step is only described.
wait_signal
Waits until other clients have sent a signal. The rendezvous.
| Field | Type | Required | Notes |
|---|---|---|---|
channel | lowercase name, [a-z0-9_]{1,40} | yes | Wait for this channel. |
count | integer, 1–50 | no | Default 1. Wait until this many different clients have signalled. |
from | array of client names, max 50 | no | Only count these senders. |
timeoutMs | integer, 1000–600000 | no | Default 30000. |
failOnTimeout | boolean | no | Off by default, as on wait_chat. |
The count is of different clients: one client sending three times counts once. Signals that
arrived before the step started do not count, so the wait begins when the step does. The
last signal's details land in {{signal_from}}, {{signal_message}}, {{signal_x}},
{{signal_y}}, {{signal_z}} and {{signal_dimension}}. In Try it the step resolves as
if the full count arrived.
Example: a group attack
One leader calls the others; every listener walks to the leader, fights, and reports back. Clients with no signal trigger do nothing.
The first trigger goes on the client named leader; the second on the others.
Example: a rendezvous
The leader waits for five clients to report ready, then tells them all to go.