# Pioreactor Experiment Profiles

> 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. Use when this capability is needed.

- Skill: `tomevault-io/pioreactor-experiment-profiles` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add tomevault-io/pioreactor-experiment-profiles`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tomevault-io/pioreactor-experiment-profiles/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: tomevault-io (https://skillmd.com/u/tomevault-io)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/tomevault-io/pioreactor-experiment-profiles

---


# 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
experiment_profile_name: <string>  # Name of the experiment profile


# Metadata (optional)
metadata:
  author: <string>
  description: <string>

# Plugins (optional)
plugins:
  - name: <string>
    version: <string>  # version or constraint, e.g. "1.2.3" or ">=1.2.3"

# Inputs available to expressions (optional)
inputs:
  <input_name>: <value>


# Jobs common to all Pioreactors (optional)
common:
  jobs:
    <job_name>:
      description: <string>
      actions:
        - # see Action definitions below

# Jobs per Pioreactor (optional)
pioreactors:
  <pioreactor_unit_name>:
    label: <string>
    jobs:
      <job_name>:
        description: <string>
        actions:
          - # see Action definitions below


# Action definitions
# - type: log
#   t: <time_string_or_float>
#   if: <bool_or_expression>
#   options:
#     message: <string>
#     level: DEBUG|debug|WARNING|warning|INFO|info|NOTICE|notice|ERROR|error (default: notice)
#
# - type: start
#   t: <time_string_or_float>
#   if: <bool_or_expression>
#   options: {<option_name>: <value>}  # expressions allowed via ${{ }}
#   args: [<string>, ...]
#   config_overrides: {<config_name>: <value>}
#
# - type: update
#   t: <time_string_or_float>
#   if: <bool_or_expression>
#   options: {<option_name>: <value>}  # expressions allowed via ${{ }}
#
# - type: pause
#   t: <time_string_or_float>
#   if: <bool_or_expression>
#
# - type: resume
#   t: <time_string_or_float>
#   if: <bool_or_expression>
#
# - type: stop
#   t: <time_string_or_float>
#   if: <bool_or_expression>
#
# - type: repeat
#   t: <time_string_or_float>
#   if: <bool_or_expression>
#   every: <time_string_or_float>
#   while: <bool_or_expression>  # optional stop condition
#   max_time: <time_string_or_float>      # optional cap on total time loops run for
#   actions:
#     - # basic action only (log, start, pause, resume, stop, update)
#
# - type: when
#   t: <time_string_or_float>
#   if: <bool_or_expression>
#   wait_until: <bool_or_expression>
#   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
# - <unit>:<job>:<setting>[.<nested_key>]*
# - ::<job>:<setting>[.<nested_key>]* (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

---
> Source: [Pioreactor/pioreactor](https://github.com/Pioreactor/pioreactor) — distributed by [TomeVault](https://tomevault.io).
<!-- tomevault:4.0:skill_md:2026-06-26 -->

