A vision-language model answers from one prompt. An action policy reads one frame per camera and returns a chunk. A world model rolls thirty-three frames forward before it commits to a move. Three kinds of work that differ by orders of magnitude, so one flat rate would price them all wrong — the tier follows the architecture, and the architecture is printed next to every model in the catalogue.
A robot does not send text, so the unit had to be defined rather than borrowed. It is defined so that the meter tracks the work: an image is 256 tokens, a state dimension is one, and an action chunk is its step count times its width.
| Side | Counted as | Rate | Why |
|---|---|---|---|
| observation | frames × 256, plus one per state dimension, plus instruction text | input | Frames dominate, which is exactly right: a world model reading 33 of them is doing an order of magnitude more work than a policy reading one. |
| action | steps × action_dim | output | Longer chunks and wider embodiments are more work. It also removes the incentive to stretch the chunk purely to save money, which would cost you control quality. |
| prompt / completion | images × 256, text at ~4 chars each | input / output | The vocabulary of the chat half. The action half calls the same two sides observation / action — same structure, words that fit each domain. |
A VLA keeps only the newest frame per camera. Send it thirty and twenty-eight are dropped — but they still crossed the wire and still hit storage, so they are still billed. Rather than hide that, every response reports both numbers.
{
"observation_tokens": 5133,
"action_tokens": 480,
"total_tokens": 5613,
"frames_received": 20, // what you sent, and what you pay for
"frames_used": 2 // what this model actually read
}
// A large gap means check context_frames in the catalogue —
// this model wanted 1 frame per view and you sent 10.
Once a policy is yours and the load is steady, tokens stop being a useful proxy for GPU time. Dedicated containers bill per GPU-hour with scale-to-zero between shifts, and the crossover sits around a third of a GPU held continuously. Nothing in your code changes at that boundary — only the model string.