Strands Robots¶
One Robot object. Any robot.
Simulated or physical, arm or humanoid, the same call. Hand it to a Strands Agent and it becomes a tool the model can use. Learned policies from the Hugging Face Hub run through the same call, in MuJoCo and on the physical robot. A policy does not reach a real arm until an operator says yes.
run_policy callStart¶
The ladder: see it in 30 seconds, run a simulated SO-101 in three minutes, talk to it, plug in the real one, run one checkpoint on both, teach it, fleet.
Robots¶
The catalog: arms, hands, humanoids, quadrupeds, mobile bases. Which ones simulate, which ones have a driver.
Agents¶
Agent(tools=[robot]). What the model sees, what it can call, and the operator gate in front of real motion.
One API, sim or real¶
The left fence runs on a laptop; the right needs an SO-101 on USB. Same tool, same verbs: the sim addresses joints by the model's names in radians, the native driver addresses servos by name in degrees. Start here.
The same checkpoint, sim or real¶
import os; os.environ["STRANDS_TRUST_REMOTE_CODE"] = "1"
from strands_robots import Robot
robot = Robot("so101", mode="sim")
robot.add_camera(name="front", position=[0.22, 0.025, 0.6], target=[0.22, 0.025, 0])
robot.add_camera(name="wrist", parent_body="so101/gripper", position=[0.058, 0.0, -0.029], target=[-0.024, 0.0, -0.297])
joints = robot.robot_joint_names("so101")
embodiment = {"state_keys": joints, "action_keys": joints, "dim_policy": "pad", "obs_rename": {
"front": "observation.images.camera1", "wrist": "observation.images.camera2", "default": "observation.images.camera3"}}
print(robot.run_policy(robot_name="so101", policy_provider="lerobot_local", instruction="pick up the cube", n_steps=60,
policy_config={"pretrained_name_or_path": "lerobot/smolvla_base", "embodiment": embodiment})["status"])
robot.cleanup()
import os; os.environ["STRANDS_TRUST_REMOTE_CODE"] = "1"
from strands_robots import Robot; from strands_robots.policies import create_policy
robot = Robot("so101", mode="real", port="/dev/ttyACM0", cameras={"front": {"type": "opencv", "index_or_path": 0},
"wrist": {"type": "opencv", "index_or_path": 1}, "top": {"type": "opencv", "index_or_path": 2}})
keys = [f"{m}.pos" for m in ("shoulder_pan", "shoulder_lift", "elbow_flex", "wrist_flex", "wrist_roll", "gripper")]
embodiment = {"state_keys": keys, "action_keys": keys, "dim_policy": "pad", "obs_rename": {
"front": "observation.images.camera1", "wrist": "observation.images.camera2", "top": "observation.images.camera3"}}
policy = create_policy("lerobot_local", pretrained_name_or_path="lerobot/smolvla_base", embodiment=embodiment)
print(robot.run_policy(policy, instruction="pick up the cube", duration=10.0)["status"])
robot.cleanup()
The left fence runs on a laptop with no GPU: SmolVLA, a vision-language-action model from the Hub, reads three cameras and the instruction and drives the simulated arm. The right one runs the same checkpoint on the physical arm, whose state arrives as <motor>.pos keys; as an agent tool, its execute waits for operator approval. Same checkpoint explains obs_rename and the embodiment.