What a run knows about itself
Code often needs to know which run it is: to write the run id into a log line, to build a key that is unique per loop item, to tell a scheduled run from a test, or to link back to the run that sent an e-mail. Every run carries that context — as nine environment variables and as one call in each language’s library, with the same values.
- Read the run context in Python, TypeScript, JavaScript, C, C++, Go, Bash, PHP and Ruby
- Know what each field holds and when it is empty
- Match the loop index with the #N the Runs page shows
- Know the reserved variable names
The context of a run
The values are the ones the Runs page shows: WAISO_RUN_ID is the id you open on that page, a flow step sees the flow run it belongs to and the outermost flow run above it, and the trigger says how the run started. Nothing in the context is secret — ids, a path and a word — so it is safe to print and to send to another system. Inputs, outputs and variable values are never part of it.
Read it in your language
Python has waiso.run.context(); TypeScript and JavaScript import run from waiso and call run.context(); C has waiso_run_context(), C++ waiso::run::context(), Go waiso.RunContext(), PHP Waiso::runContext() and Ruby Waiso.run_context. In Bash read the variables directly.
import waiso
def main():
ctx = waiso.run.context()
print("run", ctx.run_id, "started by", ctx.trigger)
if ctx.flow_run_id: # None outside a flow
print("step", ctx.flow_step_id, "of flow run", ctx.flow_run_id)
if ctx.loop_index is not None: # 0-based: the Runs page shows #1 for 0
print("loop item #", ctx.loop_index + 1)
return {"runId": ctx.run_id, "trigger": ctx.trigger, "itemPath": ctx.item_path}{
"runId": "0f0b6c1e-…",
"trigger": "manual",
"itemPath": "reports/who_am_i"
}The fields
Python, C, C++ and Ruby name the fields in snake case (run_id); TypeScript, JavaScript and PHP in camel case (runId); Go with capitals (RunID). An empty value is null / None / NULL / nil in the library and an empty string in the environment.
| Variable | What it holds | Empty when |
|---|---|---|
WAISO_RUN_ID | This run, as on the Runs page. | A transform step (it runs no code of its own). |
WAISO_FLOW_RUN_ID | The flow run this step belongs to. | The code is not a flow step. |
WAISO_ROOT_FLOW_RUN_ID | The outermost flow run: the same as the flow run, unless a subflow started it. | The code is not a flow step. |
WAISO_FLOW_STEP_ID | The step’s id in the flow. | The code is not a flow step. |
WAISO_LOOP_INDEX | The item’s position in the innermost loop, from 0. | The step is not inside a loop. |
WAISO_PROJECT_ID | The project the run belongs to. | Never. |
WAISO_ITEM_PATH | The saved script’s (or flow’s) path, such as reports/daily. | The code was never saved. |
WAISO_TRIGGER | How the run started (the words below). | Never. |
WAISO_SCHEDULE_ID | The schedule that fired. | The trigger is not schedule. |
How a run started
| Trigger | Started by |
|---|---|
manual | A person, from the editor, the flow page or the Runs page. |
api | A call to the item’s API endpoint. |
schedule | A schedule; WAISO_SCHEDULE_ID says which. |
flow | A flow, as one of its steps or as a subflow. |
event | An event trigger: an e-mail, a database change or an MQTT message. |
link | A visitor on a shared link. |
script | Another script, through the library’s run call. |
Loops and subflows
Inside a loop the index starts at 0, while the Runs page and the run view number the items from 1: WAISO_LOOP_INDEX=0 is the row marked #1. In a loop inside a loop, the index is the inner loop’s. The flow run id plus the index makes a key that is unique per item, which is what an idempotency key or a file name per item needs:
import os
def main(email: str):
# The same values, read straight from the environment (empty string = not applicable).
flow_run = os.environ["WAISO_FLOW_RUN_ID"]
index = int(os.environ["WAISO_LOOP_INDEX"]) # 0, 1, 2…
key = f"{flow_run}:{index}" # unique per item of this flow run
print("sending", email, "as", key)
return {"key": key}A subflow is a flow run of its own: its steps see the subflow’s run as WAISO_FLOW_RUN_ID and the flow that called it as WAISO_ROOT_FLOW_RUN_ID, however deep the nesting goes. A flow that pauses for an approval keeps its ids: the steps after the decision see the same flow run and the same root.
Reserved names
- The nine names belong to the run. A new variable cannot take one of them: saving it is refused with
variable_name_reserved, also on import, copy and Git sync. - A variable that already had one of these names keeps its row on the Variables page with a Reserved name mark, but never reaches code: the run’s own value wins. Rename it.
- Reading the context costs nothing: the values are already in the environment when your code starts.