You have got an agent that may already report an illustration and push it to the Hugging Face Hub. Now you need to run that loop repeatedly: gather episodes by way of the day, practice a coverage on the rising dataset, deploy it, and pull the following batch again to enhance it. Run that loop as soon as and each piece works. Run it every single day and also you begin paying for a similar byte transfers again and again. The recordings you add continue to grow, every coaching run copies the entire dataset to the GPUs earlier than it begins, and each new checkpoint ships out whereas the following batch of recordings comes again.
The primary publish on this sequence launched Strands Robots, an open supply SDK from AWS (Apache 2.0) that exposes robotic abstractions, simulation, and the LeRobot stack as AgentTools you compose right into a single Strands agent. It lined the Robotic() manufacturing unit, recording an illustration in simulation, working a coverage, and deploying the identical agent code to a bodily SO-101. That manufacturing unit resolves a reputation towards a registry of arms, humanoids, cell bases, and arms, so the SO-100 used all through this publish is one in every of many supported embodiments. The robotic catalog lists each robotic the manufacturing unit is aware of about. LeRobot’s dataset format is already utilized by over 90,000 datasets and fashions on the Hub from greater than 8,000 publishers (LeRobot Mission Pulse). A Strands Robots recording is yet another of them, so something constructed to learn LeRobot knowledge can learn it with out conversion. If you’re new to Strands Robots, begin there; this publish assumes that setup.
That publish adopted the agent loop in a single path, from a Hub dataset to a bodily robotic. This one follows the information the opposite method, from the primary recorded body again to the deployed coverage, over Hugging Face Storage Buckets – a mutable, non-versioned, Xet-backed object-storage repository sort introduced in March 2026. A bucket sits beside your dataset repositories in the identical hf:// namespace and makes use of the hf CLI you have already got, so it turns into the working layer that holds your knowledge between the day you report it and the day you practice on it.
Somebody has to determine which episodes to maintain, when the scene has drifted far sufficient to re-record, whether or not at this time’s batch is sufficient to practice on, and which checkpoint replaces the one on the arm. Every of these selections comes up dozens of instances over a group marketing campaign, and each wants a take a look at what got here again earlier than the following command goes out. That’s the work an agent is for. This publish walks you thru the information loop inside a single agent: report an illustration right into a Storage Bucket, retailer it so that every sync uploads solely the bytes that modified, practice by streaming the dataset straight from the Hub as a substitute of downloading it, and deploy the checkpoint again to {hardware} with one key phrase argument change. The runnable companion to this publish lives at examples/notebooks/05_streaming_data_loop.ipynb.
What you will construct
The place the primary publish recorded a dataset and pushed it to the Hub, the agent you construct right here information a LeRobotDataset from a natural-language immediate, syncs it right into a Storage Bucket, and streams that very same dataset again body by body, decoding digicam video on the fly, with no native copy. You learn it again in the identical course of that wrote it: the identical Strands Robots Robotic() that recorded the dataset streams it. Your skilled checkpoint then deploys to that very same Robotic() with one key phrase argument change, and the demonstrations it information on {hardware} return to the identical bucket.

