Flow

Run named macro flows in parallel and send messages between them. Each flow has its own variables. Pass starting data with Flow.params; messages are independent copies read in the order sent.

Syntax

Flow

This class cannot be constructed directly.

Returns

—

Example

# Save an enemy template and configure watch_enemy before running
# Main: arm the watcher and stop it after the main task
Flow.start("watch_enemy")
Flow.send("watch_enemy", {"command": "ARM"})
wait(1000)
Flow.stop("watch_enemy")

Fields

NameDescription
paramsdict
Starting data for this flow. Each read returns an independent dict; changing it does not change the sender or later reads. The main flow receives an empty dict.

Methods

6 methods

Flow.start

Start a configured flow alongside the main flow. You can send messages as soon as this call returns. At most two background flows can run; they may also start other flows. A name cannot run twice, even while paused or stopping. Invalid or duplicate names, a full background limit, or a flow error stops the entire Run. System.stop() and Main Stop also stop all flows. The main flow waits for background flows before Run finishes: explicitly stop flows that run indefinitely. Starting data is copied using the limits in Flow.send().

Syntax

Flow.start(name, params=None)

Parameters

NameDescription
nameString
Exact name of the configured flow.
Required · Positional or named
No default
paramsdict?
Optional starting data copied for the new flow and available through Flow.params.
Optional · Positional or named
Default: None

Returns

Int — A positive number that increases with each start, used in dock status and logs. It cannot be used to control the flow.

Example

# Start recognition and telemetry beside the main flow
recognition_no = Flow.start("recognition", {"region": "arena", "threshold": 0.86})
telemetry_no = Flow.start("telemetry")

# Inside the configured recognition flow, read this branch's copied input
region_name = Flow.params.get("region", "full_screen")
threshold = Flow.params.get("threshold", 0.8)

Flow.send

Send an independent copy to a running flow without waiting. Messages are safe to send from multiple flows and are received in the order sent, including while paused. Allowed values are None, Boolean, finite numbers, String, list, tuple and dict with String keys. Maximum nesting depth is 8, total values 512 and total text length 65536. Functions, resource or app objects, and circular references cause an error. Each start has a new message queue; stopping or finishing discards unread messages.

Syntax

Flow.send(name, data)

Parameters

NameDescription
nameString
Exact configured name of the target flow. The main flow has no automatically assigned name.
Required · Positional or named
No default
dataAny
Value to send. It is copied before being added to the message queue.
Required · Positional or named
No default

Returns

Boolean — True if accepted; False for an unknown, inactive or stopping target.

Example

# Send an ARM command to the configured watcher
Flow.start("watch_enemy")
accepted = Flow.send("watch_enemy", {"command": "ARM"})
print(accepted)

Flow.receive

Wait for and remove the oldest message for this flow. The main flow and background flows can receive messages. A nested named group running in the same flow shares that flow’s queue. Cancellation ends the wait promptly; Pause keeps queued messages. Received lists and dicts are independent copies.

Syntax

Flow.receive(timeout=None)

Parameters

NameDescription
timeoutNumber?
Optional finite timeout in milliseconds: 0 <= timeout < 2^63. Fractional milliseconds are truncated; None waits indefinitely, 0 checks immediately.
Optional · Positional or named
Default: None

Returns

Any? — The oldest message, or None if the wait times out or an immediate check finds no message. A message containing None also returns None.

Example

# Configured watch_enemy flow: wait for ARM, then check commands between work
message = Flow.receive()
if message is not None and message.get("command") == "ARM":
    while True:
        command = Flow.poll()
        if command is not None:
            print(command)
        if Region().find("enemy", timeout=0).found:
            print("enemy")
        wait(100)

Flow.poll

Immediately take the oldest message for this flow without waiting. Uses the same message queue and independent copies as Flow.receive().

Syntax

Flow.poll()

Returns

Any? — The oldest message, or None if there is no message. A message containing None also returns None.

Example

# Check for a command without waiting
message = Flow.poll()
if message is not None:
    print(message)

Flow.running

Check whether the named flow is running or paused. The result may change immediately after the call.

Syntax

Flow.running(name)

Parameters

NameDescription
nameString
Exact configured name of the target flow. The main flow has no automatically assigned name.
Required · Positional or named
No default

Returns

Boolean — True while active; False when unknown, stopping or completed.

Example

print(Flow.running("watch_enemy"))

Flow.stop

Request that one background flow stop; return without waiting for cleanup. The main flow and other flows keep running. This cannot stop the main flow. Stopping yourself ends the calling flow. For a nested named group, stops the background flow that owns it. Wait for cleanup before restarting the same name. Background dock controls provide Pause/Resume. Main Pause/Resume affects all flows; Main Resume also clears their individual pause settings.

Syntax

Flow.stop(name)

Parameters

NameDescription
nameString
Exact configured name of the target flow. The main flow has no automatically assigned name.
Required · Positional or named
No default

Returns

Boolean — True for a newly requested stop; False for an absent, unknown, already stopping or main target. True does not confirm cleanup completion.

Example

print(Flow.stop("watch_enemy"))