"The farm thinks for itself."
Demeter is a fully autonomous, multi-agent AI system for precision hydroponic farm management. It combines reinforcement learning, computer vision, LLM-based reasoning, vector memory, and a physics-based digital twin to monitor, analyze, and act on crop conditions - 24/7, without human intervention.
Built for the Microsoft AI Unlocked - AI for India hackathon, Demeter addresses food security and precision agriculture challenges in the Indian context, with full Hindi language support and a design philosophy accessible to rural operators.
Click here to view the Project Deliverables.
| Dashboard | Analytics | Intelligence |
|---|---|---|
![]() |
![]() |
![]() |
| Alerts | Run Cycle | Hindi Support |
![]() |
![]() |
![]() |
| Crop Details (Overview) | Crop Details (Log) | Light Mode |
![]() |
![]() |
![]() |
| Onboarding 1 | Onboarding 2 | |
![]() |
![]() |
- 7 specialized AI agents collaborating in a structured pipeline
- Contextual Bandit (MARL) for cycle-level strategic goal selection based on historical rewards
- LangGraph state machines for each expert agent with tool-use and retry loops
- Supervisor Agent that synthesizes conflicting expert plans and enforces safety constraints
- Azure OpenAI (GPT-4.1) powering all LLM-based reasoning agents
- Azure Custom Vision for real-time plant disease and pest detection
- CLIP (ViT-B/32) for plant image encoding into the FMU vector
- Custom Contextual Bandit (LinGreedy) for strategic action selection
- RAG pipeline with FastEmbed + Qdrant for domain knowledge retrieval
- Qdrant Vector DB - dual-collection architecture:
Crop_States- FMU snapshots (image + sensor fused vectors)Knowledge_Base- agronomic research documents (RAG)Plant_Biographies_HF- long-term per-crop memory (via Mem0)
- Mem0 - semantic plant biography system backed by Azure OpenAI
- MongoDB - primary structured store for crop state, sensor history, and simulator state
- Multi-batch Digital Twin: FastAPI server that manages one
DigitalTwininstance per crop, all loaded into memory and synced from MongoDB on every request - Simulates pH, EC, water temp, air temp, humidity, VPD, and biomass across all active crops simultaneously
- Hybrid physics + neural residual model (
ResidualPhysicsNet) and image generation - Syncs state to Azure Digital Twins after every action
| Layer | Technology |
|---|---|
| LLM | Azure OpenAI GPT-4.1 |
| Agent Orchestration | LangGraph, LangChain |
| Vision | Azure Custom Vision, CLIP ViT-B/32 (OpenAI) |
| Vector DB | Qdrant |
| Semantic Memory | Mem0 |
| Embeddings | FastEmbed (BAAI/bge-small-en-v1.5), all-MiniLM-L6-v2 |
| Digital Twin | Azure Digital Twins + custom physics sim |
| Backend (Python) | FastAPI, Uvicorn |
| Backend (Node) | Express.js, MongoDB |
| Frontend | React 19, React Router v7, Recharts, Tailwind CSS v3 |
| Physics | PyTorch (ResidualPhysicsNet), NumPy |
| RL | Custom Contextual Bandit (LinGreedy) |
The FMU is the core data structure of Demeter. It is a fused multimodal vector created by the Sentinel system at the start of every cycle:
Image (512Γ512 plant photo)
β CLIP ViT-B/32
[512-dim visual embedding]
+
Sensor Window (pH, EC, temp, humidity, VPD, biomass, ...)
β SensorEncoder (LSTM + linear projection)
[7-dim sensor embedding]
=
FMU Vector [519-dim] ββ stored in Qdrant with full metadata payload
The FMU is stored in Qdrant and becomes the memory of the farm - every past state is retrievable by similarity search.
Each autonomous cycle follows this sequence:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β DEMETER AGENT CYCLE β
β β
β 1. FetchingAgent β
β ββ Polls simulator/ADT β builds FMU β stores in Qdrant β
β β
β 2. JudgeAgent (LangGraph) β
β ββ Retrieves N-1 FMU β runs Azure CV (visual forensics) β
β ββ Queries FarmMemory (Mem0) β deliberates via LLM β
β ββ Files reward score β trains Bandit β
β β
β 3. SupervisorAgent β ContextualBandit β
β ββ Encodes current FMU as context vector (519-dim) β
β ββ Bandit selects 1 of 15 strategies (LinGreedy) β
β ββ Strategy instruction passed to expert agents β
β β
β 4. ResearcherAgent β
β ββ Queries Knowledge_Base (RAG) for crop-specific data β
β β
β 5. AtmosphericAgent (LangGraph) β
β ββ Tools: ask_rag, web_search, calculate_vpd, diagnose_plantβ
β ββ Generates climate action plan (temp/humidity/CO2/light) β
β ββ Simulates plan β retry loop if unsafe β
β β
β 6. WaterAgent (LangGraph) β
β ββ Tools: ask_rag, web_search, calculate_vpd, diagnose_plantβ
β ββ Generates nutrient plan (pH dosing, EC adjustment) β
β ββ Simulates plan β retry loop if unsafe β
β β
β 7. SupervisorAgent β synthesize_plan β
β ββ Merges atmospheric + water plans β
β ββ Detects conflicts, enforces safety bounds β
β ββ Dispatches final FarmAction to Simulator/ADT β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
The Contextual Bandit (agent/Marl/bandit.py) is a LinGreedy (pure-exploitation) contextual bandit that selects from 15 farm management strategies:
| Category | Strategies |
|---|---|
| π’ Passive | MAINTAIN_CURRENT, CALIBRATE_SENSORS |
| π§ Nutrients | AGGRESSIVE_PH_DOWN/UP, GENTLE_PH_BALANCING, INCREASE_EC_VEG/BLOOM, LOWER_EC_FLUSH, CALMAG_BOOST |
| π€οΈ Climate | RAISE_TEMP_HUMIDITY, LOWER_TEMP_HUMIDITY, MAX_AIR_CIRCULATION |
| π Disease | FUNGAL_TREATMENT, PEST_ISOLATION, PRUNE_NECROTIC_LEAVES |
The bandit uses the 519-dim FMU vector as its context, learns reward signals from the JudgeAgent, and persists its model weights to disk (model_bandit_greedy.pkl).
The JudgeAgent is the reward signal generator. After each cycle, it:
- Retrieves the previous FMU (N-1) from Qdrant
- Runs Azure CV-based visual diagnosis on the plant image
- Queries Mem0 for the crop's text biography
- Deliberates via LLM: compares sensor delta, visual report, and history
- Issues a reward score (β1.0 to +1.0) and outcome classification
- Updates Qdrant payload and writes to FarmMemory (Mem0)
- Returns training data β Bandit updates its weights online
The simulator (simulator/main.py) is a FastAPI server managing a fleet of DigitalTwin instances β one per active crop:
- Multi-batch architecture: An in-memory
simulatorsdict mapscrop_id β DigitalTwin. On every request,sync_simulators_from_db()reads MongoDB and instantiates twins for any newly registered crops automatically - Hybrid physics model: First-principles equations for pH, EC, VPD, biomass growth
- Neural residual: A small
ResidualPhysicsNet(PyTorch MLP) that corrects physics approximations - State vector:
[pH, EC, water_temp, air_temp, humidity, VPD, biomass] - Global clock: A
simulator_stateMongoDB collection tracks the global tick; eachGET /simulation/statecall advances it by 1 hour and incrementssimulated_age_hoursfor every crop - Image generation: Outputs plant health images based on a bucket score (0β100)
- Azure Digital Twins sync: Every action call pushes telemetry to the ADT twin (
HydrophonicTank) - Endpoints:
GET /simulation/stateβ returns state for all active cropsPOST /simulation/actionβ accepts a list of{crop_id, action}objects, steps each twin
The frontend is a highly responsive React 19 SPA featuring bilingual support (English/ΰ€Ήΰ€Ώΰ€¨ΰ₯ΰ€¦ΰ₯) for accessibility in Indian agriculture.
| Page | Route | Description |
|---|---|---|
| Landing Page | / |
Hero, live agent activity feed, feature cards, live stats |
| Dashboard | /dashboard |
Crop card grid with health/maturity/stage filters and harvest banner |
| Crop Details | /crop/:id |
Per-crop sensor charts, agent reasoning log, event timeline, actuator commands |
| Add Crop | /add-crop |
Crop registration form: Type, ID, location, notes, sensor IDs, and optional seed photo |
| Run Cycle | /run-cycle/:cropId |
Triggers agent cycle for a specific crop. Streams live logs with phase progress indicator, live sensor readout panel, and actuator command summary |
| Farm Intelligence | /intelligence |
Natural-language RAG search against the agronomic knowledge base |
| Analytics | /analytics |
Multi-chart analytics: pH/EC/temp traces, daily sequences, parameter health scores, per-crop table |
| Alerts | /alerts |
Categorized alert system (CRITICAL/WARNING/INFO/HARVEST) with acknowledge workflow |
| Help | /help |
Farming terms, simple explanations and definitions |
| Settings | /settings |
Theme, language, farm name, notification prefs, onboarding |
The Node.js Express server (backend/node_server/) is the primary CRUD layer for all crop data, backed by MongoDB.
crop_id String (unique, required)
crop String
stage String
sequence_number Number
cycle_duration_hours Number (auto-set per crop type: lettuce/basil=1h, tomato/strawberry=2h)
total_crop_lifetime_days Number
simulated_age_hours Number
planted_at Date
last_updated Date
sensors { pH: [Number], EC: [Number], temp: [Number], humidity: [Number] }
sensor_ids { ph_sensor, ec_sensor, temp_sensor, humidity_sensor }
location String
notes String
image_url String
action_taken Mixed
outcome String
explanation_log String
bandit_action_id Number
strategic_intent String
reward_score Number
visual_diagnosis String
schema_version String (current: "1.2")
| Method | Path | Description |
|---|---|---|
| POST | /api/crops/create |
Register a new crop |
| GET | /api/crops/all |
Retrieve all crops |
| GET | /api/crops/:cropId |
Get a single crop by ID |
| PUT | /api/crops/:cropId |
Partial update |
| DELETE | /api/crops/:cropId |
Remove a crop |
demeter/
βββ agent/
β βββ main_agent.py # Orchestration loop (runs the 7-agent cycle)
β βββ memory.py # FarmMemory class (Mem0 + Qdrant)
β βββ guardrails/
β β βββ README.md # Guardrails documentation
β β βββ validation.py # Input sanitization, bounds checking, injection detection
β βββ model/
β β βββ plant_disease_model.pt # Plant disease detection model
β βββ Marl/
β β βββ bandit.py # Contextual Bandit (LinGreedy, 15 arms)
β β βββ strategies.py # Strategy definitions
β β βββ train-bandit.py # Offline training script
β β βββ model_bandit_greedy.pkl # Trained bandit model weights
β βββ Sentinel/
β β βββ agent.py # FMUBuilder - creates fused vectors
β β βββ fmu.py # FMU dataclass
β β βββ Encoders/
β β βββ Vision.py # CLIP ViT-B/32 image encoder
β β βββ TimeSeries.py # LSTM-based sensor encoder
β βββ Qdrant/
β β βββ Client.py # Qdrant client singleton
β β βββ Setup.py # Collection initialization
β β βββ Store.py # FMU storage helpers
β β βββ Search.py # Similarity search helpers
β βββ sub_agents/
β β βββ base_agent.py # BaseReasoningAgent (Azure OpenAI client)
β β βββ fetching_agent.py # FetchingAgent - polls simulator, builds FMU
β β βββ judge_agent.py # JudgeAgent - reward evaluation (LangGraph)
β β βββ atmospheric_agent.py # AtmosphericAgent - climate planning (LangGraph)
β β βββ water_agent.py # WaterAgent - nutrient planning (LangGraph)
β β βββ Supervisor.py # SupervisorAgent - strategy + synthesis
β β βββ Researcher.py # ResearcherAgent - RAG knowledge retrieval
β β βββ Explainer.py # ExplainerAgent - chain-of-thought log generation
β β βββ Doctor.py # VisionAgent - plant disease detection (Azure Custom Vision)
β β βββ water_and_atmospheric_dependencies/
β β βββ state.py # LangGraph AgentState definition
β β βββ nodes.py # LangGraph node functions
β β βββ tools.py # LangChain tools (calculate_vpd, web_search)
β β βββ physics_engine.py # LLM-based plan safety simulator
β β βββ retrieval.py # LangChain tools (ask_rag, diagnose_plant, ask_memory)
β βββ tools/
β βββ actuation.py # Actuator command builders
β βββ db_tools.py # Database utility tools
β βββ processing_tools.py # Sensor processing utilities
β βββ reset_memory.py # Memory reset utility
β
βββ backend/
β βββ server/
β β βββ main.py # FastAPI server (Python) - agent HTTP endpoints
β β βββ functions.py # Backend utility functions
β β βββ rag_brain.py # PDF ingestion pipeline for Knowledge Base
β β βββ create-index.py # Qdrant index setup script
β β βββ reset-db.py # Database reset utility
β βββ node_server/
β βββ index.js # Express.js server - crop CRUD API + MongoDB init
β βββ routes/
β β βββ farmRoutes.js # Farm/Qdrant history routes
β β βββ cropRoutes.js # Crop CRUD routes
β βββ controllers/
β β βββ farmController.js
β β βββ cropController.js
β βββ schema/
β β βββ cropSchema.js # Mongoose schema (v1.2)
β βββ config/db.js # MongoDB + legacy DB connection
β
βββ frontend/
β βββ src/
β β βββ App.js # Router, providers, onboarding gate
β β βββ pages/ # All 10 page components
β β βββ components/ # Sidebar, AgentWidgets, Onboarding
β β βββ hooks/ # useFarmData, useSettings, useTranslation
β β βββ api/
β β β βββ agentApi.js
β β β βββ farmApi.jsx # MongoDB CRUD calls
β β βββ utils/ # translations.js, dataUtils.js
β β βββ data/mockData.js # Mock data for testing
β βββ tailwind.config.js
β
βββ simulator/
β βββ main.py # Multi-batch DigitalTwin fleet + Azure ADT sync
β
βββ yolov8n.pt # Pre-trained YOLOv8 model
βββ Knowledge_Base/ # Drop agronomic PDFs here for RAG ingestion
βββ requirements.txt
βββ README.md
- Python 3.10+
- NodeJS 18+
- A running Qdrant instance (local Docker or Qdrant Cloud)
- Azure OpenAI resource with GPT-4.1 deployment
- MongoDB instance (local or Atlas)
- (Optional) Azure Digital Twins instance
git clone https://github.com/maydayv7/demeter.git
cd demeter
pip install -r requirements.txtCreate a .env file in the project root:
# Azure OpenAI
AZURE_OPENAI_API_KEY=your_azure_openai_key
AZURE_OPENAI_ENDPOINT=https://your-resource.openai.azure.com/
AZURE_OPENAI_DEPLOYMENT_NAME=gpt-4.1
AZURE_OPENAI_API_VERSION=2024-12-01-preview
# Qdrant
QDRANT_URL=http://localhost:6333
QDRANT_API_KEY=your_qdrant_api_key # Only needed for Qdrant Cloud
# Azure Custom Vision
AZURE_API_KEY=your_azure_api_key
AZURE_ENDPOINT=your_azure_endpoint
AZURE_PROJECT_ID=your_azure_project_id
AZURE_PREDICTION_KEY=your_azure_prediction_key
AZURE_URL=your_azure_url
AZURE_ITERATION_NAME=DemeterDoctor
DATASET_FOLDER="train"
# Simulator
SIMULATOR_STATE_URL=http://localhost:8001/simulation/state
SIMULATOR_ACTION_URL=http://localhost:8001/simulation/action
SIMULATOR_PORT=8001
# Azure Digital Twins
ADT_URL=your-adt-instance.digitaltwins.azure.net
# Backend
PORT=3001
MONGODB_URI=your_mongodb_connection_string
# Frontend
REACT_APP_AGENT_API_URL=http://localhost:8000
REACT_APP_FARM_API_URL=http://localhost:3001/apiOption A: Local Docker (Recommended for development)
docker run -p 6333:6333 -p 6334:6334 qdrant/qdrantOption B: Cloud Qdrant
- Sign up at cloud.qdrant.io
- Create a cluster and update your
.envwith the provided URL and API key
Run the following command from the root directory to create the required Qdrant collections and indexes:
python backend/server/create-index.pyMongoDB collections are created automatically on first use by the simulator.
Place agronomic PDFs in the Knowledge_Base/ folder, then run:
python backend/server/rag_brain.pyOtherwise, download model_bandit_greedy.pkl and place it inside the agent/Marl directory.
python simulator/main.py
# Runs on http://localhost:8001Download plant_disease_model.pt and place it inside the agent/model directory.
# Python FastAPI server
python backend/server/main.py
# NodeJS Express server
cd backend/node_server
npm install && npm startcd frontend
npm install
npm start
# Runs on http://localhost:3000python agent/main_agent.py












