Harvest: from grocery list to local producers
Abstract
Harvest flips local-food search around: instead of browsing directories producer by producer, the user gives their grocery list in natural language, their position and a radius. An agent identifies the requested products, a geospatial query finds the local producers who sell them, and the answer arrives as action-ready cards: address, distance, opening hours, contact. Designed, built and operated by Myelink.
01The problem
Buying local today means browsing directories: producer by producer, page by page, hoping one of them sells what you need. Harvest takes the problem from the consumer's side: you start from the grocery list ("eggs, beef, wheat", or even "I want proteins and carbs"), and the producers are the ones who show up.
02The approach
Three inputs: the list in natural language, the browser's position, an adjustable search radius. An agent translates the user's free-form terms into real catalogue products, writing its own SQL queries against a whitelist of tables. Finding the producers, however, is fully deterministic: a PostGIS geospatial query filters by real distance, aggregates the covered products per merchant and ranks nearest first.
The answer is rendered as producer cards: address, distance, opening hours, phone, website, directions. All in the detected language of the question. The database grows through contributions: submitted producers go through a moderation queue before publication.
03The architecture
Two services: a Django frontend handling accounts, chat sessions and rendering, and a FastAPI service hosting the LangGraph graph. They talk over authenticated REST and share a PostgreSQL/PostGIS database whose schema belongs to the frontend. Conversations keep their memory across turns through Redis checkpoints.
04The design choice
The slowest part of an LLM pipeline is decoding, token by token. Harvest's formatter therefore only generates what needs generating: the detected language, a greeting, and a short description per producer. Everything else, coordinates, addresses, contacts, product lists, is re-attached in Python from the database, byte for byte. The model produces a few percent of the answer; the code guarantees the other 95.
The same discipline applies to guardrails: the agent can only read whitelisted tables, off-topic requests short-circuit the graph through sentinel tags filtered from display, and model output is escaped before any rendering, with injection through malicious content treated as a nominal case.
05The stack
| Layer | Choice |
|---|---|
| Frontend | Django, vanilla ES modules, SSE, browser geolocation |
| Agent | FastAPI + LangGraph, Pydantic structured outputs |
| Geospatial | PostgreSQL + PostGIS: real distance, per-merchant aggregates |
| Memory | Redis checkpoints, conversation persisted across turns |
| Inference | models through an OpenAI-compatible gateway, temperature 0 for matching |
| Observability | Langfuse: tracing and versioned prompt management |
| Quality | around a hundred Python and JavaScript tests, CI on every branch |
06Status
Harvest is in production, operated by Myelink, with producer coverage expanding region by region, fed by moderated contributions.
@software{harvest,
author = {Vinceslas, Medhy},
title = {Harvest: de la liste de courses aux producteurs locaux},
note = {En production, Myelink EURL}
}