Hugging Face · 官方博客

从 Hugging Face Hub 到机器人硬件:Strands Agents 与 LeRobot 实践

From the Hugging Face Hub to robot hardware with Strands Agents and LeRobot

二〇二六年六月十七日 · 英文原文

AWS 发布了 Strands Robots 开源 SDK(Apache 2.0),将 LeRobot 栈暴露为 AgentTool,实现从 Hugging Face Hub 数据集到物理机器人的完整 agent 循环。该集成支持 SO-101 机械臂,仿真(MuJoCo)与硬件模式共享相同 LeRobotDataset 格式,仅需更改一个关键字参数即可切换。GR00T 和 LerobotLocal 提供策略推理,MolmoAct2 检查点通过后者运行。内置 Zenoh 对等 mesh 可协调多台机器人,支持 broadcast 和 emergency_stop 等集群操作。

](https://huggingface.co/rsundaraws)

Image 2: Cagatay Cali 的头像

Strands Robots 中 LeRobot 集成的演练——一个 agent 循环,从 Hub 数据集到物理机器人,使用相同磁盘格式的 sim-to-real 数据集和只需一个字符串即可切换的策略。

你有一台机器人,Hugging Face Hub 上有一个演示数据文件夹,以及一个你想让它学习的新任务。如今这需要五个独立的工具:一个用于录制新演示,另一个用于训练,第三个用于在仿真中测试,自定义代码用于部署到硬件,以及另一个用于协调多台机器人。这些组件各自独立工作,彼此之间没有通信。

Strands Robots 是来自 AWS 的开源 SDK(Apache 2.0),它将机器人抽象、仿真和 LeRobot 栈暴露为 AgentTool,你可以将它们组合成一个单一的 Strands agent。这种集成刻意保持轻量:LeRobot 自身的脚本处理硬件录制和校准,而 Strands AgentTool 则负责 agent 实际编排的部分。仿真工具录制的 LeRobotDataset 与 LeRobot 在硬件上写入的格式相同。GR00TLerobotLocal 在通用接口背后提供策略推理,MolmoAct2 检查点通过 LerobotLocal 路径运行。一个对等 mesh 将 agent 扩展到远程机器人。数据集格式完全保持 LeRobot 写入时的样子;agent 循环是粘合剂。

本文将通过一个 agent 内部的五个步骤进行讲解:在 LeRobot AgentTool 之上构建 agent,在仿真中将演示录制为 LeRobotDataset,在同一台机器人上运行策略,仅更改一个关键字参数即可将相同的 agent 代码部署到物理 SO-101,并通过 Zenoh mesh 向整个机器人集群广播指令。最后,你可以从 GitHub 克隆可运行的示例应用,并在笔记本电脑上的仿真环境中运行。默认路径无需硬件、GPU 或 Hugging Face 凭证。本文的可运行配套文件位于 examples/lerobot/hub_to_hardware.pyhub_to_hardware.ipynb。该 notebook 默认仅使用仿真和 Mock 策略。

你将构建什么

Strands Robots SDK 将 LeRobot 栈暴露为 AgentTool,你可以将它们组合成一个 Strands agent。本文中的示例 agent 执行四项操作:在仿真中录制新的演示,将结果作为 LeRobotDataset 推送到 Hub,在仿真中针对相同格式运行策略,以及仅更改一个关键字参数即可将相同的 agent 代码部署到物理机器人。当你拥有多台机器人时,agent 可以通过内置的对等 mesh 协调整个集群。对于硬件录制和校准,LeRobot 自身的 CLI(lerobot-recordlerobot-calibrate)负责启动;agent 从那里接手。

Image 3: arch_hugginface

图 1. Robot("so100") 默认返回一个 MuJoCo 支持的仿真;mode="real" 返回一个由 LeRobot 驱动的硬件机器人。两种模式共享相同的 DatasetRecorder 和相同的策略提供者,因此在仿真中捕获的数据集和在硬件上捕获的数据集使用相同的磁盘格式 LeRobotDataset。

两个设计选择使其得以实现。首先,Robot("so100") 默认返回一个仿真(无需硬件,无风险),而 mode="real" 返回一个由 LeRobot 驱动的硬件机器人。agent 代码在两种模式下完全相同。其次,写入 LeRobotDataset 的 DatasetRecorder仿真路径和 LeRobot 自身的硬件录制之间共享,因此在 MuJoCo 中捕获的数据集和从物理 SO-101 捕获的数据集格式相同。

整个工作流程只需五行 Python 代码:

from strands_robots import Robot
from strands import Agent

arm = Robot("so100") # mode="sim" (默认 - 安全,无需硬件)
agent = Agent(tools=[arm])
agent("Pick up the red cube")

接下来将逐步揭示该调用内部实际发生的事情。

前提条件

最低要求(默认仿真路径)

就是这样。本文中的示例在满足这三个条件的笔记本电脑上端到端运行。

高级(硬件部署、真实策略、Hub 推送)

步骤 1 - 设置示例

安装 Strands Robots 并获取示例文件:

uv pip install "strands-robots[sim-mujoco,lerobot,mesh]"
git clone https://github.com/strands-labs/robots.git
cd robots

如果你希望 agent 推送数据集或从 Hub 拉取策略,请导出你的 Hugging Face token。对于本文中的默认仿真路径,这是可选的;示例使用 Mock 策略端到端运行,并将数据集写入本地缓存,无需 Hub 访问权限。

export HF_TOKEN=hf_...

可运行示例位于 strands-labs/robots 仓库中的 examples/lerobot/hub_to_hardware.py(Python 脚本)和 hub_to_hardware.ipynb(notebook),与 MuJoCo 和 LIBERO 示例放在一起。notebook 是推荐的起点:在 JupyterLab 中打开它,并在仿真模式下从上到下运行单元格,无需连接任何硬件。

步骤 2 - 录制演示并推送到 Hub

仿真工具录制 LeRobotDataset 的格式与 LeRobot 在硬件上写入的格式相同。无需硬件。Simulation 工具的 start_recording 操作通过相同的 DatasetRecorder 类写入:相同的关节状态和动作 parquet schema,相同的每摄像头 MP4 布局。agent 提示几乎相同:

from strands import Agent
from strands_robots import Robot

robot = Robot("so100")  # 默认 mode="sim"
agent = Agent(tools=[robot])

agent(
    "Record a demonstration of 'pick the red cube and place it in the box' "
    "using the Mock policy provider at FPS 30. Write the dataset to "
    "my_user/cube_picking_sim and push to the Hub when done."
)

Image 4: sim_scene

图 2. MuJoCo 仿真中的录制场景:SO-100 机械臂伸向地面上的红色立方体,捕获到 LeRobotDataset。此默认路径无需硬件、GPU 或 Hugging Face 凭证。

使用 Mock 策略是有意为之:它生成占位关节动作,以便工作流程无需训练好的检查点即可端到端运行。机器人会执行随机运动而非完成抓取,录制在结构上是完整的(有效的关节状态、有效的摄像头帧、格式良好的 LeRobotDataset episode),但演示本身作为训练数据并无用处。下面的步骤 3 将替换为 GR00T 或 LerobotLocal 以实现真实的抓取行为。要在此步骤中看到实际的立方体拾取,请运行 --policy lerobot_local --checkpoint allenai/MolmoAct2-SO100_101(一个 MolmoAct2 检查点,从其 config.json 自动检测并通过 LerobotLocal 路径路由);提示、数据集格式和 agent 代码保持不变。

证明在于接下来发生的事情。LeRobot 自身的数据集加载器无需任何 Strands 特定代码路径即可读取仿真记录的数据:

from lerobot.datasets.lerobot_dataset import LeRobotDataset

dataset = LeRobotDataset("my_user/cube_picking_sim")
print(dataset.features)
# {'observation.state': Sequence(...),
#  'observation.images.front': VideoFrame(...),
#  'action': Sequence(...),
#  'episode_index': Value(...), 'frame_index': Value(...), ...}

这个 features 字典在形状上与 Hub 上的任何 LeRobot 数据集相同:相同的列名、相同的 parquet+MP4 布局、相同的加载器路径。消费硬件记录数据的训练脚本无需修改即可消费仿真记录的数据。如果需要,从仿真推送的数据集可以与硬件记录一起存放在同一个 Hub 仓库中。

一个录制的 LeRobotDataset 中的单个 episode,从录制器写入的每摄像头 MP4 回放,与训练脚本读取的磁盘视频相同。

在硬件上录制

要在物理 SO-101 上录制演示而非仿真,请直接使用 LeRobot 的 record CLI。Strands 集成并未将该命令包装为 AgentTool,因为 LeRobot 已经很好地完成了这项工作:

lerobot-calibrate --robot.type=so101_follower --robot.id=my_follower
lerobot-calibrate --robot.type=so101_leader   --robot.id=my_leader

lerobot-record \
  --robot.type=so101_follower --robot.id=my_follower \
  --teleop.type=so101_leader  --teleop.id=my_leader \
  --dataset.repo_id=my_user/cube_picking \
  --dataset.single_task='Pick up the red cube and place it in the box' \
  --dataset.num_episodes=25 \
  --dataset.push_to_hub=true

此命令推送到 Hub 的数据集格式与仿真录制相同。要在此基础上微调策略,请运行 LeRobot 的训练 CLI(lerobot-train);训练本身不在本文讨论范围内,遵循标准的 LeRobot 工作流程。从步骤 3 开始,agent 可以互换地使用原始检查点或微调后的检查点。有关完整的 SO-101 硬件设置、校准演练和故障排除,请参阅示例文件夹中的 README

步骤 3 - 在仿真中运行策略

数据集在 Hub 上之后,下一步是运行策略。该示例使用默认仿真模式的 Robot() 工厂,然后附加 gr00t_inference,以便 agent 管理推理容器:

from strands import Agent
from strands_robots import Robot, gr00t_inference

robot = Robot("so100")  # 默认 mode="sim"
agent = Agent(tools=[robot, gr00t_inference])

agent(
    "Start GR00T inference on port 5555 with the cube-picking checkpoint "
    "from my_user/cube-picker. Then ask the robot to pick up the red cube."
)

在底层,agent 运行 gr00t_inference(action="lifecycle", lifecycle="full", ...) 来拉取 GR00T 容器镜像,从 Hub 下载检查点,并启动推理服务。然后,它在仿真机器人上使用 policy_provider="groot" 运行 run_policy 操作,在 policy_config 字典中传递 GR00T 服务的主机和端口(容器可通过端口 5555 访问)。仿真随策略的动作块步进,结果渲染可通过 Simulation.render 获得。

Image 5: sim_grasp

图 3. 使用训练好的策略(GR00T 或 MolmoAct2 检查点),agent 驱动 SO-100 在仿真中抓取红色立方体,这是 Mock 策略所替代的行为。

对于偏好进程内推理(无需容器,无需 ZeroMQ (ZMQ))的开发者,可以将 gr00t_inference 替换为从 Hub 仓库加载的 LerobotLocalPolicy 实例。该提供者会将 lerobot/ 组织下的任何模型 ID 路由到进程内路径:

from strands_robots.policies import create_policy
policy = create_policy("lerobot/act_aloha_sim_transfer_cube_human")

LerobotLocalPolicy 支持 ACTDiffusion PolicySmolVLAπ0π0.5,以及任何 LeRobot 自身策略注册表能从 config.json 解析的内容。对于提供 rtc_config 的 flow-matching 策略(π0、SmolVLA),实时分块会自动启用。

NVIDIA 最近发布的 Cosmos 3 也可作为同一接口背后的策略提供者,因此无论你指向哪个提供者,agent 代码都保持不变。

注意:LerobotLocalPolicy 使用 trust_remote_code=True 加载 Hugging Face 模型。设置 STRANDS_TRUST_REMOTE_CODE=1 以选择加入,并且只加载来自你信任的组织的检查点。

步骤 4 - 将策略部署到物理硬件

这与步骤 3 的代码相同,只更改了一个关键字参数。Robot 工厂返回一个由 LeRobot 的 make_robot_from_config 驱动的硬件机器人:

robot = Robot(
    "so100",
    mode="real",
    port="/dev/ttyACM0",
    data_config="so100_dualcam",
    cameras={
        "front": {"type": "opencv", "index_or_path": "/dev/video0", "fps": 30},
        "wrist": {"type": "opencv", "index_or_path": "/dev/video2", "fps": 30},
    },
)
agent = Agent(tools=[robot, gr00t_inference])

agent(
    "Start GR00T inference on port 5555 with the cube-picking checkpoint "
    "from my_user/cube-picker. Then ask the robot to pick up the red cube."
)

相同的 agent 提示现在针对物理机械臂运行。硬件路径使用 LeRobot 的机器人抽象进行关节命令和摄像头读取,而端口 5555 上可访问的 GR00T 容器生成动作块。

在针对你的 SO-101 运行之前,必须准备好从动臂和主控臂的校准。每个设备运行一次 LeRobot 的校准命令(lerobot-calibrate);文件会存放在 ~/.cache/huggingface/lerobot/calibration/ 下,任何接触硬件的 Strands 代码路径都会从那里读取。如果缺少校准,agent 会从 LeRobot 驱动层抛出错误。

步骤 5 - 使用 mesh 协调多台机器人

到目前为止,我们一次只驱动一台机器人。Mesh 是 Strands Robots 处理多台机器人的方式。想象一下,你桌上的主控臂远程操作另一个房间的从动臂,或者五台 SO-101 并行执行相同的仓库任务,或者一个人形机器人与移动底座协调。所有这些都是 mesh 模式。Mesh 构建在 Zenoh(一个开源的对等协议)之上,你无需管理 IP 地址、编写发现代码或选择代理;新机器人一上线就会出现在 mesh 上,agent 可以同时与所有机器人通信。

每个 Robot() 和每个 Simulation() 都会自动加入一个 Zenoh 对等 mesh。robot_mesh 工具为 agent 提供了用于集群操作的词汇表,例如发现、结构化命令、广播和紧急停止:

agent = Agent(tools=[robot_mesh])

agent(
    "List every robot and simulation on the mesh. "
    "Then send 'go to home pose' to each one in parallel."
)

agent 调用 robot_mesh(action="peers") 来枚举本地和已发现的 peers,然后调用 robot_mesh(action="broadcast", ...) 向每个 peer 发送带有超时的结构化命令。添加 [mesh-iot] 附加组件可将此流量通过 AWS IoT Core 路由,用于跨网络集群。项目文档中的 robot_mesh 工具操作参考涵盖了完整的词汇表:subscribe、watch、inbox 和结构化点对点命令。

默认情况下,每个物理执行 mesh 操作在运行前都会暂停等待人工批准中断:集群范围的 broadcast 和 emergency_stop,以及单 peer 的 tell、send 和 stop。你可以使用 STRANDS_MESH_HITL_ACTIONS 环境变量调整此集合(设置为 allnone 或逗号分隔的子集)。第一次运行此示例时,你会在终端中看到 robot_mesh-broadcast-approval 提示;输入 y(或 yes / approve)以授权广播。该批准在 LLM 的工具参数之外传递,因此试图将批准标志潜入命令体的 prompt injection 攻击无法绕过此关卡。

传输层无需修改 agent 代码即可扩展。内置的 Zenoh mesh 是自动回退方案:在 LAN 上,Zenoh 多播无需代理即可处理 peer 发现;添加 [mesh-iot] 附加组件可通过 AWS IoT Core(MQTT5 with mTLS)路由流量,用于云集群,并带有一个 BridgeTransport,通过一个 API 扇出 LAN 和云(使用 STRANDS_MESH_BACKEND=bridge 选择)。

对于生产集群,Device Connect(与 Arm 合作开发的设备感知网络层)处理发现、存在、结构化 RPC、事件路由和安全性。相同的 robot_mesh 工具在 Device Connect 可用时通过它进行调度,否则回退到内置的 Zenoh mesh,因此本文中的 agent 代码无论哪种方式都保持不变。有关设置和当前可用性,请参阅 Device Connect 文档

使用示例应用进行尝试

完整示例位于 GitHub 上的 strands-labs/robots 仓库的 examples/lerobot/ 文件夹中。它将所有五个步骤打包成一个 CLI 脚本(hub_to_hardware.py)和一个 notebook(hub_to_hardware.ipynb)。CLI 默认使用 Mock 策略在仿真中端到端运行。无需 GPU、Docker 或 Hugging Face 凭证。

uv pip install "strands-robots[sim-mujoco,lerobot,mesh]"
git clone https://github.com/strands-labs/robots.git
cd robots

export STRANDS_MESH_LOCAL_DEV=1

python examples/lerobot/hub_to_hardware.py

录制的数据集存放在 ~/.cache/huggingface/lerobot/local/strands-cube-pick/。要推送到 Hugging Face Hub 而非本地保存,请在导出具有写入范围的 HF_TOKEN 后传递 --hf-user <your-user>。要在步骤 3 中获得真实的抓取行为,请传递 --policy groot --checkpoint <hf_repo>(需要 Docker + NVIDIA GPU)或 --policy lerobot_local --checkpoint <hf_repo>(需要 GPU 和 STRANDS_TRUST_REMOTE_CODE=1)。

notebook(examples/lerobot/hub_to_hardware.ipynb)逐单元格地讲解相同的工作流程,每一步之间都有说明。在 JupyterLab 中打开它,并在仿真模式下从上到下运行。

安全考量

本设置中显示的代码片段代表了使用 HuggingFace 设置 Strands Robots 的“hello world”示例。对于更严肃、生产就绪的用例,用户应注意一些重要考量:

Prompt Injection

向 agent 提供不受信任的数据可能导致 prompt injection,即不可信的上下文被视为 LLM 指令。鉴于这些机器人在物理空间中的驱动能力,这是一个需要关注的重要风险。为了减轻这种行为,开发者应小心地只向机器人提供来自可信来源的数据。如果并非所有输入数据都可信,开发者应限制 agent 可用的工具,以防止机器人执行安全关键操作。

Robot Mesh 认证行为

本文代码片段中共享的 STRANDS_MESH_LOCAL_DEV=1 设置会在没有认证或访问控制的情况下初始化机器人 mesh。这意味着同一网络上的任何设备都可以向机器人集群发送命令。这对于受信任的开发环境是可以接受的,但不适用于不受信任的网络或生产环境。对于这些用例,需要 STRANDS_MESH_AUTH_MODE=mtls

集群范围操作的操作员批准

robot_mesh 工具的物理执行操作会影响网络上的 peers:broadcast 和 emergency_stop 到达每个 peer,而 tell、send 和 stop 到达单个目标 peer。为了防止 agent 自主(或在 prompt injection 下)发出这些命令,默认情况下所有五个操作都通过人工介入中断进行门控。当 agent 调用门控操作时,Strands 运行时会暂停 agent 循环,并要求操作员在 LLM 的工具参数之外进行批准。你可以使用 STRANDS_MESH_HITL_ACTIONS 环境变量(allnone 或逗号分隔的子集)调整门控集合。每个操作的速率限制、命令验证和审计跟踪与中断并行运行。在 agent 循环之外(裸脚本或单元测试),门控操作会安全失败。

清理

前面的工作流程会启动一个 GR00T 容器,在硬件上打开串行端口,并写入本地数据集缓存。要将环境恢复到干净状态:

整体架构

该集成的核心设计选择是 Strands Robots 不重新实现 LeRobot 已经提供的功能。硬件抽象、校准和数据集格式保持在上游。Strands 添加了 AgentTool 接口,使其可以通过自然语言进行组合。

这带来了两个结果。对于用户来说,Hub 上的每个数据集都是 agent 可以扩展、微调并部署的资产,无需转换步骤。对于开发者来说,仿真数据和硬件数据共享单一文件格式,因此为一种数据编写的训练脚本可以不加修改地消费另一种数据。仿真与真实之间的界限变成了部署细节,而非架构鸿沟。

后续方向

Image 6: fleet

图 4. Strands Robots 目录涵盖机械臂、人形机器人、四足机器人和灵巧手,全部在相同的 MuJoCo 仿真中,并位于相同的 Robot() 工厂背后。本文中的 SO-100 是众多支持的形态之一。

完整的 Strands Robots 文档深入介绍了机器人目录、仿真、策略提供者、mesh 和 Device Connect。对于更大的工作负载,strands-labs/robots-sim 仓库托管了更重的仿真后端,包括 Isaac Sim 和 Newton,以及一个 LIBERO 基准测试示例。两个后端都插入本文所示的相同 Robot 抽象,因此随着规模扩大,agent 代码保持不变。

欢迎在 Apache 2.0 下贡献。如果你使用此工作流程构建了某些东西,请提交一个 issue,说明哪些有效,哪些无效。当开发者反馈直接落在需要改进的接口上时,SDK 改进最快。

资源


作者

Cagatay Cali 是 AWS 的研究工程师,专注于 Agentic AI 和机器人技术。他设计将 AI agent 连接到物理机器人的接口,使开发者能够通过自然语言控制机器人系统,并让任何技能水平的构建者都能进行 agent 和机器人开发。

Sundar Raghavan 是 AWS Agentic AI Foundations 团队的高级解决方案架构师。他领导 Amazon Bedrock AgentCore 的开发者体验,负责 SDK 和 CLI,并推动框架和生态系统集成策略。他专注于开发者如何在 AWS 上构建、部署和扩展生产级 AI agent。他目前正在将这一重点扩展到物理 AI,与 Strands Robots 合作,将相同的 agent 开发者体验引入机器人领域。

译自 Hugging Face · 官方博客 · 录于 二〇二六年六月十七日