~/satyajit

FLUX 3 Action: 2,720 tokens of imagined video for every 32 robot actions

mdjsonmcp

2026-09-26 · 25 min · robotics · world-models · black-forest-labs · open-weights · flow-matching · diffusion · explainer

Two months ago this site covered FLUX 3, Black Forest Labs' move from image model to "world model". One row of that article's release table read FLUX 3 Action: rolling out. On 2026-09-23 it rolled out, as open weights, in three Hugging Face repositories: flux-3-action-base, flux-3-action-so101 and flux-3-action-droid. There is also a training and inference codebase, flux-action, and a long technical write-up on BFL's blog that stands in for a paper. There is no arXiv report.

The card makes two headline claims: "an open weights 7B world action model", and first place on the RoboLab-120 simulation benchmark at 42.92% task success. I summed the tensor shapes in every safetensors header, read by HTTP range request. I read the flux-action source to see how an action leaves the network. And I checked the benchmark claim against the live leaderboard and BFL's own seed table. The mechanism comes first, because it explains the costs.

What a world action model is

A robot policy maps what the robot sees and feels to what it does next. Modern policies emit an action chunk: a short trajectory of future commands, say 32 joint targets, executed open-loop before the policy looks again. Chunking amortizes one expensive network call over many control ticks.

There are two families of learned policy, and the DROID model card defines both under its results table:

The argument for a WAM is data. Robot demonstrations are scarce and expensive. Video of the world moving is not. If the same weights must predict what the scene will look like after the gripper closes, a video model's knowledge of how objects move transfers to the action it pairs with the frames. The argument against is cost. Video is thousands of tokens, actions are a few dozen, and a WAM pays for the whole sequence on every denoising step. BFL frames its release as making that cost tolerable: "When you choose a WAM you pay in latency and hardware costs; when you choose a VLA you give up on almost a quarter of successful rollouts."

How it works: five streams on one clock

What goes in, and what comes out

Take the DROID policy, the one with the benchmark number. Per call it takes a text instruction, three RGB cameras at 360×640 and an 8-value state: seven joint angles in radians plus a gripper closed fraction. It returns a (1, 32, 8) array of 32 absolute joint targets plus gripper, at 15 Hz. That is 2.13 s of motion.

Inside, everything becomes tokens in five streams, and each stream has its own embedding layer:

The first three streams are clean inputs: the model sees them at noise level zero. The last two start as Gaussian noise and are denoised together. Switch to SO-101 below and the shapes change: five joints plus a gripper at 30 Hz, a 42-action chunk, two camera snapshots and eight ticks of history.

one forward pass ·
clean inputs, t = 0hatched: denoised from noise
streamtokensshareeach token is
task text802.5%20,480 values → 3,072 · Qwen3-VL-4B layers 4, 8 … 32, stacked
camera now34010.7%96 values → 3,072 · 3 cameras on one canvas, 1 latent frame of 17 × 20
joint state10.0%8 values → 3,072 · 7 joint angles + gripper
future video2,72085.7%96 values → 3,072 · 8 latent frames × 340, each spanning 4 control ticks
action chunk321.0%8 values → 3,072 · one token per 15 Hz tick: 7 joint targets + gripper
total3,173100%80 is the floor: captions are padded up to a multiple of 80
checkpoint ·

actions are 1.0% of the sequence; imagined future video is 85.7%.

4 UniPC steps, video guidance 4 → 8 passes per plan · 25,384 token-passes through the 28 shared blocks for 32 actions

Read from the released config.json files and the flux-action code: VAE latents are 96 channels at 32× spatial and 4× temporal compression. The inference API returns only the action stream; the future-video tokens are denoised and dropped.

In one DROID forward pass the sequence is 3,173 tokens (with the shortest caption), and 85.7% of it is imagined future video. The actions the robot will actually execute are 32 tokens, 1.0% of the sequence. The released base checkpoint runs 4 sampler steps with classifier-free guidance, which means two passes per step, so one plan pushes about 25,000 token-passes through the network to produce 32 vectors of 8 numbers.

One backbone, private blocks first

