DEV Community

Cover image for air=true Is Not a Diagnosis: A Testable Python Evidence Gate for Fluidics AI Agents
yujin hu
yujin hu

Posted on

air=true Is Not a Diagnosis: A Testable Python Evidence Gate for Fluidics AI Agents

When an instrument reads air=true from a Modbus register, it is tempting to treat the bit as a fault verdict. That shortcut is unsafe.

The bit tells us what the sensor adapter observed. It does not tell us whether the event was expected during priming, caused by an empty source, produced by a suction-side leak, replayed from an old frame, or invalidated by the wrong tube setup.

This article shows a small, dependency-free Python pattern for keeping that distinction explicit.

Evidence gate flow

The real engineering question

Consider two events that contain the same raw value:

{"air": true}
Enter fullscreen mode Exit fullscreen mode

The first occurs 120 ms after a reagent switch. The pump is following a validated priming recipe, and the interface lasts 80 ms.

The second occurs during forward aspiration from a reagent bottle. It persists for 900 ms while the valve route is unchanged.

The raw observation is identical, but the engineering meaning is not. A controller therefore needs an evidence contract, not only a decoded bit.

At minimum, the contract should carry:

  • sample timestamp and monotonic sequence number;
  • communication, frame and sensor-readiness status;
  • configuration identity and tube-setup verification;
  • process phase and time since phase entry;
  • pump state, direction and valve route;
  • observed fluid state and event duration.

The AI layer may help generate the protocol adapter, analyse logs or explain a result. The final state transition should remain deterministic and testable.

A deliberately conservative state model

The reference implementation returns one of six verdicts:

Verdict Interpretation Example controller action
LIQUID_CONFIRMED Current evidence supports a liquid observation Continue under existing interlocks
EXPECTED_INTERFACE A short interface is inside an allowed process window Log and continue under phase rules
POSSIBLE_AIR_INGRESS Air persists during forward aspiration Pause fluid motion and diagnose
SENSOR_SETUP_SUSPECT Configuration, installation or residue evidence is inconsistent Pause and inspect setup
COMMUNICATION_INVALID Frame, readiness, time or sequence evidence is invalid Safe hold
NEEDS_HUMAN_REVIEW Context is insufficient for a deterministic interpretation Safe hold and review

Notice what is intentionally missing: there is no air_detected == emergency_stop rule.

Phase and context matrix

Put data validity before process interpretation

The evaluator first rejects stale, malformed or replayed observations. Only then does it reason about physical context.

if (
    not evidence.communication_ok
    or not evidence.frame_valid
    or not evidence.sensor_ready
    or age_ms < 0
    or age_ms > policy.max_sample_age_ms
    or sequence_invalid
):
    return EvaluationResult(
        Verdict.COMMUNICATION_INVALID,
        "Communication, frame, readiness, timestamp, or sequence evidence is invalid",
        "SAFE_HOLD",
    )
Enter fullscreen mode Exit fullscreen mode

This ordering prevents a common AI-agent failure mode: confidently explaining a number that should never have entered the decision path.

The next gate checks configuration identity, tube setup and residue evidence:

if (
    evidence.config_revision != evidence.expected_config_revision
    or not evidence.tube_setup_verified
    or evidence.residue_suspected
):
    return EvaluationResult(
        Verdict.SENSOR_SETUP_SUSPECT,
        "Configuration, tube setup, or residue evidence invalidates interpretation",
        "PAUSE_AND_INSPECT_SETUP",
    )
Enter fullscreen mode Exit fullscreen mode

Only a validated observation reaches the process-phase rules.

Distinguish an expected interface from possible ingress

An air event may be expected during priming, reagent switching or rinsing, but only inside a validated time window and below a validated event duration.

expected_phase = evidence.phase in {
    ProcessPhase.PRIMING,
    ProcessPhase.REAGENT_SWITCH,
    ProcessPhase.RINSE,
}

if (
    expected_phase
    and evidence.phase_elapsed_ms <= policy.expected_interface_window_ms
    and evidence.event_duration_ms <= policy.max_expected_air_event_ms
):
    return EvaluationResult(
        Verdict.EXPECTED_INTERFACE,
        "The air event falls inside an allowed interface window",
        "LOG_AND_CONTINUE_UNDER_PHASE_RULES",
    )
Enter fullscreen mode Exit fullscreen mode

By contrast, persistent air evidence during forward aspiration should trigger a different path:

if (
    evidence.phase is ProcessPhase.ASPIRATION
    and evidence.pump_running
    and evidence.pump_direction is PumpDirection.FORWARD
):
    return EvaluationResult(
        Verdict.POSSIBLE_AIR_INGRESS,
        "Persistent air evidence during aspiration requires source and suction-side checks",
        "PAUSE_FLUID_MOTION_AND_DIAGNOSE",
    )
Enter fullscreen mode Exit fullscreen mode

The word possible matters. The signal still does not identify root cause. Diagnosis may require checking the source container, fittings, tubing, valve route, mounting, medium and recent maintenance history.

Make the boundary executable

The complete reference project includes nine regression tests. They cover:

  1. normal liquid evidence;
  2. an expected short interface;
  3. possible air ingress during aspiration;
  4. stale samples;
  5. invalid frames;
  6. configuration mismatch;
  7. residue suspicion;
  8. unknown physical state;
  9. replayed or out-of-order sequences.

Run everything with standard Python 3.9+:

git clone https://github.com/blmdxiao/fluidics-bubble-evidence-gate.git
cd fluidics-bubble-evidence-gate
python3 -m unittest discover -s tests -v
python3 -m examples.evaluate_event
Enter fullscreen mode Exit fullscreen mode

The repository is available here: Fluidics Bubble Evidence Gate on GitHub.

Where AI helps—and where it should stop

Claude Code, Codex, ChatGPT, Gemini or another coding agent can be useful for:

  • generating UART, TTL or Modbus adapter scaffolding;
  • producing test fixtures from a written evidence contract;
  • checking unit conversions and schema completeness;
  • clustering logs and proposing diagnostic hypotheses;
  • reviewing whether every state has an explicit safe action.

The model should not silently invent register definitions, validated limits or tube-specific thresholds. It should also not replace deterministic interlocks with a natural-language confidence score.

A useful division of labour is:

sensor/protocol adapter
        ↓
normalized evidence package
        ↓
deterministic evidence gate
        ↓
safe controller action + auditable log
        ↓
AI explanation or diagnostic assistance
Enter fullscreen mode Exit fullscreen mode

Engineering limits

The timing values in the example are demonstrations, not release limits. Real values must be validated for tube material, wall thickness, inner diameter, medium, flow rate, mounting, sensor response and the instrument risk analysis.

For public detector specifications and application context, see the FOREACH ABD air-bubble detector.

The broader lesson is simple: a sensor bit is evidence, not a diagnosis. Giving an AI agent more context is useful, but putting an explicit, tested state contract between the agent and the hardware is what makes the workflow auditable.

Top comments (0)