Robot Agent Services
The robot agent lets the tablet identify a robot and inspect its health without
touching the control path. It is a small read-only service that runs alongside
ROS, and it never imports ROS, never acquires a control lease, and never
publishes actuator commands. Control traffic stays on rosbridge port 9090.
What the services do
Section titled “What the services do”Two systemd services make up the agent:
hausbots-robot-agent— the HTTP service on port8080. It answers with the robot’s identity and a health snapshot.hausbots-robot-health— a read-only ROS adapter. It subscribes to/hb2/app/status, writes/run/hausbots/health.json, and is the only part that talks to ROS at all.
The agent exists so the tablet can discover robots on the switch, show diagnostics while ROS is down or faulted, and gate launch on fresh readiness. It is not a second control channel: commands and telemetry stay on rosbridge.
Endpoints
Section titled “Endpoints”All three endpoints are GET only, and every response carries
Cache-Control: no-store:
| Endpoint | Purpose |
|---|---|
/api/v1/identity |
Stable robot identity used for discovery and defaults |
/api/v1/health |
Diagnostic snapshot used to verify readiness |
/healthz |
Liveness: 200 with ok while serving, 503 during shutdown |
Identity and health return JSON. Identity looks like this:
{ "schemaVersion": 1, "protocolVersion": "1.0.0", "robotId": "hb2-23", "displayName": "Wall Crawler 23", "model": "HB2", "capabilities": ["drive", "fan", "static-camera", "mira", "pundit", "lifter"], "rosbridgePort": 9090, "isSimulator": false}Health is a diagnostic snapshot. A fully ready robot:
{ "schemaVersion": 1, "status": "ready", "components": { "controller": "ready", "rosbridge": "ready" }, "uptimeSeconds": 1234, "observedAt": "2026-09-22T08:00:00.000Z"}The same robot with the ROS side down:
{ "schemaVersion": 1, "status": "degraded", "components": { "controller": "unknown", "rosbridge": "offline" }, "uptimeSeconds": 1234, "observedAt": "2026-09-22T08:00:00.000Z"}How health is computed
Section titled “How health is computed”The adapter writes /run/hausbots/health.json from /hb2/app/status at 10 Hz.
The agent reads that file and treats a snapshot older than five seconds — or
more than two seconds in the future — as stale, reporting
controller: unknown. It adds a bounded loopback TCP probe as rosbridge.
Overall ready requires a fresh snapshot with controller: ready and
rosbridge: ready; anything else is degraded.
observedAt is the robot’s own clock and is never compared against the
tablet’s clock.
What the tablet does with it
Section titled “What the tablet does with it”The tablet scans port 8080 across the switch subnet. For each candidate it
validates the identity response, fetches health, and probes rosbridge itself.
It launches only a fully verified candidate: health ready with controller
ready. A robot with a valid identity but degraded health stays visible in the
list for diagnostics — it just cannot be launched. Health is diagnostic only
and never grants a control lease.
The bundle
Section titled “The bundle”The agent ships as one tarball from this site. See Downloads for sizes and checksums.
| File | Purpose |
|---|---|
hausbots-robot-agent-linux-arm64 |
The service binary |
install-robot-agent.sh |
Installer (verifies ROS prerequisites, installs files, creates the hausbots user, enables services) |
robot-agent.example.json |
Configuration template |
hausbots-robot-agent.service |
HTTP service unit |
hausbots-robot-health.service |
ROS health adapter unit |
ros/health_snapshot.py |
Adapter script |
Before installing
Section titled “Before installing”Run these checks on the robot first. A fresh shell needs ROS sourced so
rospack and rosmsg are on PATH:
source /opt/ros/noetic/setup.bashrospack find hb2_api_bridgerosmsg show hb2_api_bridge/TabletStatusBoth must succeed. The installer refuses to run when either is missing. If a check fails, stop and contact HausBots: the robot is missing the bridge package this agent is paired with, and installing the agent will not fix that.
Install
Section titled “Install”The offline path is the normal one for a robot on an isolated switch. Download and verify the bundle on a workstation:
curl -fLO https://hausbots-docs.celeriscode.com/downloads/robot-agent/hausbots-robot-agent-linux-arm64.tar.gzcurl -fLO https://hausbots-docs.celeriscode.com/downloads/robot-agent/hausbots-robot-agent-linux-arm64.tar.gz.sha256sha256sum -c hausbots-robot-agent-linux-arm64.tar.gz.sha256 # expect: OKscp hausbots-robot-agent-linux-arm64.tar.gz robot@10.0.0.23:/tmp/Then, on the robot:
tar -xzf /tmp/hausbots-robot-agent-linux-arm64.tar.gz -C /tmpcd /tmp/hausbots-robot-agent-v*-linux-arm64sudo ./install-robot-agent.shThe directory name carries the bundle version; v* matches whatever version
you downloaded.
The installer verifies hb2_api_bridge and hb2_api_bridge/TabletStatus,
installs /usr/local/bin/hausbots-robot-agent,
/usr/local/libexec/hausbots-health-snapshot.py, both systemd units, and
/etc/hausbots/robot-agent.json, creates the hausbots system user, and
enables and starts both services. It preserves an existing configuration unless
--replace-config is passed.
If the robot has internet access, fetch and run the same tarball directly on the robot:
curl -fLO https://hausbots-docs.celeriscode.com/downloads/robot-agent/hausbots-robot-agent-linux-arm64.tar.gzcurl -fLO https://hausbots-docs.celeriscode.com/downloads/robot-agent/hausbots-robot-agent-linux-arm64.tar.gz.sha256sha256sum -c hausbots-robot-agent-linux-arm64.tar.gz.sha256 # expect: OKtar -xzf hausbots-robot-agent-linux-arm64.tar.gzcd hausbots-robot-agent-v*-linux-arm64sudo ./install-robot-agent.shConfigure the identity
Section titled “Configure the identity”Edit /etc/hausbots/robot-agent.json. Every robot on a switch needs its own
robotId and displayName; never reuse an id, and never run a simulator on a
robot’s address.
| Field | Meaning |
|---|---|
identity.schemaVersion |
Must be 1 |
identity.protocolVersion |
Semver whose major must be 1 (e.g. 1.0.0) |
identity.robotId |
Stable id used in discovery (e.g. hb2-23) |
identity.displayName |
Human name shown on the tablet (e.g. Wall Crawler 23) |
identity.model |
Robot model string (e.g. HB2) |
identity.capabilities |
Non-empty strings; the tablet acts on static-camera (standard camera and LED), pundit (PTZ camera and controls), mira, lifter; conventional drive and fan describe the base robot; unknown values are ignored |
identity.rosbridgePort |
Rosbridge port, 9090 |
identity.isSimulator |
false for a real robot |
listenAddress / httpPort |
HTTP bind, 0.0.0.0 / 8080 |
rosbridgeHost / rosbridgePort |
Health probe target, 127.0.0.1 / 9090 |
healthSnapshotPath |
/run/hausbots/health.json |
The installed template in full:
{ "identity": { "schemaVersion": 1, "protocolVersion": "1.0.0", "robotId": "hb2-23", "displayName": "Wall Crawler 23", "model": "HB2", "capabilities": ["drive", "fan", "static-camera", "mira", "pundit", "lifter"], "rosbridgePort": 9090, "isSimulator": false }, "listenAddress": "0.0.0.0", "httpPort": 8080, "rosbridgeHost": "127.0.0.1", "rosbridgePort": 9090, "healthSnapshotPath": "/run/hausbots/health.json"}Apply the change:
sudo systemctl restart hausbots-robot-agentUnit dependencies
Section titled “Unit dependencies”The health unit orders itself after roscore.service, rosbridge.service, and
robot_launch.service. If the robot’s bridge runs under different unit names,
override the dependencies with a drop-in, which survives installer updates:
sudo systemctl edit hausbots-robot-health.serviceIn the editor, add (replacing your-bridge.service with the actual unit name):
[Unit]Wants=After=Wants=roscore.service your-bridge.serviceAfter=roscore.service your-bridge.serviceThen apply it:
sudo systemctl daemon-reloadsudo systemctl restart hausbots-robot-healthThe empty Wants=/After= lines reset the inherited lists, which is why they
come before the new values.
The agent itself only needs rosbridge reachable on 127.0.0.1:9090.
Verify
Section titled “Verify”From another machine on the switch:
curl http://10.0.0.23:8080/api/v1/identitycurl http://10.0.0.23:8080/api/v1/healthcurl http://10.0.0.23:8080/healthz # expect: okOn the robot:
systemctl status hausbots-robot-agent.service hausbots-robot-health.servicejournalctl -u hausbots-robot-agent -n 20 --no-pagerjournalctl -u hausbots-robot-health -n 20 --no-pagerIdentity should print the configured values. Health should show ready with
both components ready once ROS is up; healthz prints ok. Both services
should be active, and the journal tails should be free of repeating errors.
Update
Section titled “Update”Download the new bundle, verify its checksum, and re-run the installer on the
robot. The existing configuration is preserved, so identity and network
settings survive the update. Unit-file edits do not survive updates — the
installer re-copies both units. Dependency overrides made with systemctl edit
are drop-ins and do survive.
Uninstall
Section titled “Uninstall”sudo systemctl disable --now hausbots-robot-agent.service hausbots-robot-health.servicesudo rm -f /lib/systemd/system/hausbots-robot-agent.service /lib/systemd/system/hausbots-robot-health.servicesudo rm -f /usr/local/bin/hausbots-robot-agent /usr/local/libexec/hausbots-health-snapshot.pysudo rm -f /run/hausbots/health.jsonsudo systemctl daemon-reloadKeep /etc/hausbots/robot-agent.json if you plan to reinstall; remove it and
the hausbots system user only when the robot will not run the agent again.
Troubleshooting
Section titled “Troubleshooting”| Symptom | Fix |
|---|---|
Identity returns 404 |
Wrong path; only the three endpoints above exist. |
| Agent exits with code 2 | /etc/hausbots/robot-agent.json failed validation; read the logged field error and fix the config. |
Health stays degraded, controller unknown |
The adapter has no fresh /hb2/app/status; check systemctl status hausbots-robot-health and that the bridge publishes status. |
Health shows rosbridge offline |
Nothing is listening on 127.0.0.1:9090; start the rosbridge service. |
Health shows degraded, controller unknown after a fault clears |
The adapter writes 10 Hz; refresh once the bridge reports a fresh status. |
| Port 8080 already in use | ss -ltnp | grep 8080; stop the conflicting process or change httpPort (and the tablet scan setting). |
| Services do not start after reboot | systemctl is-enabled hausbots-robot-agent hausbots-robot-health; re-run the installer if disabled. |
