
A policy that nails pick and place collapses at step seven. The compounding-error arithmetic behind it, and the two ways out: a planner above a language-conditioned actor, or longer demonstrations.
What you need to know
- •Stage success multiplies. Ten stages at 95 percent each land at 60 percent end to end. The ACT paper's own per-stage tables show it: on Prep Tape the four stages score 96, 92, 72 and 64 percent.
- •Behaviour cloning error grows quadratically in the horizon, not linearly. Ross, Gordon and Bagnell's bound is J(pi) <= J(pi*) + T^2 * epsilon, and the paper states it behaves as Theta(T^2 * epsilon) for small epsilon.
- •Action chunking divides the effective horizon by the chunk length. That is a useful constant factor, not an escape.
- •Route one is decomposition: a high-level model emits one subtask string at a time, a language-conditioned policy executes it. Hi Robot reports 76 percent average instruction accuracy against 36 for a flat VLA.
- •Route two is longer demonstrations plus memory. MEM solves tasks needing up to fifteen minutes of memory, but its headline results come from pretraining that no public checkpoint ships.
- •On AY-Robots you train and serve the low-level half. The planner loop is code you write. Nothing on this platform decomposes a task for you.
What actually breaks at step seven
A policy trained on 50 clean pick-and-place episodes will pick and place. Train the same architecture on a task with ten stages, open a drawer, take out a cup, set it down, close the drawer, pour, stir, and so on, and it will usually get three or four stages in and then stall, or repeat a stage it already completed, or reach for something that is no longer where the demonstrations left it. The training loss looks fine. The open-loop replay looks fine. The robot still does not finish.
This is not a mysterious failure. It is arithmetic, and it was measured carefully in the original ACT paper (Zhao, Kumar, Levine and Finn, Learning Fine-Grained Bimanual Manipulation with Low-Cost Hardware, arXiv 2304.13705). That paper reports success per stage as well as per task, across eight tasks in its Tables I and II. The per-stage columns are the most useful table in low-cost manipulation, because they show exactly where the run dies.
| Task (ACT, 25 trials each on real hardware) | Stage 1 | Stage 2 | Stage 3 | Stage 4 |
|---|---|---|---|---|
| Slide Ziploc (grasp, pinch, open) | 92 | 96 | 88 | - |
| Slot Battery (grasp, place, insert) | 100 | 100 | 96 | - |
| Open Cup (tip over, grasp, open lid) | 100 | 96 | 84 | - |
| Thread Velcro (lift, grasp, insert) | 92 | 40 | 20 | - |
| Prep Tape (grasp, cut, handover, hang) | 96 | 92 | 72 | 64 |
| Put On Shoe (lift, insert, support, secure) | 100 | 92 | 92 | 92 |
| Bimanual Insertion (simulated, human data) | 76 | 66 | 20 | - |
Read the rows sideways. Slot Battery barely degrades, because every stage is easy and the object barely moves. Thread Velcro falls from 92 to 20 across three stages, and the paper's own error analysis blames a mid-air regrasp and a low-contrast object rather than the horizon. Prep Tape loses roughly a third of its runs over four stages even though no single stage is below 64 percent. ACT collected 50 demonstrations per task, 100 for Thread Velcro, at 50 Hz, with episodes of 8 to 14 seconds, which the paper notes is 400 to 700 timesteps. A genuinely ten-step household task is several times that.
If your ten stages each succeed 95 percent of the time and failures are independent, end-to-end success is 0.9510 = 60 percent. At 90 percent per stage you get 35 percent. At 85 percent you get 20 percent. Nothing in that calculation is about the model. It is about how many chances you give it to be wrong. Independence is a simplifying assumption, and a generous one: in practice a shaky stage three hands stage four a worse starting state than the demonstrations ever showed it.
Why the horizon hurts more than linearly
Imitation learning has a known theoretical problem here. Ross, Gordon and Bagnell (arXiv 1011.0686, the DAgger paper) show that a policy trained to imitate an expert under the expert's own state distribution carries a cost bound of J(pi) <= J(pi*) + T^2 * epsilon, where T is the horizon and epsilon is the per-state loss against the expert. The paper says in as many words that this behaves as Theta(T^2 * epsilon) for small epsilon, notes that the bound is tight, and constructs a case in which the extra cost really is quadratic.
The mechanism is distribution shift. A small action error moves the arm to a state slightly off the demonstrated manifold. The next observation is therefore slightly out of distribution, so the next action is a bit worse, and so on. The ACT paper names this the compounding error problem and adds that fine manipulation makes it worse, because small differences in the predicted action can incur large differences in the state when tolerances are tight.
People plan data collection as if it were. They record 50 demonstrations of the whole ten-step sequence, the same number that worked for pick and place, and expect the same result. What dropped is per-stage coverage: each individual stage now has 50 examples of itself in exactly one preceding context. That is far less coverage of stage seven than a dedicated stage-seven dataset would give you, and stage seven is the one being reached from the widest spread of states.
Action chunking buys a constant factor
Action chunking is the standard mitigation, and it is real. Instead of modelling pi(a_t | s_t), the policy models pi(a_t..t+k | s_t) and executes k actions per observation. The ACT paper states the effect plainly: this reduces the effective horizon of the task by k-fold. Every model you can train on this platform predicts chunks rather than single steps.
| Policy | Latency per action step | Chunk-related setting | Where that comes from |
|---|---|---|---|
| ACT | 20 ms | chunkSize 100, nActionSteps 100 | AY-Robots trainer form defaults |
| GR00T N1.7 | 152 ms | no chunk knob in the training form; NVIDIA's own LIBERO rollout runs the client with --n-action-steps 8 | AY-Robots trainer form, Isaac-GR00T LIBERO example |
| GR00T N1.5 | 165 ms | no chunk knob in the training form | AY-Robots trainer form |
| SmolVLA | 245 ms | actions_per_chunk is a required flag with no default; every lerobot async example passes 50 | lerobot async inference docs |
| Pi0.5 | 485 ms | chunk_size 50, n_action_steps 50 | lerobot configuration_pi05.py, main branch |
Do the arithmetic on your own task. LeRobot records at 30 fps by default, and its own docs call a 30 fps dataset the default when explaining how to scale frame-based settings. A 60 second sequence is therefore 1800 frames. With ACT at nActionSteps 100 that is 18 decision points. With Pi0.5 at n_action_steps 50 it is 36. Compare that with a 10 second pick and place, which is 300 frames and three to six decision points. Chunking took your horizon from 1800 to 18. It did not take it to 3. That arithmetic is mine, from published defaults, not a platform capability.

