ScriptsReference

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.

What you will learn
  • 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.

RunsEvery script and flow run in this project
Live
Search name or value · amount>100Ctrl KToday7 days30 daysAll time
Kind: AllStatus: AllWaiting for you 1
campaignFlowTriggered byScheduleDuration713msRan at5 h agoStatusSuccess
load_customersstep 1 of campaignTriggered bycampaignDuration38msRan at5 h agoStatusSuccess
send_offer ×4step 2 · loopTriggered bycampaignDuration188msRan at5 h agoStatusSuccess
approvalFlowTriggered byana@shop.devDuration174msRan at5 h agoStatusWaiting
report.pyTriggered byScheduleDuration6.7sRan at4 h agoStatusSuccess
broken.pyTriggered byana@shop.devDuration877msRan at26 min agoStatusFailed
The Runs page: the id of each row is the WAISO_RUN_ID its code read, and a loop’s rows carry #1, #2…

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.

who_am_i.py
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}
Expected outputSuccessRun from the editor
{
  "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.

VariableWhat it holdsEmpty when
WAISO_RUN_IDThis run, as on the Runs page.A transform step (it runs no code of its own).
WAISO_FLOW_RUN_IDThe flow run this step belongs to.The code is not a flow step.
WAISO_ROOT_FLOW_RUN_IDThe outermost flow run: the same as the flow run, unless a subflow started it.The code is not a flow step.
WAISO_FLOW_STEP_IDThe step’s id in the flow.The code is not a flow step.
WAISO_LOOP_INDEXThe item’s position in the innermost loop, from 0.The step is not inside a loop.
WAISO_PROJECT_IDThe project the run belongs to.Never.
WAISO_ITEM_PATHThe saved script’s (or flow’s) path, such as reports/daily.The code was never saved.
WAISO_TRIGGERHow the run started (the words below).Never.
WAISO_SCHEDULE_IDThe schedule that fired.The trigger is not schedule.

How a run started

TriggerStarted by
manualA person, from the editor, the flow page or the Runs page.
apiA call to the item’s API endpoint.
scheduleA schedule; WAISO_SCHEDULE_ID says which.
flowA flow, as one of its steps or as a subflow.
eventAn event trigger: an e-mail, a database change or an MQTT message.
linkA visitor on a shared link.
scriptAnother 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:

send_one.py
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.