--- name: pioreactor-experiment-profiles description: Write, edit, review, or debug Pioreactor experiment profile YAML, including profile structure, inputs, common jobs, per-Pioreactor jobs, action timing, expressions, MQTT lookups, and repeat or wait-until blocks. --- # Pioreactor Experiment Profiles ## Goal Help Codex produce valid Pioreactor experiment profile YAML that matches the runtime schema and uses the supported action and expression syntax. ## Experiment Profile Spec ``` # Main structure of the experiment profile version: "1.0" # Required and quoted; unquoted 1.0 is a YAML number and is rejected experiment_profile_name: # Name of the experiment profile # Metadata (optional) metadata: author: description: # Plugins (optional) plugins: - name: version: # version or constraint, e.g. "1.2.3" or ">=1.2.3" # Inputs available to expressions (optional) inputs: : # Jobs common to all Pioreactors (optional) common: jobs: : description: actions: - # see Action definitions below # Jobs per Pioreactor (optional) pioreactors: : label: jobs: : description: actions: - # see Action definitions below # Action definitions # - type: log # t: # if: # options: # message: # level: DEBUG|debug|WARNING|warning|INFO|info|NOTICE|notice|ERROR|error (default: notice) # # - type: start # t: # if: # options: {: } # expressions allowed via ${{ }} # args: [, ...] # config_overrides: {: } # expressions allowed via ${{ }} # # - type: update # t: # if: # options: {: } # expressions allowed via ${{ }} # # - type: pause # t: # if: # # - type: resume # t: # if: # # - type: stop # t: # if: # # - type: repeat # t: # if: # every: # while: # optional stop condition # max_time: # optional cap on total time loops run for # actions: # - # basic action only (log, start, pause, resume, stop, update) # # - type: when # t: # if: # wait_until: # actions: # - # any action (including repeat/when) # # # Profile expression syntax (used in ${{ ... }} in options/conditions) # # Literals # - Numbers: integer or float (e.g., 1, -2.5) # - Booleans: true, false (case-insensitive) # - Names resolve to values provided in the expression environment (inputs, etc.); otherwise they remain strings. # # Operators # - Arithmetic: +, -, *, / (raises on division by zero), ** (exponent) # - Comparisons: <, <=, ==, >=, > # - Logical: and, or, not # - Parentheses for precedence # # Functions # - random(): float in [0,1) # - unit(): current unit name # - hours_elapsed(): current action time # - experiment(): current experiment name # - job_name(): current job name # # MQTT lookups # - ::[.]* # - :::[.]* (uses current unit) # Examples: unit():od_reading:od600, ::stirring:setting.target_rpm # Fails if worker is inactive or topic missing. # # Conversion rules # - Numeric strings become floats; "true"/"false" become booleans; otherwise strings stay strings. # Time strings # Accepted formats are either a number (float/int) meaning hours, or a string that is a number immediately followed by a unit: # s, m, h, or d (case-insensitive). Examples: 0.5 (30min), "30s", "2m", "1.5h", "2d". Whitespace or extra text is rejected, and # negative values are disallowed # ``` ### Examples See more examples at https://github.com/Pioreactor/experiment_profile_examples