What Is CUA-S1-FORMS? Cua's 706K-Param System 1 Model
The short version
CUA-S1-FORMS is what happens when you stop asking a frontier model to decide whether the “Phone number” field should get the phone number. Cua founder Francesco Bonacci open-sourced it on September 17, 2026: a 706,048-parameter, 2.8 MB, MIT-licensed model that makes exactly that class of decision in one forward pass, at 99.95% top-1 on its synthetic test and 100% on real forms, and that runs in a browser tab.
It matters less as a form filler than as a pattern: the first checkpoint in a planned family of small “System 1” models for bounded interface decisions inside computer-use agents, sitting beneath a large model that does the planning. Cua’s frame borrows from Kahneman — fast, intuitive System 1 for recurring narrow choices; slow, deliberate System 2 (the LLM) for everything else.
Verified September 20, 2026 against the Hugging Face model card and the trycua/cua repository.
How it works
| Aspect | Detail |
|---|---|
| Task | Given one actionable form element and the entities extracted from a source document, decide: fill with entity i, CHECK, CLICK or SKIP |
| Input (context) | Up to 224 bytes: TASK …, FORM <title>, ELEMENT Edit "Phone number" value="" |
| Input (options) | One per document entity (e.g. fill Tel: (503) 555-0142, fill DOB: 03/14/1987) plus check, click, skip, each ≤ 96 bytes |
| Output | One probability per live option, softmax over the option count |
| Architecture | Byte-level embedding → 2-layer Transformer encoder (width 128, 4 heads) over context and, separately, over each option; a Jev-style attention head turns each option into a query against the context, and a shared dot product yields one logit per option |
| Size | 706,048 trainable parameters; 2.8 MB checkpoint (state dict + config + training history + best validation metrics) |
| What it does not do | Generate new text, read screenshots, decide execution order |
| Execution | Every actionable element is scored independently and in parallel in one batch; downstream code orders fills → checkboxes → the single submit click and sends set_value/click to Cua Driver |
This is the same input/output contract as TypeSafe’s Jev, the hosted “System One” model that introduced the pattern. Cua’s contribution is an open, tiny, locally trained equivalent that beats the hosted API on its own task.
Training
- 10,000 synthetic episodes from
cua_s1/synth.py: a random form of 2–16 fields drawn from a 55-concept catalogue with form-label/document-label synonyms; a random person; a random document with distractor entities and forced look-alike confuser pairs (email vs street, phone vs emergency-contact phone, state vs university); random window-title suffixes and 20% title dropout. - Splits are disjoint by exact form field signature — no test form’s field set appears in training.
- AdamW, cosine schedule with warmup, 6 epochs, batch size 128, cross-entropy over the live option count.
Results
| Evaluation | Top-1 | Note |
|---|---|---|
| Synthetic test (form-disjoint, ~15K decisions) | 99.95% | Hard confuser pairs forced in |
| Real demo eval (3 real forms + 3 real PDFs, 196 decisions) | 100% | Nothing synthetic |
| Shuffled-context control | 37% | Confirms it reads the element, not option statistics |
vs hosted Jev (jev-latest, zero fine-tuning, same task) | 99.7% vs 83.6% | Jev: 96% on judgment decisions (fill/check/click), 74% on recognising an already-filled field as a no-op — a convention this model was trained on and Jev was not |
Read the last row carefully: the head-to-head is on Cua’s task definition, and the “already filled → skip” convention is one Jev never saw. The fair claim is that a purpose-trained 700K-parameter model beats a general hosted System-1 API on the exact task it was trained for — which is the point of the pattern, not a knock on Jev.
How to use it
from pathlib import Path
from huggingface_hub import hf_hub_download
from cua_s1.model import load_checkpoint, select_device
repo = "cua-ai/cua-s1-forms"
weights = Path(hf_hub_download(repo, "cua-s1-forms.safetensors"))
hf_hub_download(repo, "cua-s1-forms.json", local_dir=weights.parent) # sidecar next to the weights
# validates format, version and SHA-256 tensor signature before returning
model, collator, config = load_checkpoint(weights, select_device("auto"))
cua_s1/planner.py in the repository has the full snapshot → score → order → execute loop against a live Cua Driver session.
Notes from the model card:
- The checkpoint format is safetensors + JSON sidecar (architecture config, a SHA-256 signature over the tensors, metadata).
cua_s1’s loader rejects pickled.pt/.pthfiles by design — arbitrary pickle is a code-execution risk for a public checkpoint. A.ptis kept only for people callingtorch.load(..., weights_only=False)directly; both encode identical weights. - The live Cua Driver integration, synthetic data generator, training and eval code live in
libs/cua-s1of the trycua/cua repository. Cua itself is the open-source framework that gives agents full control of macOS, Linux and Windows desktops. - A community ONNX conversion runs the model in the browser through ONNX Runtime Web, WebAssembly or WebGPU — no server inference at all.
When to use a System 1 model instead of the LLM
Use CUA-S1-FORMS (or train your own on the released code) when a decision is:
- Recurring and bounded — a fixed set of actions per element;
- Too variable for a script — labels, synonyms and layouts change;
- Latency- or cost-sensitive — a 2.8 MB model scores every field of a form in one batch in milliseconds, versus one LLM call per field at frontier prices;
- Private — the document entities never leave the machine.
Keep the LLM for extracting the entities from the source document in the first place, for deciding what the task is, and for anything requiring generated text. The stack Cua is pointing at is LLM for System 2, a shelf of tiny specialists for System 1, and CUA-S1-FORMS is specialist number one. For where this fits among full computer-use agents, see best computer-use AI agents 2026 and how to deploy a computer-use agent safely.