The DiT is a FLUX-lineage transformer: hidden size 3,072, 24 heads of 128, a SwiGLU MLP of 9,216, and RMS-normed queries and keys. What is unusual is the order of its blocks, and the checkpoint spells it out:

Block groupWhat it doesParameters (base, measured)
5 mode blocks per stream, × 5 streamseach stream attends only to itself, with its own weights3,067,091,200
28 shared blocksall streams concatenated, one joint attention over everything3,435,142,144
per-stream modulation (early + shared)each stream's scale, shift and gate from its own timestep283,115,520
input embedders (txt_in, time_in, vector_in)project text, timestep and a pooled vector to 3,07284,934,656
per-stream input and output heads (video, ee50, gaming, each with a _cond twin)tokens in, predictions out115,826,688
total DiT457 tensors, all BF166,986,110,208

Each stream gets five private transformer blocks. The text is processed as text and the camera history as video, with no cross-talk. Then all five streams are concatenated and 28 shared blocks attend across the whole sequence. This is where an action token can read the video tokens of the frame it will cause. Two details make the shared blocks work for tokens at different noise levels:

The text path has a practical consequence. The five text mode blocks never see the video, and their timestep is pinned at zero, so their output depends only on the prompt. BFL caches it once per instruction, which its latency table relies on. BFL's own diagram draws the same structure without the numbers:

Block diagram titled FLUX 3 Action. An instruction, three camera images and a robot-state waveform pass through a text encoder, a video encoder and a state encoder into task, history and state tokens. These feed a box labelled FLUX 3 backbone whose layers 1 to N each hold task, history, state, future and action features. From the last layer, future tokens go through a video decoder to predicted frames, and action tokens go through an action decoder to robot actions.
Text, camera history and robot state enter as tokens; the backbone carries task, history, state, future and action features through every layer; future tokens decode to frames and action tokens to robot actions (BFL, FLUX 3 Action report, Figure 3).

How an action comes out

The "action decoder" in that figure is one linear layer, 3,072 → 8, behind an adaptive layer norm. There is no action vocabulary, no binning, no autoregressive decoding over tokens. The action stream is continuous and generated by flow matching, the same objective as the image and video models. Training mixes clean data x0x_0 with noise ε\varepsilon as zt=(1−t) x0+t εz_t = (1-t)\,x_0 + t\,\varepsilon and learns the velocity that carries ztz_t back toward x0x_0. At inference the DROID sampler runs:

  1. Start the future-video stream and the 32-token action stream from Gaussian noise.
  2. Take 4 steps of the UniPC solver (order 2, time shift 5). Video and actions share each step's time.
  3. At every step run the DiT twice, once with the instruction and once with an empty caption, and combine the two predictions per stream: guidance 4 on video, 1 on actions. A scale of 1 means the action stream simply takes the conditional prediction; only the video is pushed toward the instruction. BFL's grid search over the two scales peaked at exactly that pair, 42.00% success.
  4. Divide the action stream by the action scale of 2, undo the gripper inversion, and return 32 absolute joint targets.

The action scale is the least obvious knob. Multiplying the actions by ss before noising means more noise is needed to destroy them, so the action stream resolves earlier in sampling than the video. BFL's reading is that with s≫1s \gg 1 the joint model approximates choosing the motion first and then imagining what it looks like, and with s≪1s \ll 1 the reverse. BFL says plainly that its sweep showed no clear trend. But s=2s = 2 with a timestep distribution shifted by α=42\alpha = 42 kept scoring well, and it had the best median, 36.72% on the simple task suite. The settings sit in the released configs: action_scale: 2.0, train_timestep_shift: 42.0, train_timestep_width: 0.75.

Step 4 is the one to notice. _sample returns out[ak], the action stream. The 2,720 future-video tokens are denoised on every call and then dropped. They are never decoded to pixels. BFL's inference docs say it plainly: the API "neither decodes those latents into RGB frames nor exposes a video output flag."

Where the weights came from

The base checkpoint's metadata says:

FLUX Action DiT base for embodiment finetuning: video + text + shared action streams, ee50 and gaming action heads. Removed: image and audio streams, joint14 heads, repa projectors. BF16.