Determine 1. The 4 phases share one backend. Robotic(“so100″) information a LeRobotDataset by way of the shared DatasetRecorder; sync_dataset_to_bucket(…) syncs it right into a Storage Bucket; stream_dataset(…) reads it again over the Hub with no full obtain; and the skilled checkpoint deploys to the identical Robotic with mode=”actual”. The on-disk format stays precisely as LeRobot wrote it.
As a result of one Robotic() each information a dataset and reads it again, amassing knowledge and coaching on it are two strategies on one object over one backend. The agent decides to run an episode and invokes one instrument; the rollout then proceeds on the robotic’s management frequency till the episode ends, with the skilled coverage producing each motion. The entire loop, in a handful of strains:
from strands import Agent
from strands_robots import Robotic
sim = Robotic(“so100”)
agent = Agent(instruments=[sim])
agent(“Report a pick-the-cube demo and sync it to my-org/robot-fave.”)
for batch in sim.stream_dataset(“my-org/robot-fave/cube_pick”, repo_type=“bucket”).dataloader(batch_size=64):
…
What follows is what’s truly taking place inside that loop, step-by-step.
Conditions
Minimal (default simulation path)
Python 3.12+, on Linux or macOS (Apple Silicon supported for the MuJoCo backend).
A Strands-compatible mannequin supplier for the agent’s reasoning. Amazon Bedrock with AWS credentials, the Anthropic API, OpenAI, or Ollama working regionally.
Strands Robots with the dataset extras: uv pip set up -U “strands-robots[sim-mujoco,lerobot]>=0.5.1”. The lerobot additional pulls in LeRobot (>=0.6.1), datasets, av, and torchcodec, so recording and video decode each work with out additional setup. Confer with set up information.
That is it. Each stage on this publish runs on a laptop computer with these three. What runs is the loop, not a working coverage: the default path makes use of a mock coverage, which information a sound dataset however not a helpful one.
Superior (buckets, {hardware}, actual insurance policies)
A Hugging Face account and a token with write permission, plus the hf CLI for creating buckets and syncing datasets: pip set up -U “huggingface-hub>=1.6.0,<2.0.0”, then hf auth login.
For the {hardware} path: an SO-101 follower and chief pair, or every other LeRobot-supported robotic, with calibration information below ~/.cache/huggingface/lerobot/calibration/.
For native vision-language-action (VLA) inference: an NVIDIA GPU. For coaching at scale, a GPU cluster studying from the Hub.
To run the coaching step: uv pip set up “lerobot[training]”. Recording and streaming don’t want it. When you skip it, coach.practice() returns an error end result fairly than a checkpoint. The troubleshooting information names that error and the set up that fixes it.
Step 1 – Report an illustration right into a bucket
You report new episodes by way of the day, every a steady run of digicam frames and joint state-action telemetry. LeRobot writes that as a small set of enormous information that develop as you report. Push them right into a versioned dataset repository and each append turns into a commit, and each revision is retained. Assortment needs the reverse: someplace to put in writing bytes and overwrite them in place. That could be a Storage Bucket, which lives inside your Hugging Face workspace and makes use of the permissions you have already got. There are not any id and entry administration (IAM) roles to configure, no cross-origin useful resource sharing (CORS) guidelines, and no add service to keep up.
Your agent information a LeRobotDataset in the identical format LeRobot writes on {hardware}. Report the episode, then sync the completed dataset right into a bucket. The immediate asks for the mock coverage, a stand-in that produces joint actions and not using a skilled mannequin, so you’ll be able to run the entire loop earlier than you will have a checkpoint to run:
from strands import Agent
from strands_robots import Robotic, sync_dataset_to_bucket
sim = Robotic(“so100”)
agent = Agent(instruments=[sim])
agent(
“Create a world with the so100 robotic, add a crimson dice and a entrance digicam, “
“begin recording (repo_id=’native/cube_pick’, root=”/tmp/cube_pick”, fps=30, “
“overwrite=True, process=’decide up the crimson dice’), run the mock coverage for “
“60 steps, then cease recording.”
)
sync_dataset_to_bucket(“/tmp/cube_pick”, “my-org/robot-fave”)
The sync writes to hf://buckets/{bucket}/{run_id}, the place run_id defaults to the dataset listing title. The streaming learn in Step 3 names the run too: the primary two segments of the id are the bucket, and every thing after them is the trail inside it.
sync_dataset_to_bucket(root, bucket, run_id=…) validates the dataset and syncs it by way of the hf CLI, decoupled from the recording lifecycle. The identical functionality is on DatasetRecorder.sync_to_bucket(bucket, run_id=…) should you drive an open recorder immediately, and stop_recording(bucket=…) syncs in the intervening time you cease an lively recording. The bucket is the working layer you write to by way of the day; for the versioned, revealed artifact you continue to name push_to_hub(). Each maintain the identical format.
The episode is structurally full, however the actions are placeholders, so it’s not coaching knowledge you’d need. Swap in an actual coverage with create_policy(“”) for precise greedy; the immediate, the format, and the bucket sync keep similar.
Recording on {hardware}
To report on a bodily SO-101, LeRobot’s report CLI handles the leader-follower bring-up:
lerobot-record
–robot.sort=so101_follower –robot.id=my_follower
–teleop.sort=so101_leader –teleop.id=my_leader
–dataset.repo_id=my_user/cube_picking
–dataset.single_task=’Decide up the crimson dice’
The dataset lands on disk in the identical format because the simulation recording, so the identical sync name takes it to a bucket: sync_dataset_to_bucket(“./recordings”, “my-org/robot-fave”, run_id=”run-021″) (or the hf sync ./recordings hf://buckets/my-org/robot-fave/run-021 CLI it wraps). Assortment runs append into one place, and your revealed repositories solely get the variations you select to publish.
Step 2 – Retailer with byte-level deduplication
Now {that a} dataset is within the bucket, the query is what the following sync prices you. Level two mounted cameras at an arm clearing the identical desk for eight hours and most of what you report is pixels you have already got: the identical lighting, the identical chassis, the identical background, throughout 1000’s of episodes. On a versioned repository it will get worse, as a result of altering one body in a multi-gigabyte video shard re-uploads the entire file.
Buckets are backed by Xet, which deduplicates your uploads on the byte degree utilizing content-defined chunking. Chunk boundaries comply with the content material, so inserting just a few bytes adjustments solely the chunk it lands in as a substitute of shifting each boundary after it. In Hugging Face’s personal measurements (HF Storage), content-defined chunking reduces knowledge transferred per add by about 4 instances throughout the Hub, and on Enterprise plans billing is on the deduplicated footprint. Their bucket benchmarks present what that appears like on a single file. Ranging from a 500 MB add, altering 1% of the bytes and re-uploading moved 5.5 MB, altering 5% moved 27.5 MB, and altering 10% moved 55 MB. With out chunk-level deduplication, overwriting an object means sending all of its bytes once more, whether or not or not they modified.
How a lot that saves you relies on the file structure, and the Strands Robots recorder makes use of LeRobot’s. Episodes go into Parquet shards (knowledge/chunk-000/file-000.parquet) and per-camera MP4 shards (movies/commentary.photos.entrance/chunk-000/file-000.mp4), rolling to a brand new file solely when the present one fills, at LeRobot’s defaults of 100 MB for knowledge Parquet and 200 MB for video MP4. So a sync after a day of recording uploads the brand new trailing shards plus the one partially-filled shard that grew, fairly than the entire dataset. Sync the identical bucket once more tomorrow and Xet handles the deduplication.

Determine 2. A sync uploads solely what modified. The primary sync of a contemporary dataset uploads each chunk; after recording extra episodes, Xet’s content-defined chunking means the following sync uploads solely the brand new chunks and skips those already saved.
Step 3 – Prepare by streaming from the Hub
To coach, you level GPUs at your dataset. Obtain it first and people GPUs sit idle till tons of of gigabytes end copying. Streaming straight from the Hub works right here due to the shard structure from Step 2: a batch turns into just a few byte-range reads over giant shards fairly than 1000’s of small fetches. LeRobot’s StreamingLeRobotDataset turns that right into a drop-in torch iterable, and Strands Robots exposes it by way of stream_dataset():

Determine 3. Stream, do not obtain. The obtain path copies the entire dataset to native disk first, so the GPU waits; stream_dataset() reads batches straight from the bucket with nothing on native disk, so the GPU trains from the primary batch.
reader = sim.stream_dataset(“my-org/robot-fave/cube_pick”, repo_type=“bucket”,
shuffle=False, max_num_shards=1, buffer_size=1,
)
print(reader.num_episodes, reader.num_frames, reader.fps)
for body in reader:
body[“observation.images.front”]
body[“observation.state”]
body[“action”]
break
Nothing lands on native disk besides the small meta/ folder of schema, statistics, and episode index. Digicam frames are decoded from the distant MP4 shards as you iterate; state and motion come from the Parquet shards. That loop reads one body at a time, which fits inspecting an episode. To coach, cross the reader to a DataLoader and iterate batches as a substitute. The streaming dataset shuffles internally by way of a bounded reservoir buffer, so video decoding parallelizes throughout employee processes, and the coaching step itself is the bizarre PyTorch one:
for batch in reader.dataloader(batch_size=64, num_workers=4):
loss, _ = coverage(batch)
loss.backward()
When you would fairly not write the loop in any respect, LeRobot’s personal coach reads by way of the identical engine, so the dataset your agent collected trains and not using a line of recent code. It takes a bucket by way of the identical key phrase argument the in-process reader makes use of:
lerobot-train –policy.sort=act
–dataset.repo_id=my-org/robot-fave/cube_pick
–dataset.repo_type=bucket
–dataset.streaming=true
–num_workers=4
Buckets are streaming-only, so –dataset.repo_type=bucket requires –dataset.streaming=true and the config rejects the mix in any other case. Attain for stream_dataset() once you need the loop in your personal course of: validating an episode, replaying it in simulation, or feeding a customized analysis loop. For proprioceptive-only streaming, drop_videos=True skips video decode totally, which is what makes this work on an edge machine with no torchcodec wheel. The recording and datasets information paperwork that argument together with the delta_timestamps map it requires.
Supplier names are shared between working a coverage and coaching one. create_trainer(“lerobot_local”) returns a Coach that works like create_policy(), and a TrainSpec describes the run; the record-train-deploy loop then closes in just a few strains:
import os
os.environ[“STRANDS_TRUST_REMOTE_CODE”] = “1”
from strands_robots import create_policy
from strands_robots.coaching import TrainSpec, create_trainer
coach = create_trainer(“lerobot_local”, machine=“cuda”)
spec = TrainSpec(dataset_root=“/tmp/cube_pick”, output_dir=“/tmp/cube_pick_ft”,
base_model=“”, steps=500, additional={“policy_type”: “act”})
end result = coach.practice(spec)
coverage = create_policy(end result.checkpoint_dir)
On a single NVIDIA L4 (g6.4xlarge), 500 optimizer steps of ACT (51.6M parameters, efficient batch dimension 8) over a 120-frame episode accomplished in 133 seconds and wrote a checkpoint that create_policy() hundreds again by way of the identical entry level used to run every other coverage. Coaching time scales with dataset dimension, batch dimension, and step rely, so deal with this as one measured configuration fairly than a benchmark. The “groot” and “cosmos3” suppliers goal the identical TrainSpec and Coach lifecycle, so the encircling loop is unchanged; each validates its personal required fields first, so a GR00T run wants a base_model and an embodiment tag, and a Cosmos 3 run wants a base_model and an SFT recipe. Name coach.validate(spec) earlier than practice() and it returns the precise record of what a given backend is lacking.
Hugging Face’s pre-warming caches bucket knowledge at edge areas close to the cloud and area the place your jobs run, so your cluster reads regionally and the dataloader stays forward of the GPU. In Hugging Face’s personal bucket benchmarks, a heat content material supply community (CDN) learn hit about 1,086 MB/s on a ten GB payload towards 780 MB/s chilly, and roughly 1,124 MB/s heat at 100 GB, measured on an m5dn.24xlarge in us-east-1. The complete comparability towards plain object storage, add in addition to obtain, is on that dashboard. Selecting the place that knowledge lives is a Storage Areas setting on Staff and Enterprise plans, as of this writing US and EU, with Asia-Pacific and Gulf Cooperation Council (GCC) areas introduced as coming; exterior these plans repositories are saved within the US.
On macOS, import strands_robots places Homebrew’s ffmpeg on the loader path for you, so torchcodec decodes streamed video with out additional setup.
Step 4 – Deploy the coverage and return knowledge to the loop
On this step you’re taking the checkpoint you simply skilled, run it on a bodily robotic, and report the following spherical of demonstrations with it. This is similar agent code from the primary publish, with one key phrase argument modified to mode=”actual”:
robotic = Robotic(“so100”, mode=“actual”, port=“/dev/ttyACM0”,
cameras={“entrance”: {“sort”: “opencv”, “index_or_path”: “/dev/video0”, “fps”: 30}})
agent = Agent(instruments=[robot])
agent(“Decide up the crimson dice.”)
The checkpoint runs towards the bodily arm, and the demonstrations that arm information are saved to disk in the identical LeRobot format you began with, able to sync again to the bucket for the following coaching run.
In case your knowledge already lives on Amazon Easy Storage Service (Amazon S3), not one of the format work on this publish adjustments. A LeRobotDataset is a listing of Parquet and MP4 shards, so it shops on Amazon S3 the identical as anyplace else, and the recording, coaching, and deploy steps learn that format wherever it sits. What a bucket provides is the Hub-native route: sync_dataset_to_bucket and stream_dataset(repo_type=”bucket”) goal hf:// immediately, so that you get the sync and the streaming learn with no separate storage path to wire up. Each paths run the identical loop: Amazon S3 if that’s the place your knowledge already sits, a bucket if you would like the sync and the streaming learn with out provisioning storage first.
Run the loop once more tomorrow and you’re recording into that bucket, syncing solely the bytes that modified, and streaming these bytes to the GPUs with out ready for a obtain. The info by no means leaves the LeRobot format, and it by no means leaves the Hub.
Strive it utilizing the pattern utility
The complete Strands Robots pattern is on GitHub at strands-labs/robots in examples/notebooks/05_streaming_data_loop.ipynb. It walks you thru the complete loop cell by cell: report, render, sync to a bucket, stream again, practice, and cargo the checkpoint. Each cell runs in simulation on the mock coverage, so no GPU, no Docker, and no Hugging Face credentials are wanted.
git clone https://github.com/strands-labs/robots.git
cd robots
uv pip set up -U “strands-robots[sim-mujoco,lerobot]>=0.5.1”
jupyter pocket book examples/notebooks/05_streaming_data_loop.ipynb
Run the cells high to backside. The recorded dataset lands below /tmp/nb5_dataset. To sync it to a bucket, set BUCKET = “my-org/robot-fave” within the first cell (after hf auth login); the neighboring RUN_ID names the folder contained in the bucket, and the pocket book streams again from f”{BUCKET}/{RUN_ID}”. To coach on a GPU, elevate steps to 500 and set machine=”cuda”. The agent-driven model of the identical loop lives at examples/06_agent_collect_and_stream.py.
Safety Issues
The snippets listed here are a “hi there world” of the Strands Robots knowledge loop. 5 issues change when you run it towards actual knowledge.
Immediate injection. Supplying untrusted knowledge to an agent can result in immediate injection, the place untrustworthy context is handled as LLM directions. These brokers actuate robots and now additionally write to and skim from shared storage, so this is a vital danger to trace. Feed the agent solely knowledge from trusted sources. If not all enter may be trusted, prohibit the instruments out there to the agent so it can not take safety-critical actions or overwrite bucket contents.
Coaching knowledge is a belief boundary. An agent that may write into the gathering bucket may write episodes {that a} coverage later trains on, and that coverage drives a bodily arm. Maintain the credential that writes assortment knowledge separate from the one a coaching job reads with, sync every run below its personal run_id so an episode may be traced to the run that produced it and eliminated by itself, and deal with the versioned dataset repository because the reviewed artifact, as a result of the bucket retains no revisions to audit towards.
Bucket credentials and scope. sync_dataset_to_bucket(…), stop_recording(bucket=…), and sync_to_bucket add by way of the hf CLI utilizing the token from hf auth login. Use a token scoped to the particular namespace you’re writing to, choose –private buckets for assortment knowledge, and maintain the bucket distinct from the versioned dataset repository you push_to_hub and share.
Overwrite in place retains no revisions. A bucket overwrites in place and retains no revisions, which is what makes it a working layer and in addition means a repeated run_id replaces the run already saved there. Go an specific run_id per assortment run, as in sync_dataset_to_bucket(“./recordings”, “my-org/robot-fave”, run_id=”run-021″). For something you want to have the ability to return to, push_to_hub() to a versioned dataset repository, the place each revision is retained.
Solely use trusted Hugging Face orgs. The native inference path hundreds Hugging Face fashions with trust_remote_code=True. Set STRANDS_TRUST_REMOTE_CODE=1 to decide in, and solely load checkpoints from organizations you belief. When loading pre-trained weights from the Hub (e.g., by way of pretrained_name_or_path), confirm the group is trusted earlier than loading. Mannequin weights can include arbitrary code (pickle-based checkpoints). Want safetensors-format checkpoints the place out there.
Clear up
The loop leaves a bucket, datasets below /tmp, and a checkpoint on disk. Bucket contents rely towards your saved quantity, so take away what you not want:
hf buckets rm my-org/robot-fave/cube_pick/ –recursive –dry-run # lists, removes nothing
hf buckets rm my-org/robot-fave/cube_pick/ –recursive # –yes skips the immediate
hf buckets delete my-org/robot-fave # takes every thing in it
rm -rf /tmp/cube_pick /tmp/cube_pick_ft /tmp/nb5_dataset /tmp/nb5_ft
Cease any coaching course of nonetheless on a GPU occasion, and cease the occasion. When you ran the pocket book, substitute its RUN_ID (nb5_demo by default) for cube_pick. Something you revealed with push_to_hub() is in a versioned repository and is untouched.
The place to go from right here
The Strands Robots documentation covers the robotic catalog, simulation, coverage suppliers, recording, and the mesh in depth. The recording and datasets information paperwork the DatasetRecorder API, sync_dataset_to_bucket / sync_to_bucket, and stream_dataset in full.
When you gather from a couple of robotic, give each its personal run_id they usually write into the identical bucket in parallel. The multi-robot mesh followers one agent out throughout these robots, so the identical loop turns into a fleet amassing by way of the day into shared storage. A streaming reader reads one run at a time. The recording and datasets information describes easy methods to practice throughout a number of of them.
In order for you a bigger coverage than ACT, the TrainSpec and Coach lifecycle from Step 3 covers GR00T and Cosmos 3 behind their very own supplier names, so fine-tuning a VLA on the dataset you simply streamed is similar calls with a distinct supplier string and a base mannequin. Operating the result’s the place the paths diverge, as a result of a VLA checkpoint deploys to {hardware} fairly than to the simulator you skilled from. For heavier simulation to generate that knowledge, the Newton (sim-newton) and Isaac Sim (isaac) backends sit behind the identical Robotic() manufacturing unit, so the agent code doesn’t change as you scale up.
Bucket streaming reached LeRobot by way of contributions from each the Strands Robots and LeRobot groups, upstream in LeRobot itself, so the datasets your agent collects are readable by each instrument in that ecosystem. That runs each methods: the reader in Step 3 opens any of the LeRobot datasets already revealed on the Hub, so an agent can replay and consider towards present demonstrations earlier than it information one in every of its personal.
Contributions are welcome below Apache 2.0. When you construct one thing with this loop, open a problem with what labored and what did not.
Assets
Strands Robots
LeRobot and the Hub
Insurance policies
Background

