Sentio OS

Developer Preview

Program the Unitree G1 in Python

Sentio OS turns the G1 EDU into a robot you can script: say something, drive a metre, find an AprilTag, close the gripper — each is one line of Python or one HTTP request. The same API powers the Sentio web interface and the Flow block editor.

198HTTP endpoints

robot, driving, navigation, LiDAR, camera, speech, gripper, Flow

29 + 6steps and conditions in Flow

blocks you can also start, stop and watch from code

10 minto the first application

20 developers without humanoid experience, workshop on 17 September 2026

Developer Preview. The Python SDK and this guide are new and still evolving. We are looking for the first developers to try them on their own G1 EDU and tell us what's missing. Join the preview.

Three steps to the first script

Install Sentio on the G1 EDU

Sentio runs as a Docker container on the robot's second computer (PC2). Connect over SSH — the address depends on your network; on the robot's wired network it is 192.168.123.164:

ssh unitree@<robot>
docker --version

Registry access and the three install commands are in My account. The installer prints the web address, the API key and the device ID. Manual control and robot care are free and never expire.

Get an API key

The installer prints the main key at the end (Klíč). It is also stored on the robot:

grep BACKPACK_API_KEY ~/sentio/.env

Teams sharing one robot get their own keys in Settings → Keys and reservations. Every request sends the key in the X-API-Key header.

Run your first script

Check the connection with curl:

curl -H "X-API-Key: $KEY" http://<robot>:8000/api/v1/robot/status

Then say hello from Python (below). Stop everything at any time with robot.stop_all() or Stop all in the web interface.

Python SDK

The sentio package is a thin synchronous client over the REST API (its only dependency is httpx). During the Developer Preview we send it directly to participants.

from sentio import Robot

robot = Robot("http://192.168.0.10:8000", api_key="…")   # or env SENTIO_URL / SENTIO_API_KEY
robot.say("Hello", lang="en", output="robot")
robot.gesture("wave_under_head")
robot.walk(1.0)                     # = drive(vx=0.3, max_m=1.0) + wait until driving=False
robot.turn(90)
print(robot.lidar.front())          # nearest obstacle ahead in metres, None without LiDAR

What else the SDK covers:

robot.health() ; robot.activity() ; robot.stop_all()
robot.say("Hello", lang="en", output="robot")
robot.mode("walk") ; robot.modes()
robot.drive(vx=0.3, vyaw=0.0, max_sec=5, max_m=2) ; robot.drive_stop() ; robot.drive_status()
robot.walk(1.0)                     # = drive(vx=0.3, max_m=1.0) + wait until driving=False
robot.turn(90)                      # navigate/turn?wait=true
robot.navigate.go_tag(4, stop_cm=60) ; robot.navigate.search(4, direction="left")
robot.navigate.stop() ; robot.navigate.status()
robot.lidar.front() -> float        # from GET /lidar/pruh (nearest in the strip), None without LiDAR
robot.lidar.sectors() ; robot.lidar.strip(width_m=0.7, length_m=4.0)
robot.odom()
robot.camera.snapshot() -> bytes ; robot.camera.apriltags() ; robot.camera.objects() ; robot.camera.describe()
robot.gripper.open(side="auto") ; robot.gripper.close(grip="soft") ; robot.gripper.status()
robot.gesture("wave_under_head")
robot.flow.list() ; robot.flow.start("Pozdrav") ; robot.flow.stop() ; robot.flow.status()
for ev in robot.flow.events(run_id): ...   # generator over polling /flow/events?since_seq

Errors are exceptions: AuthError (401), Forbidden (403), Reserved (423 — another team holds the robot), Busy (409), RobotUnavailable (503), ValidationError (422).

REST API

Everything the SDK does is plain HTTP under /api/v1. The interactive documentation runs on the robot itself — open http://<robot>:8000/docs and try any endpoint from the browser (the OpenAPI schema is at /openapi.json).

GroupMain endpointsPackage
SystemGET /health · GET /status · GET /activity · POST /stop-all · GET /modulesBase
Robot and drivingGET /robot/status · GET /robot/modes · POST /robot/mode · POST /robot/drive · GET /robot/drive · POST /robot/drive/stop · POST /robot/gesture · POST /robot/ledBase
NavigationPOST /navigate/go-tag · POST /navigate/search · POST /navigate/turn · POST /navigate/stop · GET /navigate/statusMotion & Performance
LiDARGET /lidar/status · GET /lidar/sectors · GET /lidar/pruh · GET /lidar/snapshot · GET /lidar/cloud (stream) · GET /lidar/imuBase
OdometryGET /robot/odomBase
CameraGET /video/snapshot · GET /video/stream · POST /video/apriltag/detect · POST /video/object/detect · POST /video/say-what-you-seeBase
SpeechPOST /say · GET /tts/voices · POST /stt/listen · POST /stt/transcribeBase
GripperGET /gripper/status · POST /gripper/open · POST /gripper/close · POST /gripper/stopBase
FlowGET /flow · POST /flow/{name}/start · POST /flow/stop · GET /flow/status · GET /flow/events?since_seq=Base

Paths are relative to http://<robot>:8000/api/v1. Commands (POST) from a team key need a reservation when teams share the robot; reading and stopping always work.

Want to be among the first?

Write to us — tell us what robot you have and what you'd like to build. We'll send you the SDK and help you get to the first script.

Write to us  info@sentiorobotix.com