It also records "step": "724000" and "ema": "classic, decay 0.999". Together these tie the release to the FLUX 3 backbone. This is the multimodal model, pretrained on image, video and audio with "video accounting for over 95% of the training tokens", with its image and audio streams cut away. repa is the usual name for representation-alignment heads, auxiliary projectors that only matter during training; BFL credits its multimodal Self-Flow pretraining for the backbone's representations. Step 724,000 is the "724K action-midtraining checkpoint" the report fine-tunes DROID from. BFL gave no parameter count for FLUX 3 at launch, so this is the first FLUX 3 checkpoint anyone outside BFL can count. Whether FLUX 3 Video is the same size is not stated.

Midtraining is where actions enter. BFL continued training on 36.95% pretraining video with audio and 63.05% video that comes with aligned actions: 19.55% game recordings, 13.54% egocentric video with hand-pose labels, 14.03% handheld grippers and 15.93% teleoperation across 14 embodiments. Two action vocabularies exist at this stage, and both survive in the base as heads you can measure:

The report's ablation is the argument for the whole design. With random initialization, 10,000 steps of fine-tuning on DROID reach 0.75% on RoboLab. From pretraining checkpoints the same recipe reaches 11.6 to 12.4%, and from the 724K midtraining checkpoint 18.63%. The native EE50 head, with no DROID fine-tuning at all, gets 17.29%.

Bar chart of RoboLab success rate by initialization. Random initialization is under 1 percent. Pretraining checkpoints at 400K, 500K and 636K steps score about 11.6 to 12.4 percent. Action-midtraining checkpoints at 647.5K, 682K and 724K steps are shown twice: hatched bars for the EE50 head used directly, rising from about 7 to about 17 percent, and solid bars for joint fine-tuning for 10K steps, rising from about 14 to about 18.6 percent.
Video pretraining is the difference between under 1% and double digits; action midtraining adds the rest. Preliminary settings, small batch, so the absolute numbers are low (BFL, FLUX 3 Action report, Figure 4).

Three repositories, and what is in each

RepositoryDiT parameters (measured)Action headChunk and rateSampler
flux-3-action-base6,986,110,208EE50 (50) + gaming (64)n/a, adaptation basen/a
flux-3-action-so1016,947,071,2325 joints + gripper: joint deltas, absolute gripperpredict 42, execute 32, at 30 Hz4 Euler steps, shift 6.93, guidance 3
flux-3-action-droid6,947,058,9447 joints + gripper, absolutepredict 32, execute 32, at 15 Hz4 UniPC steps, shift 5, guidance 4 / 1

The base also holds the two frozen encoders every policy loads from it: the video VAE, with 1,254,034,544 parameters, and an unmodified Qwen3-VL-4B-Instruct under Apache-2.0, with 4,437,815,808. The policies pin both to a fixed base revision and ship none of their own.

The DROID repository carries five more packages under variants/, for six in all. There are three recipes: the root (4 steps with guidance), gd (guidance-distilled: 4 steps, one pass each) and sd (step-distilled: one step). Each recipe comes in BF16 at 13.9 GB and as an FP8 twin at 7.1 GB (fp8r, gd-fp8r, sd-fp8r). The FP8 file stores 6,795,952,128 weights as E4M3 with one FP32 scale per row. It keeps 151,106,816 in BF16: the action streams' input and output heads and modulation layers, which the README says are left unquantized on purpose.

The card's "new embodiments require their own action heads" makes a fine-tune sound like bolting on a head. It is not. I range-fetched the same three weight matrices from all three checkpoints: the query projection of a shared block, a text mode block and a video mode block. In each, the DROID and SO-101 policies sit 22–30% of the base weight's norm away from the base, and further still from each other: two full fine-tunes from one start. That matches the report's recipe, which freezes the trunk for the first 1,000 steps, then warms it up to a learning rate of 2e-4 over the next 2,000. Each embodiment is a complete 6.95B checkpoint. The lighter route BFL documents is a rank-32 LoRA for task adaptation on SO-101.

Checking the claims

"7B"

The DiT is 6.99B in the base and 6.95B in each policy, so "7B" is honest rounding. It is also the number that leaves out 5.69B of weights you cannot run without:

