- Trainer key
- act
- GPU tier
- RTX 4090 or any card with 24 GB
- Inference
- about 20 ms per action step
- Batch size
- 8, gradient accumulation 1
- Learning rate
- 1e-5
- Steps
- 100,000
- Dataset format
- LeRobot v2.1
- Typical run
- 2 to 5 hours, about 1 to 3 USD
- Servos
- Dynamixel XL330 and XL430
- Servo voltage
- 5 V and 12 V rails depending on the servo
A Koch v1.1 trains ACT through the same pipeline as the Feetech arms: record 50 or more consistent LeRobot v2.1 episodes, then run ACT at batch 8, learning rate 1e-5, 100 000 steps and chunk size 100 for about 1 to 3 USD. The Koch-specific work is on the hardware side, where the Dynamixel bus and its 5 V and 12 V rails behave nothing like an SO-100, and where your recording frame rate decides how many seconds of motion a chunk covers.
What compatible support means in practice
The Koch v1.1 is listed as compatible rather than fully supported, and the distinction is worth taking literally. The reference arm of this platform is the SO-100, everything is tested there first, and the Koch works because the pipeline downstream of the driver does not care which bus produced the numbers. Recording, upload, the LeRobot v2.1 layout, the act trainer, the defaults and the deployment path are all shared.
What you should expect to verify yourself is the layer where the hardware is actually touched: port detection, servo IDs on the bus, calibration ranges and whether every joint answers. When something goes wrong on a Koch, the prior probability sits with that layer rather than with the trainer. Confirm all six actuators respond before you record fifty episodes, not after.
The Koch v1.1 uses Dynamixel XL330 and XL430 servos, which run on 5 V and 12 V rails depending on the servo. The Feetech STS3215 arms on this platform run at 7.4 V. Do not reuse a supply between the two families in either direction, and do not assume a 12 V brick from the Koch build is safe anywhere near an SO-100 bus, where it destroys the servos in seconds. Label the supplies at the plug.
Why the bus never reaches the model
ACT sees joint positions and camera frames, normalized against the statistics stored with the dataset. It has no notion of Dynamixel or Feetech, no notion of servo protocol, and no notion of what a raw encoder count means. This is why a Koch dataset trains without any special handling: by the time the trainer reads it, the bus has been abstracted away into a table of numbers and a set of video files.
The corollary matters more than the fact. Because the numbers were normalized per dataset, they are not comparable across arm families. A joint value recorded on a Koch means nothing on an SO-100 and vice versa. Merging Koch and Feetech episodes into one ACT dataset produces contradictory supervision, and ACT, having no pretraining to fall back on, has no way to notice that the two halves come from different robots. One arm family per dataset, without exceptions.
Frame rate decides how long a chunk lasts
ACT predicts a chunk of future actions in one pass and executes some of them before predicting again. That is what suppresses compounding error: fewer prediction points across an episode means fewer chances for a small deviation to push the arm into a state no demonstration ever covered, and actions drawn from one plan agree with one another instead of correcting each other every frame. The chunk, though, is counted in timesteps and not in seconds, so the wall-clock length of a chunk is set by the rate you recorded at.
This is worth spelling out on a Koch specifically, because a Dynamixel setup that has not been tuned sometimes records at a lower and less steady rate than a Feetech arm on the same machine. The consequence is not a training failure, it is a policy that stays open loop for noticeably longer than you intended.
| Recording rate | nActionSteps | Open-loop time per prediction |
|---|---|---|
| 30 fps | 100 (default) | About 3.3 seconds |
| 30 fps | 25 | About 0.8 seconds |
| 20 fps | 100 (default) | About 5 seconds, which is a long time to be blind |
| 20 fps | 25 | About 1.25 seconds |
Two conclusions. Record at a steady rate and know what it is, because it changes the meaning of every chunk setting on this page. And if your Koch records below 30 fps, treat nActionSteps 100 as an aggressive setting rather than a neutral default, and start at 25 to 30 instead.
Prerequisites
- A Koch v1.1 with all six actuators responding on the Dynamixel bus, and the correct rail for each servo
- The desktop client installed and paired, so the driver and the recording path are in place
- Calibration completed on this specific arm, since Dynamixel zero points are per unit like any other servo
- A fixed scene camera, ideally plus a wrist camera
- 50 or more reviewed episodes of one task, recorded at a rate you have actually checked
ay-robots --version
# Every actuator must answer before you record anything. A joint that drops
# out mid-session poisons the episodes recorded around it.
ay-robots devices
# Per-unit calibration, exactly as on the Feetech arms
ay-robots calibrateRecording for a from-scratch model
ACT builds its entire understanding of the task out of your episodes, so consistency beats volume by a wide margin here. It is also the part where a careful operator gains the most, and where the gain is easiest to throw away by recording two hundred episodes across three sessions with three slightly different techniques.
- One task per dataset. ACT never reads the task string, so a second task inside the same dataset is just a set of contradictory demonstrations.
- One approach, one grasp height, one order of operations, held for the whole dataset.
- Object placement varies, technique does not. Placement is what generalizes; technique variation is what averages.
- Review and discard failures, including the near-misses you would call good enough.
- Keep sessions short. Demonstration quality falls off when you are bored, and ACT copies exactly what you show it, tiredness included.
- Check the recorded rate on the first session rather than assuming it matches your camera settings.
Starting the run
- 1Upload and inspect
Upload the dataset, wait for processing to finish, then open the preview and step through an episode. Confirm the action dimensions match the six actuators you expect and that both camera streams are present.
- 2Open Training and choose the dataset
If your account also holds SO-100 data, check the robot type on the card. A Koch dataset and an SO-100 dataset look alike in a list and train into very different policies.
- 3Pick ACT
The form switches to the lerobot parameter set and adds the two chunk fields that only ACT exposes.
- 4Set nActionSteps to match your recording rate
Leave it at 100 if you recorded a steady 30 fps. If you recorded slower, drop it to 25 or 30 so a single prediction does not carry five seconds of blind motion.
- 5Fill in a seed, leave everything else
Batch 8, learning rate 1e-5, 100 000 steps, gradient accumulation 1, chunk size 100. The seed is what makes your second run a comparison rather than a new experiment.
- 6Start it and check the first minutes
The pool rents a 24 GB card by VRAM, not by GPU name, so the exact hardware differs per run. Watch that the loss actually starts falling before you walk away.
# The same run over the hosted MCP server, protocol version 2025-06-18.
# start_training refuses to do anything without confirm_spend, because it
# rents a GPU and bills the account.
curl -X POST https://www.ay-robots.com/api/mcp \
-H "Authorization: Bearer $AY_ROBOTS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "start_training",
"arguments": {
"dataset_id": "ds_4b18aa",
"policy_name": "koch-block-pick-act",
"model_id": "act",
"max_steps": 100000,
"confirm_spend": true
}
}
}'Defaults and when to move them
| Setting | Default | Change this when |
|---|---|---|
| Batch size | 8 | Keep it. The 24 GB tier holds batch 8 with two camera streams; drop to 4 only in response to a real out-of-memory error, never preemptively. |
| Learning rate | 1e-5 | Keep it. Training from random initialization is less forgiving of a high rate than fine-tuning is, and a diverged run wastes the whole schedule. |
| Steps | 100 000 | Halve it while you are still shaking out the Dynamixel side of the setup. A 40 000 step run answers "did the bus record clean data" for roughly half the money. |
| Gradient accumulation | 1 | Only after you reduced batch size and want the effective batch back. ACT is not built around accumulation the way the A100-tier models are. |
| chunkSize | 100 | Lower toward 50 for episodes of only a few seconds, so the far end of the chunk is not predicting past the end of the task. |
| nActionSteps | 100 | Lower to 25 or 30 if you record below 30 fps, or if anything in the scene can move while the arm is executing. Changing it needs no retraining. |
| Seed | optional | Set it on any run you intend to compare. On a compatible-tier arm you will be running comparisons more often than on an SO-100. |
| Log frequency | form default | Tighten it for the first run on a new arm, where the interesting question is whether the loss moves at all in the first few hundred steps. |
Cost and duration
ACT trains on the 24 GB tier, which the pool rents from a spot market by VRAM. Budget 2 to 5 hours for the full 100 000 step schedule on 50 episodes, at 0.30 to 0.60 USD per hour, so roughly 1 to 3 USD for the run. The long step count is what makes ACT look expensive on paper and it is not: the same money buys an hour or two on the A100 tier that GR00T N1.7 and Pi0.5 require, where the rate is 1.20 to 2.00 USD per hour.
On a compatible-tier arm the first real question is whether your recordings are clean, not whether the architecture is optimal. A shortened ACT run costs a couple of dollars and answers that question in an afternoon. Only once the data is proven is it worth putting a 3 billion parameter model on an 80 GB card in front of it.
Deployment and evaluation
Inference runs locally in the client, at about 20 ms per action step. That is far inside the budget of a 30 fps control loop and it means the bottleneck on a Koch is the bus and the servo response, not the model. Set the scene back to the recorded configuration before the first attempt: cameras where they were, the same lighting, the same reset.
- 1Power the arm on the correct rails
Check the supply against the servo before the checkpoint gets anywhere near the hardware. This is the step where an unfamiliar arm costs people servos.
- 2Watch the first chunk with a hand on the switch
A chunked policy commits to seconds of motion at a time. If the opening move is wrong, cut power rather than let it finish the plan.
- 3Twenty attempts with varied placement
Write down every outcome. Twenty attempts is the smallest sample that distinguishes a real 40 percent from a lucky three in a row.
- 4Compare two checkpoints and two nActionSteps values
Four short evaluations on the same twenty positions. Checkpoint choice and replanning frequency are both worth real percentage points and neither costs GPU time.
- 5Target the failure cluster
Record fifteen to twenty new episodes of exactly the situation that fails, then retrain. Targeted data beats more data at every scale.
Troubleshooting
| Symptom | Likely cause | What to do |
|---|---|---|
| A joint stops responding partway through a recording session | Bus or connector, and it is a Dynamixel-side problem rather than a platform one | Discard every episode from that session. They contain a frozen joint and ACT will faithfully learn to freeze it |
| The policy overshoots the object and continues | The chunk was planned before the arm arrived, and nothing in it can react to arriving early | Lower nActionSteps, and check the recording rate: at 20 fps the default chunk holds about five seconds of motion |
| Regular twitch at a fixed interval during motion | Chunk boundaries. Each new prediction starts from a slightly different plan | Raise nActionSteps for fewer joins, or fix the cause: joins are worst where the dataset holds two techniques for one moment |
| The policy only succeeds from the exact pose it was recorded from | From-scratch training with a single start pose in every episode leaves everything else out of distribution | Vary the start pose slightly in future sessions and add episodes from the poses that currently fail |
| Excellent loss curve, no successes on the arm | The model averaged incompatible demonstrations into one trajectory that satisfies neither | Review your episodes rather than the hyperparameters. On ACT this symptom is almost always the dataset |
| Motion is jerky in a way the demonstrations were not | The recorded rate was unsteady, so the timing the policy learned does not match the timing it plays back | Fix the recording rate first, then re-record. Smoothing the output afterward hides the problem rather than solving it |
When to choose something other than ACT
ACT is the right pick on a Koch when the task is fixed, the scene is controlled, and you want the arm to move quickly and continuously. It is the wrong pick when the object can be anywhere, when you want to command the arm in language, or when you need behavior on objects that appear in no demonstration, because nothing in the model was trained before your dataset existed. The full fact sheet is at /policies/act, the head-to-head against the other 24 GB option at /compare/act-vs-smolvla, and the recording method that all of this depends on is at /learn/record-your-first-dataset.
Does the Dynamixel bus need any special configuration for training?▾
No. The bus is handled entirely by the client while recording, and the trainer only ever sees normalized joint values and video. Everything Koch-specific happens before the dataset exists, which is also why the Koch-specific failures all look like hardware failures rather than training failures.
Can I combine Koch episodes with SO-100 episodes to reach more data?▾
No. The values are normalized per dataset and the two arms are mechanically and electrically different, so pooling them gives ACT two conflicting definitions of the same task. Since it has no pretraining to reconcile them with, it will average the two and satisfy neither.
What if my Koch records at 20 fps rather than 30?▾
Training is unaffected, deployment is not. A chunk is counted in timesteps, so 100 executed steps at 20 fps is about five seconds of open-loop motion instead of about 3.3. Lower nActionSteps to 25 or 30 to compensate, which you can do without retraining.
Is 100 000 steps too many for a Koch dataset of 50 episodes?▾
It is the default and it is fine, since the whole run is 1 to 3 USD. The thing to watch on a small dataset is memorization: if loss collapses within a few thousand steps, your episodes are too similar to each other and more steps will not fix that.
Which power supply do I actually use?▾
Whichever the servo requires, XL330 and XL430 sit on different rails, 5 V and 12 V. The only universal rule is that nothing from a Koch build belongs on a Feetech arm: STS3215 servos are 7.4 V parts and 12 V destroys them within seconds.
The full tutorial chain lives under /learn.