Skip to content

Concepts

OpenHAL is an open protocol between agents and hardware. This page defines the protocol's parts.

Hub

The Hub is one process on your computer or a Raspberry Pi, and the hub owns every device. Clients talk to the hub with JSON-RPC 2.0 messages over a WebSocket or stdio, or through the MCP server, which maps onto the same methods.

Device files

Each device has a Device File that lists what can be read, what can be changed, the limits on every change and the safe state.

openhal: "0.1"
device: Klipper 3D printer
id: printer
match:
  mdns: _moonraker._tcp
  moonraker: { hostname: "printer*" }
connect: { moonraker: printer.local, port: 7125, timeout: 5 s }
read:
  state: { type: enum, values: [standby, printing, paused, complete, cancelled, error], every: 1 s }
  extruder_temp: { unit: degC, every: 1 s, range: [0, 320] }
  bed_temp: { unit: degC, every: 1 s, range: [0, 130] }
  progress: { unit: percent, every: 5 s }
write:
  extruder_target: { unit: degC, min: 0, max: 260, max_change_per_s: 50 }
  bed_target: { unit: degC, min: 0, max: 110, max_change_per_s: 20 }
actions:
  pause:
    description: Pause the print. Klipper parks the nozzle and keeps the heaters on.
    require: ["state == printing"]
  resume:
    description: Resume a paused print.
    require: ["state == paused"]
  cancel:
    description: Cancel the print. It can't be resumed afterwards.
    confirm: confirm-each-time
safe_state:
  - { extruder_target: 0, bed_target: 0 }
interlocks:
  - if: "extruder_target > 0 degC"
    require: "state != error"
    message: "Clear the printer error before heating."
watchdog: { heartbeat: 5 s, on_loss: hold }
hazard: medium
notes: "A print keeps running if the hub goes away, so the watchdog holds the printer's state instead of stopping the print. Klipper's own heater checks stay on either way."
provenance: { source: hand-written, by: openhal print babysitter example, at: 2026-10-24 }
confirmed: { by: owner, at: 2026-10-24, sha256: 43396b8f02a70481b9653275f22cc58f96b060ad2e31f4d80214acb26e51af1a }

A file is read-only until a person confirms its limits. A limit a tool suggests stays a suggestion until a person confirms the limit.

Safety kernel

The Safety Kernel evaluates every command, from every client, in a fixed order. The kernel checks units, range, step, rate of change, interlocks, the token's scope and confirmation, and stops at the first failure. The kernel is plain code with no model in it, and an unknown value, such as a stale reading, counts as unsafe.

Drivers and grants

A Driver speaks one protocol, such as SCPI or Moonraker. A driver changes hardware only with a Grant, a single-use permission the kernel issues for one exact command.

Errors

A refused command returns a JSON-RPC error with a stable code and name.

CodeNameMeaning
-32010LIMIT_EXCEEDEDOutside the confirmed limits
-32011RATE_LIMITEDFaster than the rate limit allows right now
-32012INTERLOCK_BLOCKEDAn interlock doesn't hold
-32013CONFIRMATION_REQUIREDWaiting for a person
-32014STOPPEDThe hub is stopped
-32015UNVERIFIED_LIMITSThe device file isn't confirmed

The specification lists every code.

Principals and hazard classes

Every request comes from a principal. A person uses the human token, and an agent uses an agent token with a scope of read, control_low or control_medium. A device file sets its hazard class to low, medium or high, and every change to a high hazard device waits for a person.

Conformance levels

Hubs and drivers declare a Conformance Level. Core covers discovery and reads, Control adds changes and stop, and Full adds actions, routines and confirmations.

What OpenHAL doesn't do

OpenHAL leaves firmware in charge of each device and doesn't replace e-stops, enclosures or interlocks wired in hardware.