Inspiration

Georgia planted over a million acres of cotton this year, and right now is defoliation season. On September 29, the UGA Extension cotton agronomist posted his spray advice, and it changed week to week "strictly based on temperatures in the forecast." A defoliation tank usually holds two or three products, and each one has its own EPA label with its own wind limit, rain-free period and temperature rules. Federal law says you have to follow every one of them. So the person spraying is holding three PDFs up against an hourly forecast, field by field, during the busiest weeks of the year. I wanted to do that cross-check for them and show my work. (Source: https://georgiacottoncommission.org/hand-preparing-for-the-2026-harvest-defoliation-recommendations-for-a-variable-crop/)

What it does

Pick a field and the products in your tank. Labelhand checks every EPA label in that tank against the next 156 hours of the National Weather Service forecast and gives each hour one state:

  • Forecast-permitted when every rule on every label passes.
  • Blocked when a rule fails, with the product, the page and the exact sentence.
  • Field check when the forecast can't decide, like a possible inversion, so you check on site.

"Show on the label" opens EPA's own PDF at that sentence, highlighted. You can ask the tank questions in plain English, see what changed between two versions of a label, add any EPA label by name or by photographing the jug, and get a phone call when a window opens for your tank. It never says a spray is legal. The applicator makes the call.

On my test tank at Tift (Folex 6 EC, FreeFall SC and Super Boll), 17 of 156 recorded forecast hours passed all three labels.

Try it: https://labelhand-web.vercel.app/judge walks through everything in about seven minutes. No login, no key.

How I built it

NVIDIA Nemotron 3 Super (nvidia/nemotron-3-super-120b-a12b) reads every label page and turns it into typed rules: parameter, operator, value, unit, and whether it's a must or a must not, each with its exact quote. It runs at temperature 0 with a strict JSON schema. Code decides what survives: the quote has to be on that page, and every number in the rule has to be in the quote. In my first real run that guard caught Super splicing two re-entry intervals into one rule.

NVIDIA Nemotron 3 Ultra (nvidia/Nemotron-3-Ultra-550b-a55b) does a second pass that types each rule. One Super pass covered 0.652 of my gold set on the first tank. Adding Ultra, a second reading of scanned pages and a majority vote across three runs took it to 1.0. On the tank I ship, acting recall is 10 of 10.

NVIDIA Nemotron Parse 2.0 (nvidia/NVIDIA-Nemotron-Parse-2.0) gives scanned pages a second reading. It wouldn't fit on my 8 GB card, so it ran as a Nebius AI Cloud Serverless Job on an L40S, and on a scanned label in my first tank it rescued 5 rules for $0.0046. A quote the first reading got wrong is only accepted if the OCR text of that page confirms it. The three labels in today's tank are clean text and didn't need it.

NVIDIA Nemotron 3.5 Super VL (nvidia/Nemotron-3.5-Super-VL) reads the EPA registration number off a photo of the jug, and the app checks it against EPA's record before compiling anything. It read the number right on 40 of 40 rendered label pages, half of them with simulated phone blur and tilt.

NVIDIA Nemotron 3.5 Lightning (nvidia/Nemotron-3_5-Lightning) answers "Ask the tank" and the questions on the phone call. It has to call the same planner the page uses first, and code checks every rule id, window and number in its answer against what the tools returned before you see it. An answer costs a fraction of a cent.

Nebius Token Factory runs the Super, Ultra, Super VL and Lightning calls; Parse ran as the AI Cloud job above. Compiling the first three labels cost $0.53 to $0.56 per run, and the trace on every answer shows its Token Factory request id, tokens and cost.

Nebius AI Cloud also runs a small CPU job every hour that records the forecast at ten Georgia fields and checks who to call.

The planner never touches a model. It's plain Rust compiled to WebAssembly, so the check runs free in the browser, and CI holds it to a Python reference hour by hour on four frozen forecasts.

Twilio checks your number with a code and places the call. Caps keep it from becoming a robocaller: once per window, 3 calls a day.

Next.js on Vercel serves the app. CI runs 149 Python, 8 Rust, 488 web unit and 48 Playwright tests, and a probe checks production twice a day.

Challenges I ran into

  • I built on a cancelled label for two weeks. EPA's record showed Dropp SC cancelled back in 2014, so I replaced it, wrote a new gold set first, and now the app refuses any cancelled label.
  • I asked a model to just read the labels and the forecast, 30 times. It called 5 of 1,440 hours permitted where the compiled rules found 205. Safe, but no help to someone trying to spray. That's why the decision is code.
  • A forecast is still a forecast. I checked two weeks of day-ahead answers against the airport station: 236 permitted hours held up and 134 broke, every one on wind. The page shows all of them.

Accomplishments that I'm proud of

  • Every blocked hour points to the real sentence on the real EPA PDF.
  • My own phone rang from production with a real window for my tank.
  • Every place the models missed is published on the proof page.

What I learned

  • A model reading a label is good at finding rules and bad at being the final word. Splitting "find" from "decide" fixed most of my problems.
  • Write the gold set before you see the model's answer, or you end up grading toward it.

What's next

No applicator has planned a real tank with it yet. I've asked four county Extension agents in south Georgia to try it on one field this season. Then more scored labels, starting with the ones Georgia growers actually tank-mix.

Live app: https://labelhand-web.vercel.app

Code: https://github.com/StephenSook/labelhand (Apache-2.0)

Built With

  • epa-ppls
  • github-actions
  • national-weather-service-api
  • nebius-ai-cloud
  • nebius-token-factory
  • nemotron
  • next.js
  • nvidia-nemotron-3-super
  • nvidia-nemotron-3-ultra
  • nvidia-nemotron-3.5-lightning
  • nvidia-nemotron-3.5-super-vl
  • nvidia-nemotron-parse
  • pdf-lib
  • pdf.js
  • playwright
  • python
  • rust
  • tailwind
  • twilio
  • typescript
  • vercel
  • webassembly
Share this project:

Updates

Submission history