SmolVLA: the 450M vision-language-action model for low-cost arms, as a per-call API
SmolVLA is Hugging Face's compact vision-language-action model for affordable robotics. It has about 450 million parameters. It was pretrained only on community-shared SO-100 recordings. It is small enough to run on a CPU or a MacBook. It is also the model most low-cost-arm builders meet first, and the one with the widest gap between what it can do and what anyone serves. This page is the platform's written record for a metered per-call action lane for it: the row sits in the platform's model data with its rate set, it went live on October 26, 2026, and it serves per call, confirmed by that day's requests.
Last verified: 2026-10-05
What it is
SmolVLA takes camera images, the current joint positions of your arm, and a plain-language instruction, and returns an action chunk: a short run of future motion steps. It belongs to the LeRobot family from Hugging Face. The code is Apache-2.0. The weights are a free download. The fine-tuning path is public. One naming trap: SmolVLM is the vision-language model without the action half. SmolVLA moves a robot.
| Fact | Value | Owner of the number |
|---|---|---|
| What it is | a compact VLA policy for low-cost arms | the paper, June 2025 |
| Exact size | 450,046,176 parameters in the public checkpoint | Hugging Face Hub API, read 2026-10-05 |
| License | Apache-2.0, code and weights | the model card |
| Pretraining data | 481 community datasets, 22.9K episodes, 10.6M frames, mostly SO-100 | the paper, Table 1 |
| Simulation score | 87.3 percent average on LIBERO, multi-task | the paper, Table 2 |
| Real-robot score | 78.3 percent average across three SO-100 tasks | the paper, Table 3 |
| Async gain | about 30 percent faster completion, twice the tasks in a fixed window | the paper and the release blog |
| Home hardware | runs on CPU, trains on one consumer GPU, runs on a MacBook | the release blog |
| Architecture | SmolVLM2 (a SigLIP vision encoder plus a SmolLM2 decoder) with a roughly 100M action expert, trained with flow matching | the paper |
A 450M model in two halves
The first half is a vision-language model, SmolVLM2. The second half is an action expert that turns what the first half saw into motion. The expert is trained with flow matching: it pulls noisy placeholder motion back onto a clean trajectory, emitting continuous actions in one pass instead of one token at a time. That is why a 450M model can stay in the loop of a real arm.
Three design choices keep it small, and all three come from the paper:
- Fewer visual tokens. Each camera frame is compressed to 64 tokens, whatever the image size.
- Layer skipping. The action expert reads the vision-language model's features from halfway up, not from the top. This roughly halves the vision compute.
- Interleaved attention. Inside the expert, layers alternate between attending to what the model saw and attending to earlier steps of the chunk. The first keeps actions grounded, the second keeps them smooth.
One consequence matters at fine-tune time: by default only the expert trains. An independent training log, read October 5, 2026, shows 99,880,992 learnable parameters out of 450,046,212 total, matching the expert's size. The vision half arrives frozen. Your recordings teach the motion half.
Trained on community data: the SO-100 story
SmolVLA was not trained on an industrial corpus. Its pretraining set is the 481 public datasets in the table above, mostly SO-100 recordings at 30 frames per second, from labs to living rooms. The team cleaned the text labels with a small vision-language model and mapped every camera to a fixed order: top, wrist, then side. That curation, not scale, is the stated bet, and the paper measures it: on SO-100 tasks, community pretraining lifts success from 51.7 to 78.3 percent.
The community story continued after release. The official checkpoint family now covers LIBERO, Meta-World, and other suites. A 2026 paper adapts the model to a UR10e industrial arm through ROS 2, validated on pick-and-place. A widely discussed Reddit home robot build went further: a fine-tuned SmolVLA as the brain of a wheeled robot that maps a room, finds objects, and picks them up, trained on one 16 GB card on VR-captured recordings.
The arm itself is open hardware. The SO-ARM100 design, the basis of SO-100 and SO-101, is a printed frame around inexpensive servos, kept as a public project. That pairing, an open arm and a small open policy, is the niche SmolVLA owns.
Use cases
- Your first policy on a low-cost arm. Small, well documented, cheap to iterate on. The reference recipe is about 50 recordings across five object positions.
- Teaching and coursework. It runs on hardware a school already owns, and every step from recording to serving is public.
- Language-steered multi-task cells. One checkpoint can hold several tasks and pick between them from the instruction string. Train each task under one fixed sentence.
- Dataset iteration. A run is short, so you test the data instead of guessing about it. If SmolVLA cannot learn the task, more capacity rarely fixes the recordings.
- Mobile and integrated builds. Wheeled bases and custom frames where a 3B-class model would not fit the power budget.
Where it is the wrong tool: millimeter-precise insertion, contact-dominated tasks, brand-new tasks described only at run time, and fast fluid motion where ACT-class latency wins. Its pretraining is SO-100-scale, so unfamiliar scenes are harder. For those cases see pi05 with its DROID and LIBERO tunes, or OpenVLA-OFT.
Asynchronous inference, explained
People type smolvla async inference as its own query. The plain answer, from the paper and the official follow-up post:
A policy like this returns chunks, not single steps. The naive loop executes a chunk, stops, waits for the next one, and repeats. The robot is idle while it waits. Asynchronous inference removes the idle time:
- While the arm still executes the current chunk, the robot client streams fresh camera frames to a policy server.
- The server computes the next chunk in parallel. The client fires this request when its local queue drops below a threshold, 70 percent in the reference setup.
- When the new chunk lands, overlapping steps are merged so motion stays smooth.
The measured effect on SO-100 tasks: the same success rate, tasks finished in 9.7 seconds instead of 13.75, and 19 completed pick-and-place cycles in a fixed window instead of 9. The tradeoff is freshness: the frames behind a new chunk are slightly old by the time it runs. The merging rule keeps the join smooth. The official stack runs the server side on gRPC, a round trip under 100 milliseconds with SmolVLA on one RTX 4090.
This is also the strongest hint about serving. The design already assumes the brain sits somewhere other than the arm. A per-call API is the same shape, with the platform running the server.
What hardware you need
The fragments from the results pages, assembled; each number carries its owner.
| You want to | Hardware | Basis |
|---|---|---|
| Run inference | CPU-class machine; measured peak under 1 GB of GPU memory where a GPU is present | release blog; independent walkthrough, 2025 |
| Run inference on a Mac | Apple Silicon, through a community MLX port | public port repository |
| Fine-tune at home | 12 GB card at batch 44, or a 6 GB laptop GPU at batch 16 | independent walkthrough on a 3080 Ti, 2025 |
| Fine-tune at reference scale | one A100 for about 4 hours at 20,000 steps, or a free cloud notebook | LeRobot docs |
| Run without a GPU | an NPU runtime, or nothing at all if you call a hosted lane | public NPU runtimes; this platform's lane serves per call, on the public list since October 26, 2026 |
Two honest notes. Vendors that rent training hardware quote a 24 GB card for comfort; that is a service choice, not a model requirement. And the runs-on-CPU claim is real but slow: fine for testing, painful for a fast loop. Own the hardware or rent the calls: the VLA local versus API break-even guide works the break-even.
API usage
The lane's contract speaks the platform's action route, POST /v1/action, with a Bearer key from the console. Multipart form data in, JSON out. The model id is smolvla. The tabs below are the contract the lane ships under.
| Form field | Required | Notes |
|---|---|---|
model | yes | smolvla |
instruction | yes | the task sentence, non-empty on every request |
state | yes | a JSON array of numbers: your arm's joint positions. The empty array [] is the legal stateless case |
image | yes, one or more | camera frames as file parts, the outer view plus a wrist view in practice |
One served request returns three things. actions is the action chunk in the model's own shape, the length the model prefers rather than a request parameter. normalization is the statistics block the endpoint applied, untouched. usage is ours: the call count and cost, every answer. Metering is per call: one served request is one billed call, a refused request bills nothing, the prepaid wallet is the spending stop, and the body cap is 25 MiB.
Why call a small model per call at all? Because the arm is idle most of the time. A hobby cell runs seconds of motion per minute. Hardware you own charges for the whole minute; a per-call lane charges at the moment of action. A 450M model is the class where this math works best. It is light, so a call is cheap. It is capable, so the call is worth making. Every field, error code, and limit lives in the run-action reference.
curl
curl -X POST "https://api.ironstratum.com/v1/action" \
-H "Authorization: Bearer $KEY" \
-F "model=smolvla" \
-F "instruction=pick up the red cube and put it in the box" \
-F 'state=[0.0, 0.12, -0.4, 0.0, 0.5, 0.1, 0.0]' \
-F "image=@top.jpg" \
-F "image=@wrist.jpg"
python
import os
import requests
resp = requests.post(
"https://api.ironstratum.com/v1/action",
headers={"Authorization": "Bearer " + os.environ["KEY"]},
data={
"model": "smolvla",
"instruction": "pick up the red cube and put it in the box",
"state": "[0.0, 0.12, -0.4, 0.0, 0.5, 0.1, 0.0]",
},
files=[
("image", ("top.jpg", open("top.jpg", "rb"), "image/jpeg")),
("image", ("wrist.jpg", open("wrist.jpg", "rb"), "image/jpeg")),
],
timeout=30,
)
resp.raise_for_status()
answer = resp.json()
chunk = answer["actions"] # the action chunk, in the model's own shape
stats = answer["normalization"] # the statistics this endpoint applied
print("steps in this chunk:", len(chunk))
print("cost of this call:", answer["usage"].get("cost"))
lerobot
import os
import requests
from lerobot.cameras.opencv import OpenCVCamera
session = requests.Session()
session.headers["Authorization"] = "Bearer " + os.environ["KEY"]
cam = OpenCVCamera(camera_index=0, fps=30, width=640, height=480)
cam.connect()
instruction = "pick up the red cube and put it in the box"
state = [0.0] * 7 # your arm's joint positions, same order on every call
running = True
while running:
frame = cam.async_read()
resp = session.post(
"https://api.ironstratum.com/v1/action",
data={
"model": "smolvla",
"instruction": instruction,
"state": "[" + ", ".join(str(s) for s in state) + "]",
},
files={"image": ("top.jpg", frame, "image/jpeg")},
timeout=30,
)
resp.raise_for_status()
chunk = resp.json()["actions"]
for step in chunk:
state, running = arm_step(state, step) # your arm driver goes here
if not running:
break
The loop is the whole pattern, the synchronous one. To go asynchronous, keep executing the chunk while the next frames send, exactly as the section above describes.
Norm stats, and the wild-arm problem
The most common real-world failure with this model is not a bad model. It is mismatched statistics, and it is the reason a normalization block is part of this route's contract.
Every SmolVLA checkpoint carries norm stats from the dataset it was tuned on. Those numbers translate the model's output into your arm's units. Use the stats from the wrong dataset, or forget to un-scale the output, and the arm either barely moves or sweeps hard toward its limits. Community threads describe arms slamming into their reach limits on first load; a university walkthrough opens with an arm flailing at the first instruction; the model's own issue tracker starts the same way. Nobody was doing anything exotic. The stats step was missing.
The prevention, in order. Fine-tune on your own recordings before you trust any policy near hardware. Keep one task sentence per task while you record. Apply the stats that ship with the checkpoint you actually run. Never let an untested policy drive an arm at full power. On this platform the answer carries the normalization block it applied, byte for byte; the action route notes document it, and the SO-101 cloud brain guide walks the record, train, and serve loop.
Benchmarks
Every number below is from the authors' paper (arxiv 2506.01844, June 2025) or from a named third party, dated. Nothing here is this platform's own measurement. This platform publishes its own numbers only after they are measured and held, and this page carries none.
LIBERO, simulation, multi-task. Four suites, ten tasks each. Inputs for the SmolVLA rows: camera, robot state, language.
| Policy | Parameters | Average success |
|---|---|---|
| Diffusion Policy | - | 72.4 |
| Octo | 0.09B | 75.1 |
| OpenVLA | 7B | 76.5 |
| pi0, VLM-initialized | 3B | 71.8 |
| pi0, robotics-pretrained | 3.3B | 86.0 |
| SmolVLA, small variant | 0.24B | 82.75 |
| SmolVLA | 0.45B | 87.3 |
| SmolVLA, large variant | 2.25B | 88.75 |
Meta-World MT50, simulation. SmolVLA averages 57.3, against 47.9 for a robotics-pretrained pi0 at 3.5B and 31.6 for TinyVLA.
Real robot, SO-100, three tasks (pick-place, stacking, sorting).
| Policy | Training | Average success |
|---|---|---|
| ACT | single-task, from scratch | 48.3 |
| pi0, 3.5B | multi-task, fine-tuned | 61.7 |
| SmolVLA | multi-task, fine-tuned | 78.3 |
Real robot, SO-101, pick-place-Lego. In distribution: SmolVLA 90, ACT 70. With the object moved to unseen positions: SmolVLA 50, ACT 40. The paper also notes SmolVLA trains about 40 percent faster than pi0 in this setup and needs about six times less memory.
Asynchronous inference, SO-100. Success is about equal across modes. Completion time falls from 13.75 to 9.7 seconds, and fixed-window throughput doubles from 9 to 19 cycles.
The numbers that cut the other way
Three families of numbers circulate about this model. They disagree, and the disagreement is the honest story.
The first family is the official one above: strong simulation averages, strong multi-task SO-100 results. The second is latency. A robotics vendor that trains SmolVLA for customers measured about 245 milliseconds per action step in its shared training pool in August 2026. Against that, in the same pool: roughly 20 milliseconds for ACT, 152 for GR00T N1.7, and 485 for pi0.5. The vendor's page states the basis: a shared pool, not a dedicated machine. The official async stack, on one dedicated RTX 4090, reports under 100 milliseconds. Same model, three numbers, three setups. Read a latency claim by its basis.
The third family is the hardest: PhAIL, a real-robot benchmark from Positronic Robotics, with two reads. The first is the live community leaderboard, read October 5, 2026, the read this site's family pages carry. It measures single-arm pick and place on a DROID setup, with production metrics. Human teleoperation scored 99.0 percent at 10.4 seconds per item. GR00T N1.6 and open pi 0.5 led the robots at 46.1 and 44.4 percent. ACT, third, scored 42.5 percent and was the fastest robot at 13.8 seconds per item. SmolVLA sat fourth, at 16.3 percent success and 16.3 seconds per item. The same live read, same date, is on the pi 0.5 family page and the act page.
The second read is the benchmark's own paper (arxiv 2605.29710, May 2026). That run put four public VLAs on a Franka FR3 for bin-to-bin picking, all fine-tuned on one shared 449-episode dataset, scored on human-reference throughput. SmolVLA ranked last of the four: 6.4 percent of human-reference throughput, against 10.5 for ACT, 13.3 for GR00T N1.6, and 13.8 for OpenPI pi0.5. Its restricted mean solve time was 165.8 seconds, with an intervention (safety-stop) rate of 18.6 percent. The leaderboard and the paper are different runs with different metrics, not comparable row for row. The setup notes matter: SmolVLA ran with absolute Cartesian end-effector poses, on an industrial arm, far from the SO-100 joint recordings it was pretrained on. That does not erase the result. It bounds it.
That is the shape of the honest claim. On its home ground, low-cost arms with modest data, SmolVLA is the best-documented small policy anywhere. Off its home ground, buy by benchmark, not by brand. The LeRobot LIBERO evaluation docs pin the data revision, so scores stay comparable.
Getting started
- Read the primaries. The paper. The release blog. The LeRobot docs page. The model card. Every identity fact on this page traces to them.
- Record before you trust. About 50 episodes per task, five object positions, ten each, one fixed sentence per task. The docs are explicit that 25 was not enough in their trials. Fine-tune on your hardware or a free notebook, and test with the arm at low power until the stats question is settled.
- Write your client against the contract now. The tabs above are the shape the lane ships under. The run-action reference documents every field, limit, and error. The models index is the live catalog.
- Open the console when you build. The signup flow opens the wallet, the keys, and the billing history. The loaded balance is the spend bound. Each key revokes alone.
Related pages in this family: the VLA category page explains the model class and the shared call contract. pi05 leads the bigger family, with its DROID and LIBERO tunes. OpenVLA-OFT is the fine-tune specialist at 7B. MolmoAct2 is the fresh option on the same arms. For the fastest small policy, see act; for machine vision, sam2.1-base and da3-small; for continuous visual reasoning, Molmo2-ER. The models index lists the current offering.