Benchmarks agree: long suites score lowest
The LIBERO benchmark (Liu, Zhu, Gao and colleagues, arXiv 2306.03310) is useful here because it isolates the variable. It defines four task suites, 130 tasks in total, and splits its LIBERO-100 set into 90 short-horizon tasks (LIBERO-90) and 10 long-horizon ones (LIBERO-LONG, which NVIDIA labels LIBERO-10). Same simulator, same robot, same demonstration pipeline. Between the short suites and the long one, mainly the horizon changes.
| LIBERO suite | GR00T N1.7 success, as published | What the suite varies |
|---|---|---|
| Object | 197/200 | object generalisation |
| Spatial | 195/200 | spatial arrangement |
| Goal | 195/200 | goal specification |
| 10 (Long) | 189/200 | multi-step horizon |
Those are NVIDIA's own numbers from the Isaac-GR00T LIBERO example, and all four suites were finetuned with the same recipe: 20000 max steps, global batch size 640, gradient accumulation 1, state dropout probability 0.2, on eight GPUs. The long suite comes last by a consistent margin with everything else held fixed. One caveat worth carrying: the README's percentage column does not match its own fractions exactly, so the fractions above are what to quote. And note the size of the gap. Eleven failures out of 200 in simulation with dense demonstrations is nothing like the ACT table above, where a four-stage real-hardware task with 50 episodes lost a third of its runs.

