Model a Process Workflow

This tutorial shows how a process template becomes a provenance record. A template defines slots, steps, role bindings, and parameters; a run supplies concrete resources and values.

Define the workflow

from recap.utils.general import Direction

with namespace.build_process_template("Measure Plate", "1.0") as template:
    template.add_resource_slot("input_plate", "plate", Direction.input)
    template.add_resource_slot("result_file", "file", Direction.output)
    (
        template.add_step("Measure")
        .add_parameters({
            "acquisition": [
                {"name": "exposure", "type": "float", "default": 0.1, "unit": "s"},
                {"name": "mode", "type": "str", "default": "standard"},
            ]
        })
        .bind_slot("source", "input_plate")
        .bind_slot("destination", "result_file")
        .close_step()
    )

Slots are the stable interface between a workflow and its resources. Role bindings let the step logic refer to source and destination without naming one particular plate or file.

Create a run

with namespace.build_process_run(
    name="Measure Plate 001",
    description="First measurement",
    template_name="Measure Plate",
    version="1.0",
) as run:
    run.assign_resource("input_plate", input_plate)
    run.assign_resource("result_file", result_file)

    params = run.get_params("Measure")
    params.acquisition.exposure = 0.25
    run.set_params(params)

The run records assignments and parameter values alongside the ordered steps. Use model_dump() to inspect a parameter model and model_json_schema() to inspect its generated validation schema.

Inspect assignments

When loaded with resources, assigned values are available by slot name:

run = (
    namespace.query_maker()
    .process_runs()
    .include_steps(include_parameters=True)
    .include_resources()
    .first()
)

input_plate = run.assigned_resources["input_plate"].resource