Inspiration

Every federal food recall notice carries a column headed Facilities that Received Affected Products. On the Idaho Foodbank recall of July 2017, that column reads:

Mobile pantries. Community meal sites. School Pantries. Senior centers.

The recalled food went to the places people go when they have run out of options. The notice's instruction to whoever received it is to throw it away immediately, which assumes somebody tells them.

Best By is the somebody. It watches the live openFDA feed against a pantry's shelves, produces the pull list, and calls the households that already took some home.

The reason nobody does this by hand is in the data. A recall names its product by lot code, typed into one free text field:

{
  "recall_number": "F-1170-2024",
  "product_description": "H&NATURAL 2 PACK! BRAZIL SEED 60 PIECES, 5 GRAMS PER BOX",
  "code_info": "No Lot code on label. Expiration date listed as 05/24 and 03/24.",
  "classification": "Class I"
}
Across 614 open FDA food enforcement reports Share
Publish a parseable lot code 45.7%
Publish a parseable UPC 12%
Name nothing checkable at all 27.0%

Source: api.fda.gov/food/enforcement.json, pulled 2026-09-14, n=614 open reports.

A pantry cannot match a shelf against that. Neither could we, so we stopped trying.

What it does

The inversion: instead of recovering a lot code weeks later from a record that never carried one, the code is captured at the loading dock. A volunteer photographs the case label once, while the food is in their hands, and a vision model reads the code off the picture. Weeks later, when the notice arrives, matching is exact rather than hopeful.

Then every hit splits into two different jobs, because they are done by different people at different urgencies:

Job Who does it What it looks like
Still on the shelf a volunteer, walking the aisle a printed pull sheet grouped by storage bay
Already went home the coordinator, on the phone a notice to named households, held until approved

The second job is the one that protects people, and it is the one no spreadsheet does.

The console is built for the floor rather than for a dashboard. The pull sheet groups by bay, sets the lot code large enough to compare against a stamped can, and carries a sign-off block for who pulled it and how many units came back. It refuses to double count: two recalls naming the same intake lot are one trip to the bay, so what looks like 345 units across 9 lots is really 261 units across 3.

Every notice records its delivery mode and its intended recipient on the case, so a coordinator can always tell which households were reached and which still need a phone call. The roster in this build is representative, on a domain the project controls.

How we built it

Notifying a household is irreversible. Frightening someone about food they never received is the failure that teaches a pantry to ignore the tool forever, so the path to it is gated twice.

The engine decides. The agent reads the label.

  • NotifyVeto, a Strands BeforeToolCallEvent hook, cancels notify_households unless the engine returned a confirmed lot match with a distribution record behind it.
  • approval_gate, a Strands HumanInTheLoop intervention configured allowed_tools=["*", "!notify_households"], means a coordinator approves before any household is contacted.
  • The vision read is structured output, and it reports an unreadable photo as unreadable rather than guessing a code.

Lambda runs the unattended pass, EventBridge Scheduler runs it daily, DynamoDB holds the cases, S3 holds the disposal record a pantry can hand an inspector, and SES sends from a DKIM-verified domain. Strands is model agnostic, so the model provider is one config line.

Challenges we ran into

A rerun tried to re-notify ten households. The scheduled pass rebuilds every case from the feed, and a case that had already notified ten households came back as awaiting approval while still holding its ten real SES message ids. Approving it again would have sent all ten a second notice. Terminal states are now terminal, and the test that proves it fails the moment the guard is removed.

The vision model fabricated a barcode. On a 240px image it produced three different confident wrong readings. Small images are upscaled before the model sees them, and the unreadable case now asks for a better photo. An invented lot code is a false claim against a real company.

Naive sums double counted the work. Several recalls name the same intake lot, and a volunteer walks to the bay once. Summing units across cases said 345 units and 9 lots; deduplicating by lot id gave the truth, 261 units and 3 lots. A pull sheet that overstates the work is a pull sheet nobody finishes.

Accomplishments that we're proud of

The delivery states are honest by construction. A notice that reached a household renders as reached; anything else renders in its own colour with both addresses named, and the success state is withheld while any household on a closed case is still unreached. The product can always tell you what it did rather than what it intended.

124 tests pass from a clean clone with no credentials and no network.

What we learned

The useful artifact is not a dashboard. It is a sheet of paper a volunteer can carry down an aisle and tick.

What's next for Best By

SES production access. Intake photography from a phone rather than a laptop. And the pantry network above a single pantry, because a recall almost never stops at one.

Built With

Share this project:

Updates

Submission history