Route one: decompose the task
The first way out is to stop asking one network to hold the whole plan. Split the problem: a high-level component decides what the next subtask is, and a low-level vision-language-action model executes that one subtask. The high-level output is a short language string, which is exactly what a language-conditioned policy already accepts.
What the published results say
| System | Hierarchy | Reported result | The comparison that matters |
|---|---|---|---|
| SayCan (arXiv 2204.01691) | LLM proposes skills, value functions score affordance | 101 tasks in the training kitchen: 84 percent planning, 74 percent execution | its own long-horizon family, 15 tasks, drops to 73 percent planning and 47 percent execution |
| Hi Robot (arXiv 2502.19417) | a VLM breaks the prompt into subtasks, Pi0 executes them | 76 percent average instruction accuracy | flat VLA 36, zero-shot GPT-4o high level 30, expert human oracle 100 |
| Pi0.5 (arXiv 2504.16054) | one network does high-level and low-level | the full model beat every ablation, including the expert-human oracle high-level policy | the no-HL ablation is significantly worse; zero-shot GPT-4 as planner is worst of all |
| MEM (arXiv 2603.03596) | high-level policy keeps a compressed language summary of what happened | solves tasks that require up to fifteen minutes of memory | naive concatenation of past subtask strings works significantly worse than the learned summary |
Two details in that table are worth more than the headline percentages. First, SayCan's long-horizon family drops to 47 percent execution while its overall average is 74. A planner does not make long tasks as easy as short ones; it makes them possible at all. Second, read Hi Robot's GPT-4o column carefully rather than as a punchline. On instruction accuracy the zero-shot GPT-4o planner scored 30 against the flat VLA's 36, so by that measure an unadapted general model was worse than no hierarchy. On task progress the same GPT-4o scored 64 against the flat baseline's 44. It was not useless, it was badly aligned with what the user actually asked for, and Hi Robot's authors had already constrained it to choose among the most common skill labels. Pi0.5's ablations put a zero-shot GPT-4 planner last of every variant they tried.
How Pi0.5 does it in one model
The Pi0.5 paper factorises the policy as pi(a, l_hat | o, l) = pi(a | o, l_hat) * pi(l_hat | o, l). The overall prompt l is something like "put away the dishes". The model first samples a subtask string l_hat such as "pick up the plate", then predicts the action chunk conditioned on l_hat. Note what is missing, and the paper says it explicitly: the action distribution does not depend on l at all, only on l_hat. The low-level half never sees the overall goal. Its whole world is one short instruction and the current image, which is why it transfers between tasks.
The action expert predicts a chunk of H = 49 actions, and the paper describes commanding arm actions and base velocities at 50 Hz, so roughly one second of motion per call. Pi0.5 was trained on about 400 hours of mobile manipulation data plus web data, cross-embodiment data and explicit subtask-prediction data. Its scaling study varied that mobile manipulation data over 3, 12, 22, 53, 82 and 104 distinct locations and reports performance improving steadily as locations are added; at 104 locations the model matched a control trained directly on the test homes it was then evaluated in. The paper does not report a plateau, so do not plan around one.
This is the trap that costs a day. The lerobot pi05 policy exposes select_action and predict_action_chunk, and nothing that samples a subtask string. There is no high-level inference in the port. The same applies to the MEM memory work: lerobot implements MEM's short-horizon video and proprioceptive memory (--policy.use_visual_memory=true, --policy.memory_frames=6, --policy.memory_stride=30), and the doc page for that feature states that MEM's long-horizon language memory, the part where a high-level policy predicts the next subtask and a running summary, is not implemented. If you train Pi0.5 here, you get pi(a | o, l_hat). You have to supply l_hat yourself. Note also that this section lives in the lerobot main branch docs and has not yet reached the published documentation build, so check the repo rather than the rendered page.
Building the decomposition yourself
The good news is that the pieces are all real CLI commands today. The plan is: record one dataset per subtask, relabel and merge them into a single multi-task LeRobot dataset, fine-tune a language-conditioned policy on the merged set, then drive it from your own loop that swaps the instruction string between stages. Commands below are from the lerobot main branch as read on 24 August 2026.
- 1Record each subtask as its own dataset
Do not record ten-step sequences yet. Record stage 1 fifty times, stage 2 fifty times, and so on, each with its own instruction string. Fifty is the platform minimum for Pi0.5, GR00T and ACT; SmolVLA's floor is 30. Start each recording from the realistic state that the previous stage leaves behind, including the messy ones. See record your first dataset for the setup.
bashlerobot-record \ --robot.type=so100_follower \ --robot.port=/dev/tty.usbmodem58760431541 \ --robot.id=black \ --robot.cameras="{laptop: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30}}" \ --teleop.type=so100_leader \ --teleop.port=/dev/tty.usbmodem58760431551 \ --teleop.id=blue \ --dataset.repo_id=$HF_USER/kitchen_s1_open_drawer \ --dataset.num_episodes=50 \ --dataset.single_task="open the drawer" \ --dataset.streaming_encoding=true - 2Fix any labels you got wrong
--dataset.single_taskwrites one string for the whole dataset, so if you recorded mixed stages in one session you have to relabel per episode afterwards. The script's own help marks this operation as modifying the dataset in place, so copy it first.bashlerobot-edit-dataset \ --repo_id $HF_USER/kitchen_mixed \ --operation.type modify_tasks \ --operation.episode_tasks '{"0": "open the drawer", "1": "pick up the cup", "2": "open the drawer"}' - 3Merge the per-subtask datasets into one
One policy, many instructions. The merge keeps each episode's task string, so the result is a multi-task dataset where the language is the only thing distinguishing a stage-1 episode from a stage-7 episode.
bashlerobot-edit-dataset \ --new_repo_id $HF_USER/kitchen_subtasks \ --operation.type merge \ --operation.repo_ids "['$HF_USER/kitchen_s1_open_drawer', '$HF_USER/kitchen_s2_pick_cup', '$HF_USER/kitchen_s3_close_drawer']" - 4Fine-tune a language-conditioned policy
ACT will not work for this step, see the warning below. Use Pi0.5, SmolVLA or GR00T. The command below follows the lerobot Pi0.5 training example, sized for a single 80 GB card; lerobot's default seed is 1000, while GR00T's tyro-based finetune entry point exposes no seed at all.
bashlerobot-train \ --dataset.repo_id=$HF_USER/kitchen_subtasks \ --policy.type=pi05 \ --policy.pretrained_path=lerobot/pi05_base \ --policy.gradient_checkpointing=true \ --policy.dtype=bfloat16 \ --policy.device=cuda \ --policy.push_to_hub=false \ --output_dir=./outputs/kitchen_subtasks \ --job_name=kitchen_subtasks \ --batch_size=64 \ --steps=30000 \ --save_freq=5000 \ --seed=1000 - 5Serve it, then drive the instruction from your own loop
The async client attaches the task string to every observation it sends, so you can change it mid-run. The CLI below runs one stage; the next section replaces it with a planner. Note that the docs mark
--taskas not necessarily defined for all policies, such as act.bash# terminal 1: policy server python -m lerobot.async_inference.policy_server \ --host=127.0.0.1 \ --port=8080 # terminal 2: robot client, one stage at a time python -m lerobot.async_inference.robot_client \ --server_address=127.0.0.1:8080 \ --robot.type=so100_follower \ --robot.port=/dev/tty.usbmodem585A0076841 \ --robot.id=follower_so100 \ --robot.cameras="{laptop: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30}}" \ --task="open the drawer" \ --policy_type=pi05 \ --pretrained_name_or_path=$HF_USER/kitchen_subtasks \ --policy_device=cuda \ --actions_per_chunk=50 \ --chunk_size_threshold=0.5

