Roboflare
SDKs

Python SDK

Operator client plus a robot-side helper for emitting structured logs that flow back to the dashboard.

The Python SDK has two shapes living in the same package:

  • Client — operator-side. Talks to the control plane over HTTPS. This is the analog of the TypeScript RoboflareClient.
  • Roboflare — robot-side. Writes structured JSONL records to the log path the agent tails, so your robot app can call Roboflare.log(...) and have lines show up in the dashboard log debugger.

Install

The SDK lives in this monorepo as sdk/python. Until it is published to PyPI, install in editable mode:

pip install -e ./sdk/python

Operator client

from roboflare import Client

with Client(token="rf_org_...") as rf:
    robots = rf.robots.list()
    print(f"{len(robots)} robots online")

    release = rf.releases.create({"semver": "1.2.3", "notes": "speed tune"})
    print(release["id"])

The client unwraps Roboflare's { "data": ... } / { "items": [...] } envelope automatically — list endpoints return the array, single-object endpoints return the inner data.

Resources

rf.robots.list()
rf.robots.inspect(robot_id)
rf.robots.logs(robot_id)

rf.releases.list()
rf.releases.create({"semver": "1.2.3"})

rf.configs.list()
rf.configs.set({"name": "...", "namespace": "...", "payload": {...}})

rf.enrollment_keys.list()
rf.enrollment_keys.create({"site_id": "...", "fleet_id": "..."})
rf.enrollment_keys.revoke(key_id)

Errors

Non-2xx responses raise RuntimeError with the API's error message extracted from the { "error": { "message": "..." } } envelope. Catch and inspect:

try:
    rf.releases.create({})
except RuntimeError as e:
    print("API rejected:", e)

Robot-side Roboflare helper

On the robot, your application emits structured records and the agent tails them into the tunnel — your code never opens a socket.

from roboflare import Roboflare

robot = Roboflare.connect()  # reads ROBOFLARE_LOG_PATH or defaults to ~/.roboflare/app.log

robot.log("starting pick task", task_id="abc123")
robot.event("pick_complete", duration_ms=842)
robot.metric("battery_pct", 73.2)
robot.ros_node("nav2_lifecycle_manager", status="running")
robot.rosbag("/var/lib/rosbags/2026-05-20T08-00.bag", action="started")

Every call appends one JSON record to the log file with ts, level, source, message, and the extra fields you passed. The agent tails that file and streams it to the dashboard's log debugger.

Set ROBOFLARE_LOG_PATH if you want to write somewhere other than ~/.roboflare/app.log — useful when running your app inside a container that mounts a host-side log volume.

On this page