What loads for one DROID policyParameters (measured)BF16 on disk
DiT6,947,058,94413.9 GB
Qwen3-VL-4B-Instruct text encoder4,437,815,8088.9 GB
video VAE1,254,034,5442.5 GB
total12,638,909,29625.3 GB

BFL's blog says the model beats the previous best open model "at less than half the parameters". That is Cosmos3-Nano-Policy, listed at 16B. I counted its DROID checkpoint the same way: a 15.17B transformer, a 0.70B VAE and a 0.58B vision encoder, 16.45B in all. Backbone against backbone, 6.95B is 46% of 15.17B, and the claim holds. Everything-loaded against everything-loaded, 12.64B is 77% of 16.45B. Cosmos 3's transformer contains its own language tower, while FLUX 3 Action outsources text to an encoder whose output it caches per prompt, so per denoising step the backbone is the fair comparison. Fair, then, and incomplete.

Memory comes in three numbers. The card says "about 32 GB of GPU memory in bfloat16 on an NVIDIA H200", and under 24 GB with FP8 and the text encoder offloaded. The RoboLab leaderboard lists 69 GB for the same policy. The weights alone are 25.3 GB.

"First place on RoboLab"

RoboLab-120 is 120 tabletop tasks in Isaac Sim on a DROID-style Franka arm, 10 trials each, so 1,200 episodes. A trial counts only if the task is done as instructed. Here is the top of the live leaderboard, read on 2026-09-26. The 95% intervals are exact Clopper–Pearson bounds on each success count, as the leaderboard computes them:

#PolicyTypeSuccessesSuccess rate95% intervalWeightsSim data in fine-tuning
1FLUX 3 ActionWAM515 / 1,20042.9%40.1–45.8%open, 7Bno
2HiDream-O1-EmbodiedVLA479 / 1,20039.9%37.1–42.8%closed, 6Byes
3Atomic-WAMVLM+WAM475 / 1,20039.6%36.8–42.4%open, 16.2Byes
4OASIS WAMVLM+WAM468 / 1,20039.0%36.2–41.8%closedno
5Cosmos3-Nano-PolicyWAM441 / 1,20036.8%34.0–39.5%open, 16Bno
9π0.5VLA336 / 1,20028.0%25.5–30.6%open, 3.3Bno

The first place is real, and it is better than it looks in one respect. The leaderboard marks FLUX 3 Action as verified: organizers "were able to independently run this policy and/or cross-check its reported results". The board records no RoboLab, Isaac Sim or other simulator data in its training. The entries in second and third place both fine-tuned on RoboLab or Isaac data, so their evaluation scenes are in distribution. FLUX 3 Action's are not.

It is weaker than it looks in three respects:

On real hardware, BFL commissioned Positronic Robotics to run ten DROID tasks, three attempts each, on a Franka arm. The operator was blind to which model was driving. The score was 28 of 30 for FLUX 3 Action, 27 for Cosmos 3 Nano, 20 for DreamZero and 13 for π0.5. That is one attempt ahead of Cosmos on a sample of 30: a result that says both work, not that one is better.

"Up to 3.95× faster"

Success of all six DROID packages, means over seeds from the report's Table 5:

DROID packagePasses per planBF16 successFP8 success
base (root, variants/fp8r)841.60%41.16%
guidance-distilled (gd, gd-fp8r)442.19%42.24%
step-distilled (sd, sd-fp8r)138.68%37.92%

Guidance distillation trains a student to reproduce the guided prediction in one pass: half the passes, and 0.6 to 1.08 points better. Step distillation then collapses four steps into one, at a cost of 3.5 to 4.3 points, still above Cosmos3-Nano's 36.8%. Both keep the joint video-and-action prediction intact rather than cutting the video stream. BFL's latencies per predicted chunk, with the prompt cached and cameras re-encoded on every call:

