A robot has to exist as a record before an operator can be offered it. That record has two halves, and the fleet screen writes both:
  • The robot record — the operator-facing id, model, site, edge PoP, RTT floor, and required cert. These are the columns the fleet table shows and the fields the console owns.
  • The capability manifest — what the robot is: degrees of freedom, which capabilities it declares, and which topics carry its body state, video, and map. One manifest drives the cockpit controls, the Foxglove layout, and the attach grant, whatever shape the robot is.
You write both at once from + Register robot on Admin · fleet. The register call goes to api.registerRobot, which in a live deployment writes the dim_robot row plus the manifest jsonb through the teleop BFF. In simulation mode it writes an in-memory fixture instead.

The robot record: id, model, site, edge PoP, RTT floor, required cert

Every field except Robot ID and Model may be left blank; the fleet table renders an em dash for anything unset.

Edge PoP binding

Each robot binds to an edge agent at a PoP close to the arm — the fleet table annotates the PoP column with · ~5ms to arm. That placement is deliberate: it puts the watchdog downstream of every link that can fail, so the component that can stop the robot is not on the far side of the link whose failure it has to survive. The record is where that binding is visible: if the PoP column is empty, nothing has been declared about where this robot’s edge agent lives.

RTT floor

The RTT floor is the floor, not a measurement of current conditions — the best round trip physics allows between the operator and this robot, given where they each are. It is recorded per robot so that observed latency can be read against something. A session sitting at the floor is as good as that pairing gets; a session well above it has a problem somewhere other than distance.

The capability manifest and what each capability enables

Capabilities are chosen from a fixed set: arm · gripper · nav · base · camera · lift The hint on the field states what the set is for: capabilities drive the cockpit controls, the Foxglove panels, and job matching. Two of them also change what the register form itself asks for:
  • camera reveals the Video topics field. Without it, the manifest’s video list is written empty.
  • nav reveals the Map topic field, which expects an OccupancyGrid topic and defaults to map. Without nav, no map entry is written to the manifest at all.
The capabilities you select are also what the attach grant advertises, which is why declaring one the hardware does not have is not a cosmetic error — it advertises a camera the arm does not have. DoF records the robot’s degrees of freedom as a whole number and is part of the manifest, not the record.

Body topic, URDF and video topics: how panels are chosen

Video topics are entered comma-separated. Each one becomes a video entry whose label is derived from the topic path: the trailing path segment is used, skipping image_raw. So camera/wrist/image_raw labels the panel wrist and camera/overhead/image_raw labels it overhead. The codec recorded for each entry is h264. This is the marketplace model at work: the panels an operator sees are not configured per robot in the cockpit. They are derived from the manifest, so a newly registered robot of an unfamiliar shape gets a working layout from its declaration alone.

Editing vs re-registering a robot

Edit reuses the same drawer, prefilled from the existing record, but it submits a different call — api.updateRobot — and it patches only the fields the console owns:
  • display name
  • model
  • site
  • edge PoP
  • RTT floor
  • required cert
The capability manifest is deliberately not editable here. Changing what a robot can do is a re-registration, not a rename. Rewriting a manifest from a form that was only partly filled in is how a fleet ends up advertising hardware that is not there, so the edit path never sends the manifest fields at all. Consistently, DoF and URDF are validated only on the register path, because the edit path does not submit them. The Robot ID is likewise not editable. It is already on the wire as a topic path segment and in every session and audit row recorded against the robot.

Retiring and restoring a robot

Retiring is reversible and keeps history. dim_robot is referenced by every session and audit row ever recorded against the robot, so the row is not deleted. The confirmation states the effect plainly: the robot leaves the fleet and stops being offered to operators, session history is kept, and it can be restored later. A retired robot keeps its record, its manifest, its tags, and everything that points at it. It renders in the muted retired status in the fleet table.

Reading the status column

Status is not part of what you fill in — it reflects what has been heard from the robot. unknown is rendered muted rather than green on purpose. This is the screen on which someone decides whether an arm can be driven, and “we have never heard from this arm” must not read as healthy.

Tagging robots

Tags attach to the robot’s dim_robot primary key, which the API returns as robotRowId. This is distinct from id, the operator-facing external robot id you typed at registration. A robot whose row id is not available shows an em dash in the Tags column instead of a tag editor. Because tags hang off the row, they survive editing the record and they survive retirement.