Skip to main content

Edge Agent Configuration

The agent is configured with a single YAML file, config.yaml, that it reads on startup. By default it looks for config.yaml in the working directory; you can also pass a path as the first command-line argument.

Because the file contains your API key, restrict its permissions:

chmod 600 config.yaml

Example config.yaml​

# ── Cloud connection (required) ──────────────────────────────
cloud_api_url: "https://api.haltless.io"
api_key: "YOUR_API_KEY"

# ── Collection behaviour ─────────────────────────────────────
collection_interval_seconds: 10 # how often to poll every source
batch_size: 100 # readings per HTTP request (max 1000)

# ── Local buffer (offline resilience) ────────────────────────
buffer_dir: "/var/lib/haltless-agent"
max_buffer_size_mb: 512

# ── TLS / logging ────────────────────────────────────────────
ca_cert_path: null # custom CA bundle, or null for defaults
log_level: "INFO"

# ── Data sources (one entry per System) ──────────────────────
sources:
- type: modbus
system_identifier: "CNC-001"
connection:
host: "192.168.1.100"
port: 502
registers:
- address: 0
count: 1
register_type: holding
metric_name: temperature_celsius
unit: celsius
scale: 0.1
offset: 0.0

- type: opcua
system_identifier: "ROBOT-002"
connection:
endpoint_url: "opc.tcp://192.168.1.200:4840"
username: ""
password: ""
nodes:
- node_id: "ns=2;i=1001"
metric_name: spindle_speed_rpm
unit: rpm

- type: csv
system_identifier: "PRESS-003"
connection:
directory: "/data/press-exports"
delimiter: ","
col_timestamp: "timestamp"
col_metric: "metric_name"
col_value: "value"
col_unit: "unit"

- type: json
system_identifier: "CONVEYOR-004"
connection:
directory: "/data/conveyor-exports"
key_timestamp: "timestamp"
key_metric: "metric_name"
key_value: "value"
key_unit: "unit"

Top-level keys​

KeyTypeRequiredDefaultDescription
cloud_api_urlstringYesBase URL of the Haltless API, e.g. https://api.haltless.io. Must start with http:// or https://.
api_keystringYesYour account API key. Sent as the X-API-Key header on every request. Must not be empty.
collection_interval_secondsintegerNo10How often, in seconds, to poll every configured source. Minimum 1.
batch_sizeintegerNo100Number of readings to accumulate before sending one HTTP request. Range 1–1000. When a cycle collects more than one batch (an MQTT source can), it sends full batches while half the collection interval lasts and buffers the rest locally.
sourceslistNo[]One entry per machine. See Sources below.
ca_cert_pathstringNonullPath to a custom CA certificate bundle for HTTPS verification. Leave null to use the system trust store. If set, the file must exist.
log_levelstringNoINFOLog verbosity. One of DEBUG, INFO, WARNING, ERROR, CRITICAL.
max_buffer_size_mbintegerNo512Maximum size of the on-disk buffer. When exceeded while offline, the newest readings are dropped to keep storage bounded. Minimum 1.
buffer_dirstringNo"."Directory for the local buffer file. See Buffer directory.

Buffer directory​

buffer_dir is where the agent keeps its crash-safe local buffer (buffer.db) and a small file that stores the agent's stable identity. Point it at a writable directory the agent's service user owns, such as /var/lib/haltless-agent.

The directory must be a normal data location. System directories (for example /etc, /root, /proc, /sys, /dev, /boot, and core binary paths) are rejected at startup. Use a project-owned path instead.

The buffer only holds readings that could not be delivered immediately. In normal operation it stays small or empty. Two limits keep it bounded:

  • Size cap: max_buffer_size_mb. When the buffer reaches this size while offline, the newest readings are dropped.
  • Retention: buffered readings older than about 24 hours are evicted automatically, even if the size cap has not been reached.

TLS verification​

The agent always verifies the TLS certificate of the Haltless API. Leave ca_cert_path as null to use your system's default trust store, which is correct for the standard https://api.haltless.io endpoint. Only set ca_cert_path if you connect through an endpoint that presents a certificate signed by a private or internal certificate authority; in that case, point it at that CA's bundle.