For a real planner you drive the client from Python rather than the CLI, because the CLI takes one fixed --task string for the whole run. The hook you want is control_loop_observation(task), which writes the task string into the observation it ships. The trap is that control_loop(task) is not that hook: in robot_client.py it runs while self.running and only returns after stop(), so calling it once per stage leaves your planner stuck on the first stage forever. The planner has to own the loop instead, and it has to release the start barrier that the action-receiver thread is waiting on.
import threading
import time
from lerobot.async_inference.robot_client import RobotClient
SUBTASKS = [
"open the drawer",
"pick up the cup",
"place the cup on the tray",
"close the drawer",
]
STAGE_TIMEOUT_S = 45.0
client = RobotClient(client_cfg)
if not client.start():
raise SystemExit("handshake with the policy server failed")
receiver = threading.Thread(target=client.receive_actions, daemon=True)
receiver.start()
# Both threads wait on the same barrier; control_loop() would do this for us,
# but it never returns, so the planner does it and runs the loop itself.
client.start_barrier.wait()
try:
for subtask in SUBTASKS:
deadline = time.perf_counter() + STAGE_TIMEOUT_S
while client.running and not done_with_stage(subtask):
t0 = time.perf_counter()
if client.actions_available():
client.control_loop_action()
if client._ready_to_send_observation():
# the subtask string rides along with this observation
client.control_loop_observation(subtask)
time.sleep(max(0.0, client.config.environment_dt - (time.perf_counter() - t0)))
if time.perf_counter() > deadline:
stop_and_ask_for_help(subtask)
raise SystemExit(f"stage timed out: {subtask}")
finally:
client.stop()
receiver.join()ACT is not language-conditioned. The lerobot async guide annotates the task flag as not necessarily defined for all policies, such as act. If you want subtask decomposition with ACT you need one trained ACT checkpoint per subtask and you switch checkpoints, not prompts. That is ten trainings instead of one, ten sets of normalisation statistics to keep straight, and a checkpoint swap in the middle of a motion. It is a defensible choice for a four-stage industrial task where 20 ms per action step is the binding constraint; it is a bad choice for anything open-ended. See ACT compared with GR00T N1.7 for the trade.
For GR00T N1.7 the equivalent runtime hook is the observation dictionary. The Isaac-GR00T policy guide shows the language field as {"language": {"task": [["pick up the cube"]]}}, a list of lists of strings passed to a policy server started with run_gr00t_server.py. Different repo, same pattern as lerobot: the subtask is data you send at inference time, not something baked into the checkpoint. That is what makes a planner possible at all, and it is worth checking on any model before you design around decomposition.
Route two: longer demonstrations and memory
The other way out is to keep the flat policy and give it what it is missing, which is more demonstrations of the full sequence and some way to remember what it already did. This is the direction the frontier labs have taken most recently, and the honest summary is that it works and that it is expensive.
MEM (Torne, Pertsch, Walke and colleagues, arXiv 2603.03596, March 2026) is the clearest recent statement of it. It equips a VLA, in the paper's case a Pi0.6-class model, with two memories: a short-horizon video memory compressed by a dedicated video encoder, and a long-horizon language memory in which a high-level policy keeps a running natural-language summary of what has already happened. The paper reports policies solving tasks that require up to fifteen minutes of memory, such as cleaning a kitchen or working through a recipe, and reports gains even on short tasks: plus 11 percent on picking up a chopstick, plus 62 percent on opening a fridge.
Naively concatenating every past subtask string into the prompt works worse than a learned summary. The reason is a train-inference distribution shift: human demonstrations are near-optimal, so each subtask appears exactly once, but a real policy fails and retries, producing histories like "pick up bowl, pick up bowl, pick up bowl, place bowl in cabinet" that never occur in training. MEM's memory simply does not update until the stage actually succeeds, which discards the failed attempts. If you are tempted to build your planner by appending strings to a prompt, this is the failure you will hit, and you will hit it exactly when the robot is already struggling.
- No planner to write, no stage-boundary detector to tune, no extra moving part at runtime.
- The policy learns real stage transitions, including the recovery behaviours a human operator performs without thinking.
- Pi0.5's ablations found that its implicit-HL variant, which does no high-level inference at runtime but keeps subtask-prediction data in the training mixture, was the second best model of all those tested.
- Works with any policy, including ones that ignore language such as ACT.
- Data cost scales with the horizon. A ten-stage sequence takes roughly ten times as long per episode to teleoperate as one stage.
- Per-stage coverage stays thin. 50 full-sequence episodes give stage 7 only 50 examples, all reached through one particular history.
- Operator fatigue shows up in the data. Long recording sessions produce the pauses and hesitations that later read as a stalled policy.
- MEM's headline results depend on pretraining the video encoder on a diverse mixture of robot and non-robot video, which lerobot's docs say no public Pi0.5 checkpoint currently provides; enabling memory only at finetuning time corresponds to the paper's weaker MEM-Posttrain-Only ablation.
There is also a latency cost that is easy to overlook. MEM's own inference-time figure draws a 300 ms real-time barrier and shows that naively feeding a sequence of past frames into a VLA backbone crosses it as the frame count rises; the paper's whole video-encoder design exists to avoid that. On this platform Pi0.5 already sits at 485 ms per action step before you add anything, which is why the inference latency column deserves a look before you commit to memory as a strategy.
Which route for which task
| Your situation | Route | Why |
|---|---|---|
| Two or three stages, fixed order, fixed scene | Longer demonstrations | The horizon is short enough that chunking already covers it. A planner is overhead. |
| Six or more stages, fixed order | Decompose | Per-stage data collection is cheaper and each stage gets real coverage. |
| Stage order varies with what the operator finds | Decompose | A flat policy has to learn branch selection from the same 50 episodes that teach the motions. |
| Stages are short but need memory of earlier ones | Longer demonstrations plus memory | A stateless planner cannot tell the policy which drawer it already checked. |
| You are locked to ACT for latency reasons | One checkpoint per stage | ACT does not read the instruction, so language switching does nothing. |
| You have fewer than 50 episodes total | Neither yet | Both routes assume a policy that reliably does one stage. Fix that first. |
The minimum episode counts on the policies page are 50 for GR00T N1.7, GR00T N1.5, Pi0.5 and ACT, and 30 for SmolVLA. Those floors describe one task. A merged multi-subtask dataset only helps if each subtask clears the floor on its own, so decomposing a ten-stage job into six subtasks means six times the floor before the merged set is worth a training run. That is the real cost of route one, and it is paid in teleoperation hours, not GPU hours.

