Skip to content

Working with AI assistants

Homeostat is built so that an AI assistant can drive it: a plant and its timeline are a declarative scenario (YAML or JSON), every problem comes back with a code, a location and a fix, and everything an assistant needs is one command away, with no network and no Python session. The homeostat command ships with the package (python -m homeostat does the same).

The loop

  1. Find out what exists. homeostat describe lists every template, fault, degradation, maintenance task, sensor preset and operator with a line each; homeostat describe flow_loop valve_stiction gives the parameters, ports and an example of use for the names you give.
  2. Start from an example. homeostat examples lists complete scenarios; homeostat examples plant_history > plant.yaml saves one to change.
  3. Write the scenario. Template parameters are keys of the unit itself, beside id and template. Durations are written 30s, 10min, 2h, 1d.
  4. Validate it. homeostat validate plant.yaml reports every problem it can find at once, each with a fix, and says what the scenario describes: the time base, the units, the loops, the number of events.
  5. Say what plant you described. homeostat explain plant.yaml answers in plain language, without running anything: the units, the loops (what each controller reads and writes), the inputs and which loops they disturb, and the timeline of changes. Compare it with what you meant.
  6. State what the run should show, and check it. Add an expect: section (a controlled variable that stays quiet, a valve that moves, a fault that is visible or hidden, grade changes that settle) and run homeostat diagnose plant.yaml. Each expectation passes or fails with the numbers behind it; see Checking a run against what you meant.
  7. Run it and read the summary. homeostat run plant.yaml --out out/ simulates, prints a summary (statistics of each observed signal, the first events, the warnings) and writes the data and the ground truth.
homeostat describe temperature_loop
homeostat examples disturbance_rejection > plant.yaml
homeostat validate plant.yaml
homeostat explain plant.yaml
homeostat diagnose plant.yaml
homeostat run plant.yaml --out out/

After an edit, homeostat diff before.yaml after.yaml shows what changed in the file and what the plant does differently (units, loops, signals and events added or removed), which is how to tell that a small edit rewired the plant, or that a large one changed nothing.

homeostat guide prints the documentation index, and homeostat guide guides/plans a page of it. The guides, the reference pages and the examples are inside the package, so they are there offline.

Commands

Command What it does
homeostat guide [topic] Print a documentation topic, or the index.
homeostat describe [name ...] [--kind K] [--json] List what exists, or describe the given names. A name that belongs to several kinds (fouling is a fault and a degradation) prints each; --kind picks one.
homeostat schema [--template T] Print the JSON Schema of a scenario, or only the unit shape of one template.
homeostat examples [name] [--json] List the example scenarios, or print one.
homeostat validate scenario [--json] Check a scenario without running it.
homeostat explain scenario [--all] [--json] Describe the plant in plain language: units, loops, inputs and what each disturbs, the timeline.
homeostat diagnose scenario [--json] Simulate and check the expect section; exit 3 when an expectation does not hold.
homeostat diff a b [--json] Compare two scenarios: the keys that differ, and what the compiled plants do differently.
homeostat run scenario [--out DIR] [--json] Simulate and summarize; with --out, write truth.csv, measured.csv, observed.csv and meta.json (one set per lane, truth.lane0.csv, ..., for runs with several lanes). Times are seconds in time_s, or timestamps with output.start.
homeostat convert scenario --to json\|yaml Rewrite a scenario in the other format. Comments are not kept.

A scenario is a YAML or JSON file, or - for standard input. Both formats are read by the same loader and give the same run; use YAML for files people read (it has comments) and JSON for tool calls and structured output.

Every command that reports takes --json. Exit codes: 0 success, 1 the scenario or the request is invalid (the problems are printed), 2 a usage error, 3 diagnose ran and an expectation did not hold.

Errors and warnings

An error stops the run. It has a code (see error codes), the location in the file, the reason and a fix, and the fix is meant to be applied:

[E_UNKNOWN_PORT] exogenous[0].target: Unit FIC-101 (flow_loop) has no port 'presure', so this source would drive nothing. Fix: Did you mean 'pressure'?

A warning (a code starting with W_) means the scenario is valid and runs, but something in it changes nothing: a source that no operator reads, an event scheduled after the end of the run, a regime the plan never visits. These are almost always mistakes, so read them:

[W_UNUSED_SIGNAL] exogenous[1].target: 'FIC-1O1.pressure' is not a port of any unit and no operator reads it, so it has no effect on the plant. Fix: Did you mean 'FIC-101'?
[W_EVENT_AFTER_END] interventions[0]: An event here is scheduled at 2h, but the run ends at 1h, so it never happens. Fix: Move it earlier, or lengthen `duration`.

With --json, validate prints one object:

{
  "ok": false,
  "file": "plant.yaml",
  "errors": [{"code": "E_UNKNOWN_PORT", "location": "exogenous[0].target", "reason": "...", "fix": "Did you mean 'pressure'?", "severity": "error"}],
  "warnings": [],
  "summary": null
}

When it succeeds, ok is true, errors is empty, warnings lists the warnings and summary describes the scenario. Problems are found in stages: the schema and every misspelt name (templates, parameters, faults, degradations, tasks, sensors) together, then the plant, then the compiled graph. Fixing the first ones can reveal more, so validate again until it says OK.

In Python, the same information is on the objects: HomeostatError.issues (each with to_dict()), homeostat.prepare(source).warnings, and run.meta["warnings"].

The schema

homeostat schema prints the JSON Schema of a scenario with the vocabulary of the process library: each template is its own unit shape with its parameters, units, defaults and choices, each degradation likewise, and fault, task and sensor names are enumerations. Any number may be a distribution ({normal: ...}), and plans and faults may be generators. Use it with an editor that checks YAML against a schema, with a validator, or with constrained decoding so that a misspelt name cannot be produced. homeostat schema --template reactor prints the unit shape of one template, which is small.

The schema checks the shape of a file. homeostat validate is the authority: it also checks wiring, targets, the single-writer rule and everything else that needs the compiled plant.

Writing scenarios that mean what you intended

  • Every signal has one writer. Change a regulated variable through its setpoint (<loop>.sp), and a controller output through manual mode (<loop>.mode: MAN and <loop>.man_out).
  • Instrument noise is a percentage of the measurement span, so set spans around the expected values.
  • Units connect through ports: exogenous: [{target: <unit>.<port>, from: <signal>}]. homeostat describe <template> lists the ports.
  • A fault is hidden by the loop that controls it: a transmitter bias shows on the true value and on the valve, not on the controlled reading. Look at run.truth as well as run.observed.
  • Write the expectations first, or with the scenario: they are the intent, in a form a command can check.
  • A run is deterministic: the same scenario, seed and package versions give the same data, so a result can be reproduced from meta.json.