Sources​

Each entry in sources describes one System (one connection the agent reads, such as a PLC or a folder of exports) and how to read it. On the portal, machines are built from a System's tags on the Systems page. Every source has the same three top-level fields:

FieldTypeRequiredDescription
typestringYesCollector type: modbus, modbus_rtu, opcua, s7, ethernet_ip, melsec, fins, ads, bacnet, mqtt, sparkplug_b, pi_web_api, csv, or json. These are the agent's own names; a System's protocol on the portal and API spells three of them differently (modbus_tcp, opc_ua, bacnet_ip).
system_identifierstringYesThe System this source is, as shown on the portal's Systems page. 1–255 characters, case-sensitive, must match exactly. machine_identifier, its earlier name, still works.
connectionmapYesCollector-specific settings. See Protocols for the full shape of each.

The connection block differs per collector. In brief:

  • Modbus: host, port, and a list of registers to read.
  • Modbus RTU: the serial port, its baudrate, parity, and stopbits, a default unit_id, and a list of registers, as for Modbus.
  • OPC-UA: endpoint_url, optional username/password, and a list of nodes to read.
  • Siemens S7: host, slot (and optionally rack), and a list of tags, each with an address such as DB10.DBD4:REAL.
  • EtherNet/IP: host, controller (logix or slc), optionally slot, and a list of tags, each a Logix tag name or an SLC data-file address.
  • Mitsubishi MELSEC: host, the MC protocol connection's port, optionally xy_numbering, and a list of tags, each a device address such as D100.
  • Omron FINS: host, optionally the node numbers, and a list of tags, each an address such as D100 or CIO0.03.
  • Beckhoff ADS: host, optionally ams_net_id and ams_port, and a list of tags, each a variable's symbol such as MAIN.speed.
  • BACnet/IP: the device's host and a list of points, each an object such as analog-input,1 and optionally a property.
  • MQTT: the broker's host and the topics to subscribe to, optionally a login, TLS files, hold_seconds, and units by topic.
  • Sparkplug B: the broker settings as for MQTT, and a group_id, optionally narrowed to an edge_node_id and device_id.
  • AVEVA PI Web API: the base_url, a login, and a list of points, each a PI point or AF attribute path.
  • CSV: a watched directory plus the column names to map (col_timestamp, col_metric, col_value, col_unit).
  • JSON: a watched directory plus the key names to map (key_timestamp, key_metric, key_value, key_unit).

See Protocols for every connection key, its default, and how each maps to a reading.

What a reading contains​

Whatever the source, the agent produces readings with the same fields and sends them to Haltless:

FieldRequiredNotes
machine_identifierYesThe source's system_identifier. Sent under this name for compatibility; the API accepts system_identifier too.
timestampYesISO 8601, in UTC.
metric_nameYesUp to 255 characters.
valueYesA finite number. NaN and infinite values are skipped.
unitYesUp to 50 characters. Readings with an empty unit are skipped.
raw_tagNoOriginal source tag or address, up to 500 characters.

Overly long metric_name, unit, or raw_tag values are truncated to their limits and logged, rather than rejected.

Timestamps​

Timestamps must be in UTC. For the PLCs and controllers (Modbus TCP and RTU, OPC-UA, S7, EtherNet/IP, MELSEC, FINS, ADS, and BACnet/IP), the agent stamps each reading with the collection time in UTC. For MQTT, a reading carries the message's own time when it has one (one more than two minutes ahead of the agent's clock is replaced by the arrival time), else the time it arrived; a value sent again from the hold carries the cycle's time. Sparkplug B works the same way with each metric's own timestamp. For PI Web API, a reading keeps the time PI recorded it. For CSV and JSON, the timestamp comes from your exported data. If a value has no timezone offset, the agent assumes UTC and logs a one-time warning. Keep the agent host's clock synchronized (for example with NTP) so timestamps line up with the rest of your data.

Next steps​

  • Protocols: the full connection reference for each collector
  • Troubleshooting: buffering, auth, and clock issues
  • API keys: create and rotate the key used by api_key