The same job, two ways
- Build or buy an SO-100, calibrate it, wire the cameras.
- Record one dataset per subtask with
lerobot-recordand a distinct--dataset.single_taskstring each time. - Relabel with
lerobot-edit-dataset --operation.type modify_tasks, merge with--operation.type merge. - Rent a GPU yourself, install the trainer, work through the CUDA and dependency problems, run
lerobot-train. - Stand up
lerobot.async_inference.policy_serversomewhere with a GPU and keep it alive. - Write the planner loop and the stage-done detector, which is the part nobody else can write for you.
- Remember to destroy the GPU instance.
Full control of the data schema, the chunk size, the normalisation statistics and the planner. If your task needs a custom stage detector reading force or a fixture sensor, you were always going to end up here.
- Record with the desktop client, which writes LeRobot-format datasets straight from a teleop session.
- Pick model, dataset and hyperparameters in the training form. The backend rents a GPU on the spot market by required VRAM and writes checkpoints to object storage.
- Serve the result:
/api/inference/podauto-provisions a pod, and the local robot client talks to that endpoint. Pods carry an idle watchdog and destroy themselves, so nothing bills silently. - Drive it from the CLI or from an agent through MCP, which expose the same operations.
- Still write the planner loop yourself.
There is no planner here. No high-level subtask model, no memory module, no stage-boundary detector. AY-Robots trains and serves pi(a | o, l_hat); choosing l_hat is your code. The platform removes the GPU provisioning, the trainer setup and the serving, which is most of the annoyance but none of the hard design work.
| Tier | Models | Run time | Cost per run |
|---|---|---|---|
| A100 80 GB / H100 | GR00T N1.7, GR00T N1.5, Pi0.5 | 3 to 6 hours | about 4 to 12 USD |
| RTX 4090 / 24 GB | SmolVLA, ACT | 2 to 5 hours | about 1 to 3 USD |
The cost column is why route one is less frightening than it sounds. Six subtask policies is one merged dataset and one run, not six runs, as long as the policy reads language. Six ACT checkpoints really is six runs, which at the 4090 tier is roughly 6 to 18 USD. Neither number is the bottleneck. The teleoperation time is, and no amount of GPU budget shortens it.
Honest limits
Decomposition moves the failure rather than removing it. Pi0.5's own discussion section lists the case where high-level subtask inference is easily distracted and, for example, closes and opens a drawer repeatedly while putting items away. SayCan's error analysis found 65 percent of failures were LLM failures and 35 percent were affordance failures, that is, the value function misjudging whether a skill could succeed rather than the manipulation policy fumbling it. If your planner is wrong, a perfect low-level policy executes the wrong stage flawlessly.
The second limit is inference latency. The control loop on this platform runs at 20 to 485 ms per action step depending on the model, and adding public-internet round trips to that turns a working policy into a hesitant one. Remote inference is viable for slow pick and place and for the deliberate pace of most multi-stage household tasks. It is not viable for fast reactive motion. A ten-stage task that is slow throughout is a reasonable candidate for remote inference; a ten-stage task with one fast catching motion in the middle is not.
First: lerobot's Pi0.5 config sets tokenizer_max_length = 200. Stuffing an entire plan into the instruction string silently truncates it. Keep subtask strings short, the way the training labels were. Second: a LeRobot v3.0 dataset crashes the GR00T loader and has to be converted down to v2.1. Merging datasets is exactly the moment when you discover half of them are the wrong version. See dataset rejected as v3 and the rest of the dataset documentation.
The third limit is diagnostic. A policy that stalls at stage four looks identical to a policy that has hit a hardware limit or a camera problem. Before you conclude that your horizon is too long, rule out the cheap explanations on the failure-mode pages, in particular policy freezes mid-motion and policy only works in one setup. Horizon problems degrade gradually across stages and vary run to run; hardware problems stop dead in the same place every time.