GPUF3A base BF16 / FP8 (ms)F3A gd BF16 / FP8 (ms)F3A sd BF16 / FP8 (ms)Cosmos 3 Nano BF16 / FP8 (ms)π0.5 BF16 (ms)
B200246.42 / 182.00136.25 / 101.7141.06 / 32.29387.71 / 320.4031.99
H200397.74 / 291.67216.91 / 145.6460.51 / 43.81713.76 / 575.7546.96
RTX 6000 Pro772.60 / 553.10426.00 / 309.30118.80 / 91.501278.30 / 840.8057.70
RTX 50901458.62 / 697.79720.71 / 344.51179.80 / 85.431980.22 / 1129.3434.92

"Up to 3.95×" is the guidance-distilled FP8 package against Cosmos 3 Nano in FP8 on an H200: 575.75 ÷ 145.64. The bottom of BFL's "1.52× through 3.95×" range is the base FP8 package on an RTX 6000 Pro. Both reproduce from the table.

Against π0.5, BFL itself notes the advantage is "in real-time factor, not latency per call". The real-time factor (RTF) is compute time divided by the seconds of motion that compute buys:

RTF=tcomputen/f\text{RTF} = \frac{t_{\text{compute}}}{n / f}

Here nn is the number of actions executed per plan and ff is the control rate. Per call, the step-distilled FP8 model and π0.5 cost the same on a B200: 32.29 ms against 31.99 ms. FLUX 3 Action wins on RTF because its call buys 2.13 s of motion (32 actions at 15 Hz) and π0.5's buys 1.00 s. That holds only while you execute the whole chunk blind. BFL's game example executes 8 actions and its shooter experiment 2. On a B200 the break-even is about 15 executed actions: replan any sooner and the 1-step model spends more compute per second of motion than π0.5 running its full chunk.

Scatter plot of RoboLab success rate against real-time factor on a B200 in FP8. F3A Guidance Distilled sits at about 42 percent and 0.048, F3A at about 41 percent and 0.085, and F3A Step Distilled at about 38 percent and 0.015, joined by a dashed new Pareto front. Cosmos 3 Nano sits at 36.8 percent and 0.150 and π0.5 at 28 percent and 0.032, joined by a dotted previous Pareto front.
BFL's speed–success plot on a B200 in FP8 (π0.5 was evaluated only in BF16, so its point is its BF16 result): all three FLUX 3 Action packages sit above and left of the Cosmos 3 Nano to π0.5 front. The x-axis assumes the whole chunk is executed (BFL, FLUX 3 Action report, Figure 1).

Move the slider to execute fewer actions per plan and watch the real-time factor respond:

one plan = 32 predicted actions at 15 Hz · latencies are BFL’s, the horizon arithmetic is mine
GPU
checkpoint
precision
one plan: 32 predicted actionsfive seconds of the loop: dark = computing, colour = moving0 s1 s2 s3 s4 s5 s
policy on B200per callmotionRTFFLUX 3 Action, step-distilled FP832.29 ms2.13 s0.015π0.5, BF16, 15 actions31.99 ms1.00 s0.032Cosmos 3 Nano, FP8, 32 actions320.4 ms2.13 s0.150

ahead of π0.5 per second of motion · break-even at 15.1 executed actions · robot waits 1.5% of the time in a synchronous loop

RoboLab-120 success for this checkpoint and precision: 37.92% (mean over seeds, BFL Table 5)

Latencies: BFL’s Table 4, median end-to-end per predicted chunk, prompt cached, cameras re-encoded each call; π0.5 was served in BF16 only. RTF = latency ÷ seconds of motion executed. BFL quotes RTF with all 32 actions executed; move the slider to see what replanning sooner costs.

The shipped DROID profile sets n_action_steps: 32, BFL's assumption. The docs are frank that select_action "does not provide an asynchronous controller or real-time chunking", and that fresh observations "do not replace queued commands". A cube that slips at action 3 is noticed at action 33. That is standard for chunked policies, and it is why the headline RTF is a best case.

Limits

The take

FLUX 3 Action is a video model with a small continuous action stream threaded through it. The design is readable straight off the tensors: five private streams, 28 shared blocks, a joint flow-matching sampler, and a linear action head. It also makes the WAM bargain concrete. For every 32 actions the DROID policy imagines 2,720 tokens of future video, and it throws them away. BFL's contribution is making that bargain cheaper without breaking it: guidance and step distillation that keep the video in the loop, and FP8 packages that, with the text encoder offloaded, fit a 24 GB card.

