# Launching a Motoko Workflow Motoko workflows can be run using the command line or within a Python script. ## Command-line usage Create or reset the BlackDynamite studies for a workflow: ```bash motoko create workflow_dir ``` Start launcher daemons from inside the workflow directory: ```bash cd workflow_dir motoko launcher ``` Run the orchestrator in the foreground: ```bash motoko orchestrator start --run_name test --inputs 2.1 3.2 ``` Run the orchestrator detached with `zdaemon`: ```bash motoko orchestrator start --detach --run_name test --inputs 2.1 3.2 ``` Inspect workflow state: ```bash motoko info motoko info --verbose motoko info --bd_study mult ``` Stop daemons: ```bash motoko orchestrator stop motoko kill ``` Clean BlackDynamite runs: ```bash motoko clean motoko clean --delete ``` ## Python interface The command-line interface is a thin wrapper around the Python API. A workflow can also be created and executed directly from Python: ```python from motoko.workflow import Workflow workflow = Workflow("motoko.yaml") workflow.create() workflow.start_launcher_daemons() workflow.run_name = "test" workflow.execute(inputs=[2.1, 3.1]) ``` The `Workflow` constructor reads `motoko.yaml`, creates one `TaskManager` per entry in `task_managers`, and exposes each manager as an attribute. Tasks can also be created manually outside the orchestrator function: ```python workflow = Workflow("motoko.yaml") workflow.run_name = "manual" async def submit_tasks(): runs = await workflow.mult.createTask(x=[2.1, 3.1]) finished = workflow.mult.select("state = FINISHED") return runs, finished ``` In a script, `workflow.run_name` must be set before creating tasks. Motoko stores it on every created run and uses it to scope later selections, so separate workflow executions do not accidentally interfere with one another's runs. Motoko loads `orchestrator.py` from the workflow directory and calls `main(workflow, **params)`. Parameters come from CLI arguments and are also accepted by `workflow.execute(**params)` when running from Python. For scripts that only need to add or inspect tasks, use the task managers directly: ```python workflow = Workflow("motoko.yaml") workflow.run_name = "inspection" selected = workflow.norm.select(["state = FINISHED"]) for run, job in selected: print(run.id, run.state) ``` When using the Python API outside the CLI, the caller is responsible for starting and stopping BlackDynamite launcher daemons if tasks should execute automatically: ```python subprocess.call("motoko kill", shell=True, cwd=workflow_dir) ```