Problem
Filling out job applications is repetitive form work, but naive agent loops are expensive and error-prone: dozens of model calls per form, invented answers in fields the model should have skipped, and no verification that what was typed matches what was intended. ATS forms also vary widely (Greenhouse, Ashby, Lever, Workable each have their own markup quirks), so brittle per-site scripts break constantly.
The project asks: how do you fill a form with ~50x fewer model calls and ~99% fewer tokens than a naive agent loop, while guaranteeing nothing is ever invented?
Approach and architecture
The pipeline separates what needs a model from what does not:
- schema_dump loads the posting in a debug-Chrome browser and dumps every form field (label, type, options, required) as JSON.
- map makes one model call per form: a local model maps each field to an answer from a personal facts file using strict JSON schema output. Fields with no safe answer map to
skip. - hard_patterns / templates answer the long tail of screening questions (work authorization, demographics, salary, education, yes/no willingness) with deterministic pattern matchers. Zero model calls. First matching pattern wins; unknown fields are skipped, never guessed.
- fill applies the field map through the Chrome DevTools Protocol: batched JS for text fields, real clicks for selects, radios, and uploads. Every field is read back and diffed against expected values.
- verify / submit confirm the fill, then submit.
The one hard rule: the harness never invents facts. Anything not in the facts file is skipped.
Key decisions
One model call per form, not per field
Mapping is the only step that genuinely needs judgment, so it gets exactly one strict-schema model call. Everything else is deterministic. That is where the ~50x call reduction and ~99% token reduction come from.
Deterministic patterns for the long tail
Screening questions are repetitive and enumerable: work auth, veteran status, disability, EEO demographics, salary expectations, start dates. Pattern matchers answer these with zero model calls and zero hallucination risk.
Read-back verification before submit
The fill step reads every field back from the DOM and diffs it against the expected map. A form is only submitted when the read-back matches, which catches the class of bugs where a fill silently landed in the wrong field.
Challenges
The main engineering challenges were:
- handling per-application email code gates (Greenhouse requires a fresh verification code on every submit)
- normalizing the markup differences across four ATS platforms without per-site code
- keeping the standard library as the only dependency so the tool runs anywhere
- making "skip" the safe default so missing facts can never become invented answers
Outcome and learning
Real verification numbers from production use: 42/42 Greenhouse fields verified on live forms with zero mismatches, 82/82 Ashby and Lever fields across 8 real forms with zero model calls, and 18/18 offline tests passing with no browser, model, or network required. The lasting takeaway is that agent workflows get cheaper and safer when you shrink the model's job to the smallest possible surface and make everything else deterministic.