The claims mostly survive. "7B" is the DiT, and 12.64B is what loads. First place on RoboLab is real, organizer-verified and achieved without simulator data. But the number on the card is the best of six seeds, and second place is within noise. "Up to 3.95×" reproduces from BFL's own table. The π0.5 speed win is a statement about chunk length, not model speed. For anyone building on it, the useful facts are the ones the card is quietest about. Each embodiment is a full re-train of the trunk. The imagined frames are not exposed. And the licence puts a production robot outside the free grant for any company above US$5,000,000 in revenue, and leaves it unclear for those below.

What would change my mind

5 claims above, and what would falsify each

  1. The FLUX 3 Action DiT is 6.99B parameters in the base and 6.95B in each policy; a DROID policy loads 12.64B in all.

    Summed from the safetensors headers of flux-3-action-base.safetensors, both policies' model.safetensors, video_vae.safetensors and both text-encoder shards, counting every BF16 tensor. If the loader instantiates modules that are not in these files, such as the removed image and audio streams as randomly initialized dummies, the in-memory count is higher. sum(p.numel() for p in policy.parameters()) after from_pretrained settles it.

  2. The leaderboard's 515 / 1,200 is the best of six seeds whose mean is 41.60%.

    The six values in BFL's Table 5 for base BF16 are all whole counts out of 1,200, and 515 is the only one that matches 42.92%. If the leaderboard entry was a separate, seventh evaluation, or used a checkpoint other than the released root, then the seed table and the leaderboard are measuring different things and "best of six" is wrong. The organizers' run logs would show which.

  3. The inference API discards the jointly denoised future video.

    Read from policy.py at commit e2dd1d8 (_sample returns only the action stream) and from BFL's inference docs. If a later flux-action release adds a video output path, the card's "on request, predicted camera frames" becomes true and this becomes history.

  4. The DROID and SO-101 policies are full fine-tunes of the trunk, not heads on a frozen base.

    Based on three sampled 3,072 × 3,072 matrices (one shared block, one text mode block, one video mode block), each 22–30% of the base weight's norm away from the base. A full-model diff could show that some block groups were frozen after all. Three matrices say "moved", not "all moved".

  5. Against π0.5, FLUX 3 Action's speed advantage is chunk length, not per-call latency.

    From BFL's Table 4: 32.29 ms against 31.99 ms per call on a B200 for the step-distilled FP8 package. On an H200 FLUX 3 Action is slightly faster per call (43.81 against 46.96 ms). On the RTX cards it is slower. An independent latency measurement on matched hardware, with the prompt cache and compilation settings stated, would move these numbers but not the logic.


Measured: parameter counts, tensor shapes, dtypes and checkpoint metadata, from the safetensors headers of all three FLUX 3 Action repositories and of Cosmos3-Nano-Policy-DROID, read by HTTP range request on 2026-09-26, plus the relative weight distances between checkpoints from three range-fetched matrices. Read from source: the stream layout, token counts, sampler, guidance split and the discarded video stream, from flux-action at e2dd1d8 and the released config.json files. No code from the repository was run and no model was served. Reported: everything from BFL's FLUX 3 Action report and documentation, including all success rates, latencies and the real-robot results, and the RoboLab leaderboard as read on 2026-09-26. The three figures are BFL's, captured from the report's page. The token ledger, the replanning clock and the tables are mine. Previously: FLUX 3 on the backbone, Cosmos 3 on the rival WAM, and Flex-π on another world-action policy.

Cite this article

For attribution, please use the following reference or BibTeX:

Satyajit Ghana, "FLUX 3 Action: 2,720 tokens of imagined video for every 32 robot actions", ai.thesatyajit.com, September 2026.

bibtex
@misc{ghana2026flux3action,
  author = {Satyajit Ghana},
  title  = {FLUX 3 Action: 2,720 tokens of imagined video for every 32 robot actions},
  url    = {https://ai.thesatyajit.com/articles/flux-3-action},
  year   = {2026}
}
share