The problem
The client runs row-crop operations across fields that do not all have the same sensors. A spray decision depends on wind, temperature, and whether the field's own stations are reporting. Agronomists were answering from a forecast plus a group chat about which stations were down. On a field with a dead station, the forecast for the county was being treated as if it were a reading from the field.
The client asked us not to produce a yield number. They have been shown products that promise one from a thin history. The question they wanted answered was narrower: is this field-day a spray window, given the readings we actually have, and if we do not have them, say so.
Why a refusal is an output
A recommendation on a field the sensors are not covering is a guess with the farm's name on it. The product rule is that a spray window is issued only when the required readings for that field are present and fresh. Otherwise the output is a refusal that names the missing station. It is not a softer recommendation.
Architecture
Coverage is a per-field map
We listed, with the agronomist, which stations belong to which field and which readings a spray decision needs. A county forecast can add context. It cannot replace a missing field station. The map is data, not a paragraph in the prompt.
Freshness is a threshold the farm set
A reading older than the window they set is treated as missing. Stale data was the failure mode that looked like data. The refusal names the station and the age of the last reading.
The recommendation cites the fields it used
A released window lists the stations and the forecast fields it relied on. There is no free-text recommendation that can appear without that list. Yield, revenue, and 'expected bushels' are not fields in the output schema, so they are not a sentence the model can add at the end.
The agronomist still decides to spray
The assistant does not talk to the sprayer and does not schedule the pass. It puts a cited window, or a refusal, on the screen the agronomist already uses in the morning.
Challenges and tradeoffs
- Station-to-field mapping was wrong on two parcels. A station had been reassigned after a boundary change and the old map still attributed it. We walked the list with the farm before the season and dated the map. A recommendation cites the map version.
- Forecast hours and station timezones did not line up. A morning window was being computed on the previous evening's hour. Timestamps are normalized to the farm's zone and the evaluation day includes the day boundary.
- A narrative summary put back a yield adjective. The schema was clean and the summary line said the window 'looked strong for the crop.' We deleted the free summary. The screen shows the readings and the yes, no, or refusal. Adjectives were where the yield claim was going to creep in.
Results
Through the pilot season, 22% of field-days were refusals because a required reading was missing or stale. Every released window in the review cited the stations and forecast fields it used. The output contained no yield figure and no revenue figure. The agronomist still made the spray call.
The result is not a harvest number. It is a morning screen that declines to invent one, and declines to invent a field reading the farm does not have.
What we'd do differently
We would have dated the station map before writing the freshness rules. Freshness on the wrong station is a confident answer about the neighbor's field.