What to do this week
- Write down your stages and score each one separately from your existing rollouts. If you cannot score them separately, you cannot debug them separately.
- Multiply the per-stage rates. If the product matches your observed end-to-end rate, you have a horizon problem and not a capability problem.
- Find the worst stage. Often one stage carries the whole loss, as in ACT's Thread Velcro dropping from 92 to 40 between stage one and stage two. Record 30 more episodes of that stage alone before touching anything else.
- Only then decide between routes, using the table above.
- Check the public dataset directory for a dataset with a similar stage structure before recording your own; the data collection guide covers what makes an episode reusable, and the VLA overview covers why language conditioning is the hinge this whole article turns on.
If you have no arm yet, the /live page streams a physical SO-100 you can drive with no signup, and train your first policy walks the single-stage version of everything above. There is also the flow-matching background on the Pi line of models if the pi05 architecture above went past too quickly. Get one stage to 95 percent before you plan ten of them.
Which of the five policies actually reads your instruction?
Four of them do and one does not, and that single fact decides whether subtask decomposition is one training run or ten. The comparison table has parameters, GPU tier, latency per action step and minimum episodes for GR00T N1.7, GR00T N1.5, Pi0.5, SmolVLA and ACT.
Compare the five policiesHow many stages is too many for a single flat policy?▾
There is no hard number, but the pattern in the published per-stage tables is that degradation becomes obvious somewhere around three to four stages on real hardware with 50 demonstrations. ACT's Prep Tape goes 96, 92, 72, 64 percent over four stages. Simulation with dense data holds up much longer: GR00T N1.7 scores 189 of 200 on LIBERO's long suite against 197 of 200 on the object suite. If you are on a low-cost arm with 50 episodes, treat four stages as the point where you start scoring stages separately.
Can I use ACT with subtask decomposition?▾
Not through language. ACT has no text encoder, and lerobot's async guide annotates the task flag as not necessarily defined for all policies, such as act. You can still decompose by training one ACT checkpoint per subtask and switching checkpoints between stages. That is a legitimate design for a fixed-order industrial sequence, but it means one training run per stage and one set of normalisation statistics per stage to keep straight.
Does the Pi0.5 I train on AY-Robots do high-level subtask inference?▾
No. The open lerobot pi05 implementation exposes select_action and predict_action_chunk and has no code path that samples a subtask string. You get the low-level half of the hierarchy, pi(a | o, l_hat). The subtask string has to come from your own planner, which you send with each observation. This is a property of the open port, not of the platform.
Should I use an LLM as my planner?▾
Only if it has seen robot data or you constrain its output tightly. Hi Robot measured zero-shot GPT-4o at 30 percent average instruction accuracy against 76 for its trained high-level policy and 36 for a flat VLA, even though the authors restricted GPT-4o to choosing among the most common skill labels. Its task progress was better than the flat baseline, 64 against 44, so the failure is alignment with the user's actual request rather than total incompetence. Pi0.5's ablations ranked a zero-shot GPT-4 planner last of every variant they tested. Constraining the model to pick from a fixed list of your recorded subtask strings is much safer than free-form generation.
Is more data always the answer to a long-horizon failure?▾
It is often the answer, but the cheapest version is targeted. Score your stages, find the one carrying the loss, and record more of that stage in isolation rather than more full sequences. Fifty extra full-sequence episodes buy fifty extra examples of the weak stage, all reached through the same history; fifty extra episodes of the weak stage alone buy fifty examples reached from a variety of starting states, which is what the policy is missing.
What does a subtask-decomposed training run cost here?▾
The same as any other run, because it is one run on one merged dataset. Pi0.5 and both GR00T variants sit on the A100 80 GB or H100 tier at roughly 4 to 12 USD per run; SmolVLA and ACT run on a 24 GB card at roughly 1 to 3 USD. The expensive part of decomposition is the teleoperation time to reach the minimum episode count for every subtask, not the GPU.
Sources
- Learning Fine-Grained Bimanual Manipulation with Low-Cost Hardware (ACT / ALOHA): per-stage success tables and the effective-horizon argument
- A Reduction of Imitation Learning and Structured Prediction to No-Regret Online Learning (Ross, Gordon, Bagnell): the T^2 epsilon bound
- LIBERO: Benchmarking Knowledge Transfer for Lifelong Robot Learning: four suites, 130 tasks, the LIBERO-90 / LIBERO-LONG split
- Isaac-GR00T LIBERO example: per-suite success rates and the shared finetuning recipe
- Isaac-GR00T policy API: the observation dictionary including the language task field
- pi0.5: a Vision-Language-Action Model with Open-World Generalization: the high-level / low-level factorisation and the training-recipe ablations
- Hi Robot: Open-Ended Instruction Following with Hierarchical Vision-Language-Action Models
- Physical Intelligence: Hi Robot research page, with the numeric instruction-accuracy and task-progress averages
- Do As I Can, Not As I Say: Grounding Language in Robotic Affordances (SayCan): per-family success rates and the failure attribution
- MEM: Multi-Scale Embodied Memory for Vision Language Action Models
- lerobot docs source, Pi0.5 policy: training recipe and the MEM short-horizon memory options, including what is not implemented
- lerobot docs source, asynchronous inference: PolicyServer, RobotClient, actions_per_chunk and the task flag note about act
- lerobot configuration_pi05.py: chunk_size 50, n_action_steps 50, tokenizer_max_length 200 and the memory defaults
- lerobot robot_client.py: control_loop, control_loop_observation and the start barrier
- lerobot-edit-dataset: the modify_tasks and merge operations, with the in-place warning
Sources
- Learning Fine-Grained Bimanual Manipulation with Low-Cost Hardware (ACT / ALOHA): per-stage success tables and the effective-horizon argument
- A Reduction of Imitation Learning and Structured Prediction to No-Regret Online Learning (Ross, Gordon, Bagnell): the T^2 epsilon bound
- LIBERO: Benchmarking Knowledge Transfer for Lifelong Robot Learning: four suites, 130 tasks, the LIBERO-90 / LIBERO-LONG split
- Isaac-GR00T LIBERO example: per-suite success rates and the shared finetuning recipe
- Isaac-GR00T policy API: the observation dictionary including the language task field
- pi0.5: a Vision-Language-Action Model with Open-World Generalization: the high-level / low-level factorisation and the training-recipe ablations
- Hi Robot: Open-Ended Instruction Following with Hierarchical Vision-Language-Action Models
- Physical Intelligence: Hi Robot research page, with the numeric instruction-accuracy and task-progress averages
- Do As I Can, Not As I Say: Grounding Language in Robotic Affordances (SayCan): per-family success rates and the failure attribution
- MEM: Multi-Scale Embodied Memory for Vision Language Action Models
- lerobot docs source, Pi0.5 policy: training recipe and the MEM short-horizon memory options, including what is not implemented
- lerobot docs source, asynchronous inference: PolicyServer, RobotClient, actions_per_chunk and the task flag note about act
- lerobot configuration_pi05.py: chunk_size 50, n_action_steps 50, tokenizer_max_length 200 and the memory defaults
- lerobot robot_client.py: control_loop, control_loop_observation and the start barrier
- lerobot-edit-dataset: the modify_tasks and merge operations, with the in-place warning
Ready for high-quality robotics data?
AY-Robots connects your robots to skilled operators worldwide.
Get Started