cd /news/ai-agents/open-source-agricultural-os-offline-… Β· home β€Ί topics β€Ί ai-agents β€Ί article
[ARTICLE Β· art-15772] src=github.com pub= topic=ai-agents verified=true sentiment=↑ positive

Open-source agricultural OS,offline-first,AGPL, grow tent to 500-warehouse scale

An open-source agricultural operating system called gr33n has shipped its Guardian agent layer and crop intelligence modules, enabling offline-first farm management from a single grow tent to 500-warehouse scale. The AGPL-licensed system uses PostgreSQL schemas, Go APIs, Vue dashboards, and Raspberry Pi clients to operate without permanent internet connections or third-party servers. The project aims to reclaim farmer data sovereignty from big agriculture and cloud landlords by providing decentralized tools that work on solar power or mesh networks.

read29 min publishedMay 27, 2026

An open-source agricultural operating system designed to reclaim data, land, and autonomy.

Current focus: Phase 29 β€” Guardian agent layer is shipped on main (

plan): global slide-out drawer, rule-assisted propose→confirm for alert ack/read, audit + RBAC, contextual

Ask Guardian entry points, demo seed alerts, and

OpenAPI 0.4.0.

Phase 28 β€” crop intelligence & Guardian depth is also

shipped(

plan).

Phase 30(Guardian change-request PR queue β€” config + Pi via confirm) is the natural next slice β€”

plan.

Pi / edge field validation(Phase 31) remains a parallel activity: real Pi or MQTT bridge with

PI_API_KEY

, base64-decode config

from GET /farms/{id}/devices

, then confirm readings and (

actuator_events

,

pi_client/gr33n_client.py

,

docs/pi-integration-guide.md

). Key playbooks:

cmd/api/smoke_pi_contract_test.go

,

docs/workflow-guide.md

,

docs/farm-guardian-architecture.md

,

docs/mqtt-edge-operator-playbook.md

,

docs/farm-guardian-ollama-setup.md

,

docs/local-operator-bootstrap.md

,

docs/insert-commons-pipeline-runbook.md

,

docs/insert-commons-receiver-playbook.md

,

docs/notifications-operator-playbook.md

,

docs/domain-modules-operator-playbook.md

,

docs/mobile-distribution.md

,

docs/audit-events-operator-playbook.md

,

docs/terminology-guideline.md

,

docs/phase-13-operator-documentation.md

.

docs/phase-14-operator-documentation.md

gr33n is a modular, scalable, and decentralized farm management system built for real humans β€” not cloud landlords. Whether you're managing a homestead on solar or automating thousands of acres, gr33n adapts to your size, ethics, and bandwidth.

It's PostgreSQL schemas + Go APIs + Vue dashboards + Raspberry Pi clients + shared insert statements.

But more than that: it's a political stance in schema form.

"If your DNA, soil, labor, and climate data feed trillion-dollar industries β€” and you're not seeing a dime β€” that's not tech, that's extraction."

This project exists because:

  • Big Ag is closing the loop on food systems, and we're cracking it back open.
  • Data rights matter β€” even your soil and sunlight deserve consent.
  • Billionaires shouldn't profit off your greenhouse or genome without giving back.
  • Farmers, tinkerers, and off-gridders deserve tools that don't call home.

gr33n will never require a permanent internet connection, forced login, or hidden check-in with third-party servers. Whether you're on an island, a mountaintop, or a mesh-netted greenhouse, gr33n works where you live, without compromise.

Modularityβ€” Each ag domain (crops, animals, natural-farming inputs, IoT sensors) lives in its own schema. Use what you need, prune the rest. Enable modules per-farm viagr33ncore.farm_active_modules

. - Connectivity Optionalβ€” Works offline, intranet-only, or online. Supports Supabase or bare-metal Postgres with TimescaleDB/PostGIS. - Automation-Readyβ€” Schedule tasks, trigger actuators, run AI models β€” or run it all manually. Your tech, your tempo. - Insert Commons (farm-side sender)β€” Per-farm opt-in in Settings;POST /farms/{id}/insert-commons/sync

buildscoarse, pseudonymous aggregates and optionally POSTs them toINSERT_COMMONS_INGEST_URL

with optionalAuthorization: Bearer <INSERT_COMMONS_SHARED_SECRET>

. Sync attempts are persisted (GET /farms/{id}/insert-commons/sync-events

) withidempotency keys,** rate limits**, and** server-side backoffafter repeated delivery failures. A separate farm audit trail**records sensitive actions (membership, opt-in, sync attempts, finance COA changes, cost exports, receipt access, and more) for owner/manager review viaGET /farms/{id}/audit-events

(see). For self-hosted pilots, an optionaldocs/audit-events-operator-playbook.md

receiver process (cmd/insert-commons-receiver

,make run-receiver

) validates payloads, enforces the shared secret, dedupes on payload hash, and stores rows in Postgres β€” seeand migrationdocs/insert-commons-receiver-playbook.md

db/migrations/20260417_phase13_insert_commons_receiver.sql

. Applydb/migrations/20260415_phase11_rbac_receipts_commons.sql

anddb/migrations/20260416_phase12_insert_commons_federation.sql

on existing databases.Custom clients POSTing ingest JSON themselves must use theexact documented shape (only six top-level keys, completeaggregates

children, booleanincludes_pii

) or validation returns400β€” see(docs/insert-commons-pipeline-runbook.md

Custom senders).

Layer Technology
API Go 1.25 Β· net/http stdlib
Database PostgreSQL 14+ Β· TimescaleDB Β· PostGIS
Query layer sqlc (generated β€” do not edit internal/db/ )
Frontend Vue 3 Β· Vite Β· Pinia Β· Tailwind CSS
Pi client Python 3 Β· RPi.GPIO / smbus2
Auth Supabase (hosted) / local peer auth (dev)
Schema Multi-schema PostgreSQL β€” gr33ncore + gr33nnaturalfarming
gr33n/
β”œβ”€β”€ scripts/
β”‚   β”œβ”€β”€ bootstrap-local.sh             # Schema, migrations, npm ci, .env from example
β”‚   β”œβ”€β”€ setup-first-clone.sh           # First clone (+ optional --install-system-deps)
β”‚   β”œβ”€β”€ install-system-deps-debian.sh # Debian/Ubuntu: sudo apt Postgres+Node (not Go)
β”‚   └── install-pi-edge-deps.sh       # Raspberry Pi OS: sudo apt for pi_client (+ optional Docker)
β”œβ”€β”€ cmd/api/
β”‚   β”œβ”€β”€ main.go              # Entry point, DB pool, server startup
β”‚   β”œβ”€β”€ routes.go            # All HTTP route registrations
β”‚   └── cors.go              # CORS middleware
β”œβ”€β”€ cmd/insert-commons-receiver/
β”‚   └── main.go              # Optional pilot ingest service for Insert Commons (`POST /v1/ingest`, `GET /v1/stats`)
β”œβ”€β”€ internal/
β”‚   β”œβ”€β”€ db/                  # sqlc-generated query layer (DO NOT EDIT)
β”‚   β”œβ”€β”€ handler/
β”‚   β”‚   β”œβ”€β”€ farm/            # GET /farms/:id
β”‚   β”‚   β”œβ”€β”€ zone/            # Zones CRUD
β”‚   β”‚   β”œβ”€β”€ sensor/          # Sensors CRUD + readings endpoints
β”‚   β”‚   β”œβ”€β”€ device/          # Devices CRUD + status toggle
β”‚   β”‚   └── task/            # Tasks list + status update
β”‚   β”œβ”€β”€ httputil/            # WriteJSON / WriteError helpers
β”‚   β”œβ”€β”€ insertcommonsreceiver/ # Optional Insert Commons ingest HTTP handler
β”‚   └── platform/
β”‚       └── commontypes/     # Shared enum types for sqlc
β”œβ”€β”€ db/
β”‚   β”œβ”€β”€ schema/
β”‚   β”‚   └── gr33n-schema-v2-FINAL.sql   # Full PostgreSQL schema (source of truth)
β”‚   β”œβ”€β”€ seeds/
β”‚   β”‚   └── master_seed.sql             # Demo farm: natural-farming inventory + JADAM-style inputs (v1.005)
β”‚   └── queries/             # sqlc SQL source files
β”œβ”€β”€ ui/                      # Vue 3 frontend
β”‚   └── src/
β”‚       β”œβ”€β”€ views/           # Dashboard, Zones, Sensors, Actuators, Schedules, Inventory
β”‚       β”œβ”€β”€ stores/farm.js   # Pinia store β€” all API state
β”‚       β”œβ”€β”€ api/index.js     # Axios instance β†’ localhost:8080
β”‚       └── router/index.js  # Vue Router
β”œβ”€β”€ pi_client/
β”‚   β”œβ”€β”€ gr33n_client.py      # Sensor daemon β€” reads GPIO, POSTs readings to API
β”‚   β”œβ”€β”€ config.yaml          # Per-node hardware mapping
β”‚   β”œβ”€β”€ gr33n.service        # systemd unit for autostart
β”‚   └── setup.sh             # One-time Pi bootstrap
β”œβ”€β”€ sqlc.yaml
β”œβ”€β”€ go.mod / go.sum
β”œβ”€β”€ openapi.yaml             # Full API spec (paste into editor.swagger.io for live UI)
β”œβ”€β”€ INSTALL.md
β”œβ”€β”€ ARCHITECTURE.md
└── SECURITY.md

First time after git clone: run

(or

./scripts/setup-first-clone.sh

) β€” it pulls Go deps, creates

make first-clone

.env

/ ui/.env

from examples, runs to load schema and

scripts/bootstrap-local.sh

npm ci

in ui/

. On Debian/Ubuntu,

(

./scripts/setup-first-clone.sh --install-system-deps

make first-clone-install-deps

) runs first (Postgres 16 + extensions + Node 22; Go still from

sudo apt

go.dev/dl). Otherwise you must have Postgres with TimescaleDB, PostGIS, and pgvector available first (native),

oruse

for the Compose database. Step-by-step:

./scripts/setup-first-clone.sh --docker

docs/local-operator-bootstrap.md. How the database is actually defined (ignore stale ERDs):

docs/database-schema-overview.md.

Full setup in INSTALL.md. Short manual version:

git clone https://github.com/dgang0404/gr33n.git
cd gr33n

sudo -u postgres psql -c "CREATE DATABASE gr33n;"
psql -d gr33n -f db/schema/gr33n-schema-v2-FINAL.sql

psql -d gr33n -f db/seeds/master_seed.sql

cp .env.example .env   # once: edit .env with DATABASE_URL, JWT_SECRET, PI_API_KEY if using auth
go run -tags dev ./cmd/api/

cd ui && npm install && npm run dev

API β†’ http://localhost:8080

UI β†’ http://localhost:5173

You do not need to re-clone or re-seed every time. From the repo root:

make restart-local-serve   # starts Postgres (Compose), waits, sanity-checks, then API + UI

Or step by step:

make restart-local           # Postgres only + db sanity report
make dev-auth-test           # API + UI in separate jobs (JWT login like production)

Details: docs/local-operator-bootstrap.md. First cold

go run

after reboot can take several minutes β€” pre-build with go build -tags dev -o ./bin/api ./cmd/api/

if you want faster restarts.Receipt storage defaults to local disk for development:

FILE_STORAGE_BACKEND=local

FILE_STORAGE_DIR=./data/files

Production deployments can switch receipts to S3-compatible object storage by setting:

FILE_STORAGE_BACKEND=s3

S3_BUCKET=<bucket>

S3_REGION=<region>

  • optional: S3_ENDPOINT=<custom endpoint>

for MinIO / R2 / other S3-compatible providers - optional: S3_PREFIX=<key prefix>

  • optional: S3_ACCESS_KEY_ID

andS3_SECRET_ACCESS_KEY

  • optional: S3_USE_PATH_STYLE=true

  • optional: S3_DISABLE_HTTPS=true

for local/test endpoints only - optional: FILE_STORAGE_SIGNED_URL_TTL_SECONDS=300

for short-lived receipt download links

To backfill existing blobs from an old local FILE_STORAGE_DIR

into the configured target backend before cutover:

go run ./cmd/filebackfill --source-dir /path/to/old/files --dry-run

go run ./cmd/filebackfill --source-dir /path/to/old/files
go run ./cmd/filebackfill --source-dir /path/to/old/files --file-type cost_receipt

The backfill preserves each attachment's existing storage_path

, so DB rows do not change. After the copy is complete, switch the API to the new FILE_STORAGE_BACKEND

and verify a few receipt downloads before removing the old local storage.

For operator guidance on receipt storage cutover plus DB/blob backup and restore, see docs/receipt-storage-cutover-runbook.md

.

Phase 12 adds an offline write queue for the Tasks workflow (create task

and advance status

):

  • when offline (or on retryable network failure), task writes are queued locally
  • queued items are marked in the Tasks UI
  • each queued item can be retried or discarded
  • queued writes auto-sync on reconnect, and manual Sync now

is available - non-retryable server failures are shown as stale/conflict items for operator review

Install/offline notes:

  • install the app from your browser for field use (PWA)
  • keep one online sync checkpoint before long offline sessions
  • after reconnect, verify queued writes drained before ending a shift

For Play Store / App Store / MDM distribution without replacing the PWA, use the optional Capacitor scaffold in ui/

(npm run build:cap

, cap:sync

, platform add/open). See docs/mobile-distribution.md.

Base URL: http://localhost:8080

β€” authoritative request/response schemas in openapi.yaml. Path placeholders use :id

, :rid

, :uid

, :iid

for readability (the server matches the same paths with {id}

style).

Method Path Description
GET /health
API + DB health check
POST /auth/login
Authenticate & receive JWT
POST /auth/register
Register a new account or set password for an invited user (existing email with no password yet)
GET /auth/mode
Current auth mode (dev / production / auth_test)
GET /capabilities
Feature flags β€” {"ai_enabled": bool} . Read by the UI at startup to gate Farm Guardian / Knowledge Ask-LLM.

Header: X-API-Key: <PI_API_KEY>

(see env configuration for the API process).

Method Path Description
POST /sensors/:id/readings
Pi posts a sensor reading
PATCH /devices/:id/status
Pi heartbeat / status update
POST /actuators/:id/events
Pi reports executed command
DELETE /devices/:id/pending-command
Pi clears pending command after execution

Farm API POSTs JSON to INSERT_COMMONS_INGEST_URL

; this repo’s pilot receiver (go run ./cmd/insert-commons-receiver/

or make run-receiver

) listens on INSERT_COMMONS_RECEIVER_LISTEN

(default ** :8765**) and implements:

Method Path Description
GET /health
Process liveness
GET /v1/stats
Pilot aggregate counts (pseudonyms, daily ingests, retention) β€” same Bearer auth as ingest
POST /v1/ingest
Validate payload, optional Authorization: Bearer <INSERT_COMMONS_SHARED_SECRET> , optional Gr33n-Idempotency-Key (forwarded from farm sync), persist idempotently

Details, migration, and retention: docs/insert-commons-receiver-playbook.md. If you build or forward JSON manually, match the farm API’s ingest schema (no extra top-level fields; full

aggregates

; privacy.includes_pii

as JSON boolean); GET /farms/:id/insert-commons/preview

returns a valid example body β€” full rules in .

docs/insert-commons-pipeline-runbook.md

Header: Authorization: Bearer <JWT>

(SSE also supports ?token=

on the stream URL where documented).

Farm access: most /farms/:id/...

routes require the user to be the farm owner or a member (gr33ncore.farm_memberships

). Role caps apply per area (for example view vs edit costs, operate for field workflows, admin for farm settings and membership). Exact checks live in internal/farmauthz

and in openapi.yaml per route.

Integration tests under cmd/api/

(TestMain

in cmd/api/smoke_test.go) spin up an

httptest

server with and a real JWT login flow. They need

AUTH_MODE=auth_test

Postgres at

(schema + migrations;

DATABASE_URL

master seed recommended). Env, CI behavior, and data-dependent skips:

.

docs/local-operator-bootstrap.md

Method Path Description
PATCH /auth/password
Change password (must be logged in)
GET /profile
Current user profile
PUT /profile
Update current user profile
GET /units
List all measurement units
Method Path Description
GET /farms
List farms; use ?user_id=<uuid> to restrict to that user’s farms (recommended for UIs). If omitted, lists all farms β€” use only in trusted operator contexts.
POST /farms
Create farm
GET /farms/:id
Farm detail (member or owner)
PUT /farms/:id
Update farm record (admin: owner or manager)
DELETE /farms/:id
Soft-delete farm (admin)
Method Path Description
GET /farms/:id/members
List members and roles
POST /farms/:id/members
Invite or add member (email , role_in_farm , optional full_name )
PATCH /farms/:id/members/:uid/role
Change member role (:uid = user UUID)
DELETE /farms/:id/members/:uid
Remove member from farm
Method Path Description
PATCH /farms/:id/insert-commons/opt-in
Toggle Insert Commons aggregate sharing (admin)
GET /farms/:id/insert-commons/preview
Preview validated ingest JSON only β€” no sync, no history (admin)
POST /farms/:id/insert-commons/sync
Build aggregates and POST to INSERT_COMMONS_INGEST_URL when set (admin or finance)
GET /farms/:id/insert-commons/sync-events
Paginated sync attempt history (admin or finance / anyone with cost view)
GET /farms/:id/audit-events
Sensitive-action audit log (admin only; query limit , offset )
Method Path Description
GET /farms/:id/zones
List zones for farm
GET /zones/:id
Zone detail
POST /farms/:id/zones
Create zone
PUT /zones/:id
Update zone
DELETE /zones/:id
Delete zone
Method Path Description
GET /farms/:id/devices
List devices
GET /devices/:id
Device detail
POST /farms/:id/devices
Create device
DELETE /devices/:id
Delete device
GET /farms/:id/actuators
List actuators for farm
PATCH /actuators/:id/state
Update actuator state (dashboard)
GET /actuators/:id/events
Actuator event history
Method Path Description
GET /farms/:id/sensors
List sensors
GET /farms/:id/sensors/stream
SSE live sensor readings (JWT may be passed as query token )
GET /sensors/:id
Sensor detail
POST /farms/:id/sensors
Create sensor
DELETE /sensors/:id
Delete sensor
GET /sensors/:id/readings/latest
Latest reading
GET /sensors/:id/readings
List readings (since , until , limit , …)
GET /sensors/:id/readings/stats
Aggregate stats for a time range
Method Path Description
GET /farms/:id/schedules
List schedules
PATCH /schedules/:id/active
Toggle schedule active
GET /farms/:id/automation/runs
List automation runs for farm
GET /schedules/:id/actuator-events
Actuator events triggered by schedule
GET /automation/worker/health
Automation worker health
Method Path Description
GET /farms/:id/tasks
List tasks
POST /farms/:id/tasks
Create task
PATCH /tasks/:id/status
Update task status
Method Path Description
GET /farms/:id/fertigation/reservoirs
List reservoirs
POST /farms/:id/fertigation/reservoirs
Create reservoir
PATCH /fertigation/reservoirs/:rid
Update reservoir
DELETE /fertigation/reservoirs/:rid
Delete reservoir
GET /farms/:id/fertigation/ec-targets
List EC targets
POST /farms/:id/fertigation/ec-targets
Create EC target
GET /farms/:id/fertigation/programs
List programs
POST /farms/:id/fertigation/programs
Create program
PATCH /fertigation/programs/:rid
Update program
DELETE /fertigation/programs/:rid
Delete program
GET /farms/:id/fertigation/events
List fertigation events (?crop_cycle_id= optional)
POST /farms/:id/fertigation/events
Create fertigation event (optional crop_cycle_id )
Method Path Description
GET /farms/:id/crop-cycles
List crop cycles
POST /farms/:id/crop-cycles
Create crop cycle
GET /crop-cycles/:id
Get crop cycle
PUT /crop-cycles/:id
Update crop cycle
DELETE /crop-cycles/:id
Deactivate crop cycle
PATCH /crop-cycles/:id/stage
Update growth stage
Method Path Description
GET /farms/:id/costs/summary
Cost totals (income, expenses, net)
GET /farms/:id/costs
List cost transactions (limit , offset , …)
GET /farms/:id/costs/export
Download CSV (format=csv or format=gl_csv )
GET /farms/:id/finance/coa-mappings
List COA mappings for GL export
PUT /farms/:id/finance/coa-mappings
Save COA mapping overrides
DELETE /farms/:id/finance/coa-mappings
Reset all COA overrides
DELETE /farms/:id/finance/coa-mappings/:category
Reset one category override
POST /farms/:id/costs
Create cost transaction
PUT /costs/:id
Update cost transaction
DELETE /costs/:id
Delete cost transaction
POST /farms/:id/cost-receipts
Upload cost receipt (multipart: file , optional cost_transaction_id )
GET /file-attachments/:id/content
Inline file bytes (cost receipt when linked)
GET /file-attachments/:id/download
Presigned or proxied download URL JSON (backend-dependent)
Method Path Description
GET /farms/:id/alerts
List alerts for farm
GET /farms/:id/alerts/unread-count
Unread count
PATCH /alerts/:id/read
Mark alert read
PATCH /alerts/:id/acknowledge
Acknowledge alert

AI_ENABLED=true

required; LLM_BASE_URL

  • LLM_MODEL

required for the chat endpoint. POST /v1/chat

returns 503 in Lite mode and 429 when rolling-window cost guards fire (CHAT_COST_MAX_TOKENS_PER_USER

/ CHAT_COST_MAX_TOKENS_PER_FARM

).

Method Path Description
POST /v1/chat
Send a message to Farm Guardian. Optional farm_id β†’ RAG grounding + live snapshot. Optional session_id (UUID) for multi-turn context replay. Optional "stream": true for SSE streaming. Response includes answer , grounded , citations , session_id , turn_index , prompt_tokens , completion_tokens .
GET /v1/chat/sessions
List recent conversation sessions (up to 50, latest-first).
GET /v1/chat/sessions/:id
Full ordered turn history for a session.
PATCH /v1/chat/sessions/:id
Rename session ({"title": "..."} , empty string clears).
DELETE /v1/chat/sessions/:id
Delete session and all its turns.
GET /v1/chat/usage
Rolling-window token budget dashboard (per-user; optional ?farm_id= for per-farm). Settings β†’ Guardian usage card.
Method Path Description
GET /crop-cycles/:id/summary
Per-cycle fertigation + cost + yield + stage history (JSON).
GET /crop-cycles/:id/summary.csv
Same data, flat CSV row.
GET /farms/:id/crop-cycles/compare?ids=1,2,3
Side-by-side compare (up to 5 cycles).
GET /farms/:id/crop-cycles/compare.csv
Compare as CSV (one row per cycle).

pgvector

  • embeddings required for search; AI_ENABLED=true

  • LLM configured required for answer synthesis.

Method Path Description
POST /farms/:id/rag/search
Semantic nearest-neighbour search over farm knowledge chunks.
POST /farms/:id/rag/answer
Retrieve top-K chunks then synthesise an LLM answer (Lite mode: 503 for synthesis; search still works).
Method Path Description
GET /farms/:id/naturalfarming/inputs
List input definitions
POST /farms/:id/naturalfarming/inputs
Create input definition
PUT /naturalfarming/inputs/:id
Update input definition
DELETE /naturalfarming/inputs/:id
Delete input definition
GET /farms/:id/naturalfarming/batches
List input batches
POST /farms/:id/naturalfarming/batches
Create input batch
PUT /naturalfarming/batches/:id
Update input batch
DELETE /naturalfarming/batches/:id
Delete input batch
Method Path Description
GET /farms/:id/naturalfarming/recipes
List application recipes
POST /farms/:id/naturalfarming/recipes
Create recipe
GET /naturalfarming/recipes/:id
Get recipe
PUT /naturalfarming/recipes/:id
Update recipe
DELETE /naturalfarming/recipes/:id
Delete recipe
GET /naturalfarming/recipes/:id/components
List recipe components
POST /naturalfarming/recipes/:id/components
Add component
DELETE /naturalfarming/recipes/:id/components/:iid
Remove component (:iid = component row id)

The master seed loads a demo farm (farm_id = 1

, gr33n Demo Farm) with natural-farming inventory and JADAM-style input names (JMS, JLF, …), photoperiod schedules, fertigation events, crop cycles, and automation β€” verified clean against the live schema:

Table Rows Contents
farms
1 gr33n Demo Farm
zones
3 Veg Room, Flower Room, Outdoor Garden
crop_cycles
3 Veg canopy (18/6), Flower run (12/12), Outdoor raised beds
sensors
10 PAR, lux, temp, humidity, EC, pH, CO2, soil moisture
input_definitions
15 JMS, LAB, FPJ, FFJ, OHN, JHS, WCA, WCS, JWA, JS, JLF variants, compost tea
application_recipes
14 Soil drenches, foliar sprays, pest control, fungicide
recipe_components
20 Input-to-recipe links with dilution ratios
schedules
14 Light (24/0, 18/6, 16/8, 12/12) + watering programs per grow stage
automation_rules
7 Automated light on/off rules per grow stage

Apply once: make seed

or psql -d gr33n -f db/seeds/master_seed.sql

.

Farm Guardian needs a RAG corpus too. The seed loads operational rows (zones, cycles, NF inputs, …) but does not pre-populate gr33ncore.rag_embedding_chunks

. After seeding, run ** make rag-ingest-demo** (or

for wipe + seed + ingest):

make dev-stack-fresh-rag

make rag-ingest-demo   # needs EMBEDDING_API_KEY in .env; skips cleanly if unset
make dev-stack-fresh-rag

See docs/farm-guardian-architecture.md for the three knowledge layers (Llama weights + RAG corpus + live snapshot).

Smoke-test pollution: Running make test

against a long-lived dev DB accumulates junk rows. For a clean Guardian demo, use ** make dev-stack-fresh** or

. For day-to-day migration updates on an existing DB,

make dev-stack-fresh-rag

is idempotent.

make dev-stack

make help       # Show all targets
make bootstrap-local  # Guided DB + env + UI deps (see docs/local-operator-bootstrap.md)
make bootstrap-local-docker  # Same, but start stack with docker compose
make compose-db-up   # Postgres only β€” docker-compose db (Timescale + pgvector); pair .env DATABASE_URL with INSTALL.md Β§2 / .env.example
make dev-stack       # Idempotent: migrations + seed on existing DB (auto-skips schema)
make dev-stack-fresh # Wipe Compose volume + full bootstrap + seed (clean Guardian demo)
make dev-stack-fresh-rag  # Same + rag-ingest demo farm when EMBEDDING_API_KEY is set
make rag-ingest-demo   # Index farm_id=1 only (skip message if no embedding key)
make local-up        # dev-stack then API + UI (same as ./scripts/dev-stack.sh --serve)
make restart-local   # After reboot: Compose db + wait + sanity report (no migrations)
make restart-local-serve  # restart-local then API + UI (make dev-auth-test)
make check-stack     # Verify DATABASE_URL + pgvector + optional API /health (see docs/local-operator-bootstrap.md)
make run        # Run the API server
make run-receiver # Run optional Insert Commons receiver (see docs/insert-commons-receiver-playbook.md)
make dev        # Run API + UI dev server in parallel
make ui         # Run the Vue dev server
make build      # Build the Go binary
make build-ui   # Build the Vue frontend for production
make test       # Run Go tests (-tags dev, ./...)
make lint       # Run go vet (-tags dev, ./...)
make audit-openapi  # OpenAPI ↔ cmd/api/routes.go shell diff + Go parity test in cmd/api/openapi_parity_test.go
make sqlc       # Regenerate sqlc Go code from SQL queries
make seed       # Apply seed data to the database
make schema     # Apply the schema to the database
make up         # Start Docker Compose services
make down       # Stop Docker Compose services
make logs       # Tail Docker Compose logs
make clean      # Remove build artifacts

Phase 23 / pre-merge gate (local): make test

, make lint

, make audit-openapi

, python3 -m pytest pi_client/test_gr33n_client.py pi_client/test_mqtt_telemetry_bridge.py -q

, and npm --prefix ui run build

. ** make test** expects a reachable

(see

DATABASE_URL

bootstrap β€” smoke tests) so

cmd/api

integration tests actually run.The Pi daemon runs four threads concurrently:

sensor-loopβ€” reads each GPIO/I2C sensor at its configured interval, POSTs toPOST /sensors/:id/readings

heartbeat-loopβ€” PATCHes device status every 30s so the dashboard shows "online"** schedule-loop**β€” pollsGET /farms/:id/devices

forpending_command

in device config JSONB, executes via GPIO, reports viaPOST /actuators/:id/events

, then clears viaDELETE /devices/:id/pending-command

flush-loopβ€” drains the offline SQLite queue when API becomes reachable

Configure sensors, actuators (with device_id

), and GPIO pins in pi_client/config.yaml

. Install as a systemd service with pi_client/setup.sh

so it starts automatically on boot.

Deployments: Edge-only Pis vs running Postgres + API + UI on the Pi, and how setups scale to split DB/API/UI β€” see . Minimal Pi OS apt packages before

docs/raspberry-pi-and-deployment-topology.md

setup.sh

: ./scripts/install-pi-edge-deps.sh

(make install-pi-edge-deps

).MCUs can publish to an on-farm MQTT broker; a bridge process subscribes and forwards to ** POST /sensors/readings/batch** using

X-API-Key

(same server PI_API_KEY

as the Pi daemon). Reference implementation: . Topics, TLS, ACLs, and tasking:

pi_client/mqtt_telemetry_bridge.py

.

docs/mqtt-edge-operator-playbook.md

gr33n's AI layer runs fully on your intranet β€” no data leaves the LAN in Full mode. Knowledge is never sent to cloud APIs.

Farm Guardian (Phase 27) is a conversational assistant powered by Llama 3.1 70B Q4 running on an on-premise GPU box via Ollama. It layers three knowledge sources:

Llama weightsβ€” general agricultural, scientific, and world knowledge baked in during training.** Your farm's RAG corpus**β€” anything you've ingested intoPOST /farms/{id}/rag/ingest

(sensor notes, crop logs, manuals, etc.) retrieved at query time via pgvector similarity search.Live farm-state snapshotβ€” zones, active crop cycles, and unread alerts pulled from the DB at the start of every grounded turn so answers reflectright now, not a stale index.

The AI features are gated by AI_ENABLED

(default on) and degrade gracefully: in Lite mode (no LLM configured) POST /v1/chat

returns 503 and the "Ask (LLM)" button in the Knowledge UI is disabled with an explanation. In Full mode, Guardian is available from the global slide-out drawer on any page (sidebar, TopBar ✨, right-edge tab) and at /chat

.

What Guardian does today (Phase 27–29): conversational Q&A β€” explain alerts, compare crop cycles, cite your RAG corpus, and read the live farm snapshot. Phase 29 adds confirmed agent actions: Guardian may propose alert acknowledge or mark read; the operator taps Confirm on an inline card (POST /v1/chat/confirm

). Nothing writes without your OK. Viewers can chat but cannot confirm. All confirmed actions log guardian_tool_executed

to the farm audit trail. Guardian does not change schedules, programs, or actuators autonomously β€” that scope is Phase 30 (still Confirm-only).

What comes next (Phase 30): expanded PR-queue tools (tasks, cycle stage, schedules, Pi actuator enqueue) β€” plan.

All AI calls remain inside your farm's intranet:

Pi clients ──HTTPS──▢ Go API
                        β”œβ”€β”€β–Ά Postgres + pgvector  (farm data + RAG corpus)
                        └──▢ Ollama  (Llama 3.1 70B Q4, GPU box on intranet)

Browser ──HTTPS──▢ Vue UI ──▢ Go API  (same as Pi)

See docs/farm-guardian-architecture.md for the request flow + three-knowledge-layer breakdown,

for install/setup, and

docs/farm-guardian-ollama-setup.md

for all

INSTALL.md

AI_*

/ LLM_*

/ CHAT_*

env vars.- AI is modular and never mandatory β€” AI_ENABLED=false

produces a clean Lite deployment. - No cloud calls, no training on your data, no opt-in required for basic operation.

  • Cost guards ( CHAT_COST_MAX_TOKENS_PER_USER

/_PER_FARM

) prevent runaway token usage on shared deployments.

A phase-by-phase ledger of what's live on main

. Each row links to the governing plan doc where one exists; undated rows predate the phase-plan convention.

Phase Focus Status Links
10 JWT smoke tests, farm-scoped write auth, fertigation ↔ crop cycle link, costs CSV, SensorDetail UX βœ… Done β€”
11 Farm RBAC, cost receipts + local storage, PWA shell, Insert Commons opt-in βœ… Done β€”
12 Insert Commons federation βœ… Done db/migrations/20260416_phase12_insert_commons_federation.sql
13 Platform evolution β€” receiver, audit/compliance, offline, finance depth, tenancy βœ… Done

planΒ·ops docplanplanplanplangr33ncore.zone_setpoints

) + rule engine integration + UIcost_transactions.crop_cycle_id

aquaponics.loops

, feed autologging, bootstrap upgradeexecutable_actions

surface + metadata.steps

backfill + ResolveProgramActions

fallbackplanGET /crop-cycles/{id}/summary

, compare, UI, CSV per plan)planΒ·Phase 2822****Worker program-tick + finalβ€”metadata.steps

backfill sweeprunProgramTick

dispatches executable_actions

per program, automation_runs.program_id

attribution, 20260517 sweep + per-program NOTICE log, structured fallback warning23****Stabilization sprintβ€” CI gates, smoke +DATABASE_URL

docs, OpenAPI parity, Pi/API key runbook, workflow + MQTT accuracy, worker monitoring docsplanΒ·exit sign-off24****RAG retrieval systemβ€” embeddings + farm-scoped retrieval API (+ optional LLM synthesis); builds on20.95 RAG-prepplan25****RAG operations & expansionβ€” ingest breadth, incremental re-embed, CI/pgvector parity, integration tests + synthesis limits, UX/docs (schema ERD text)plan26****Operator tutorial, observability, RAG scopeβ€” operator-guide UI, Loki/Promtail/Grafana logging overlay, RAG scope/threat-model, LLM retry/backoff, Ollama setup runbookplan27****Farm Guardian AI layerβ€” on-premise Llama 3.1 70B via Ollama,AI_ENABLED

  • /capabilities

, streaming POST /v1/chat

, multi-turn history + RAG grounding + live farm-state snapshot, session CRUD, token usage, cost guards, /chat

UI panel with session sidebar + bulk-deleteplan28****Crop intelligence & Guardian depthβ€” crop-cycle analytics, Guardian ↔ cycles + alerts, token-usage dashboard, 80% budget warnings, OpenAPI 0.3.0plan29****Guardian agent layer(candidate) β€” tool-calling actions with confirmation, global slide-out panel, Guardian-ready bootstrapplanStabilization sprint closed on main

2026-04-18. Criterion-by-criterion table and next-phase links: .

docs/plans/phase_23_stabilization_sprint.plan.md

β€” Exit sign-off| Gate | Status | |---|---| CI matrix (make test , make lint , make audit-openapi ; pytest + UI build β€” see | βœ… | OpenAPI ↔ routes.go | βœ… | Smoke / DATABASE_URL + CI without DB | βœ… Documented + TestMain behavior | | Operator docs (workflow, MQTT, Pi auth, automation logs) | βœ… |

In flight / next up (priority order):

Phase 23 β€” stabilizationβ€”** done**;exit sign-off. - Phase 24 β€” RAG retrievalβ€” vectors + farm-scoped API + optional LLM synthesis; Knowledge UI. - Phase 25 β€” RAG operations & expansionβ€” CI parity, ingest breadth, incremental re-embed, limits/tests, docs/UX polish. - Phase 26 β€” operator tutorial, observability, RAG scopeβ€” guide UI, Loki overlay, RAG boundary doc, LLM retry, Ollama runbook. - Phase 27 β€” Farm Guardian AI layerβ€” streaming chat, multi-turn history, RAG grounding, live snapshot, session management, cost guards. - Pi ↔ API contract passβ€” smoke testsTestPiContract*

in: enqueuecmd/api/smoke_pi_contract_test.go

pending_command

β†’ Pi-keyGET /farms/1/devices

β†’POST /actuators/{id}/events

β†’DELETE

pending. - Phase 28 — crop intelligence & Guardian depth— crop analytics, Guardian snapshot depth, usage dashboard, OpenAPI 0.3.0. - Phase 29 — Guardian agent layer— propose→confirm alert ack/read, slide-out drawer, contextual entry points, OpenAPI 0.4.0 —plan - Phase 30 — Guardian change requests (PR queue)— config + actuator proposals, pending inbox, zone photos / optional vision —plan - Phase 31 — field validation & safe edge— Pi/breadboard loop, proves confirmed actuator PRs reach GPIO —plan·enterprise topology sketch - Deprecate— after N deploys with zero fallback warnings, promoteprograms.metadata.steps

action_source

checks to hard errors and drop the column. - Program "run now" APIβ€” explicit trigger for unscheduled / ad-hoc programs. - Mobile distribution polishβ€” Capacitor packaging, store submission checklist.

  • gr33ncore schema β€” users, sensors, schedules, zones, automation rules
  • gr33nnaturalfarming schema β€” inputs, recipes, batches
  • Go REST API β€” farms, zones, devices, sensors, tasks, readings
  • Natural farming demo seed β€” 15 inputs, 14 recipes, full automation (JADAM-style labels)
  • sqlc query layer + enum types
  • Vue 3 frontend β€” Dashboard, Zones, Sensors, Actuators, Schedules, Settings, Inventory
  • Raspberry Pi sensor client with systemd daemon
  • OpenAPI spec (openapi.yaml)
  • Sensor readings live on dashboard (SSE stream with JWT query param auth)
  • Phase 10 β€” JWT smoke tests ( AUTH_MODE=auth_test

), farm-scoped write authorization, fertigation ↔ crop cycle link, costs CSV export, SensorDetail export UX - Phase 11 β€” Farm RBAC (viewer / operator / finance / manager / owner), cost receipts + local FILE_STORAGE_DIR

storage,PWA-first installable shell (manifest + SW in production builds; Capacitor still an option for store-distributed apps), Insert Commons opt-in + early sync hook, OpenAPI updates - Phase 13 β€” Platform evolution (receiver-side Insert Commons, audit/compliance API, offline + finance depth, tenancy experiments, optional Capacitor scaffold; indexes plans and playbooks)docs/phase-13-operator-documentation.md

  • Phase 14 β€” Field network & commons (MQTT/edge, insert pipeline, gr33n_inserts catalog, federation/receiver depth, FCM notifications, org governance, domain schema stubs; ,docs/plans/phase_14_network_and_commons.plan.md

)docs/phase-14-operator-documentation.md

  • Actuator control pipeline (automation worker β†’ pending_command β†’ Pi poll β†’ execute β†’ report)
  • Fertigation module β€” reservoirs, EC targets, programs, events
  • Natural farming inventory UI β€” input definitions & batch tracking
  • Pi heartbeat loop β€” devices show online/offline in real time
  • Docker Compose + Dockerfile for containerized deployment
  • Microcontroller integrations β€” MQTT β†’ HTTP bridge ( ,pi_client/mqtt_telemetry_bridge.py

); field tasking unchanged (docs/mqtt-edge-operator-playbook.md

pending_command

  • Pi / bridge poll) - Data insert pipeline (Insert Commons validation, approval bundles, export β€” )docs/insert-commons-pipeline-runbook.md
  • LM Studio integration and AI scaffolds for insert-sharing

  • gr33n_inserts β€” commons catalog API (browse + farm import audit; )docs/commons-catalog-operator-playbook.md

  • Stub schemas gr33ncrops

,gr33nanimals

,gr33naquaponics

(placeholder tables; enable viafarm_active_modules

β€”)docs/domain-modules-operator-playbook.md

  • Phase 20 β€” automation rule engine (sensor-driven conditions, action dispatch, cooldowns, rule-driven notifications) β€” plan - Phase 20.6–20.9 β€” stage-scoped setpoints, cost/energy nightly rollups, animal husbandry, labor auto-cost, program actions + metadata.steps

backfill - Phase 20.95 β€” RAG-prep schema housekeeping for AI consumption β€” plan - Phase 21 β€” crop cycle analytics & yield (summary, compare, UI, CSV) β€” plan(superseded by Phase 28 WS1 β€” endpoints shipped) - Phase 22 β€” worker program-tick ( runProgramTick

),automation_runs.program_id

, finalmetadata.steps

backfill sweep, observable fallback warning - Phase 23 β€” stabilization sprint (CI, smoke, OpenAPI parity, docs, small fixes) β€” planΒ·exit sign-off - Phase 24 β€” RAG retrieval system (vectors + farm-scoped API + optional LLM) β€” plan - Phase 25 β€” RAG operations & expansion (ingest breadth, incremental re-embed, CI parity, limits, UX/docs) β€” plan - Phase 26 β€” operator tutorial, observability, RAG scope (guide UI, Loki overlay, RAG boundary, LLM retry, Ollama runbook) β€” plan - Phase 27 β€” Farm Guardian AI layer (streaming chat, multi-turn sessions, RAG grounding + live snapshot, cost guards, /chat

UI panel) β€”plan - Phase 28 β€” crop intelligence & Guardian depth (crop analytics, Guardian ↔ cycles/alerts, usage dashboard, OpenAPI 0.3.0) β€” plan - Phase 29 β€” Guardian agent layer (proposeβ†’confirm, slide-out drawer, Ask Guardian entry points, OpenAPI 0.4.0) β€” plan - Phase 30 β€” Guardian PR queue (config agent, actuator proposals, zone vision) β€” plan - Phase 31 β€” field validation & edge (Pi loop, safe actuator, recipe packs) β€” planΒ·enterprise sketch

  • Fork this repo
  • Join the insert-sharing network (coming soon in gr33n_inserts)
  • Help build bridges between sensors, dashboards, and soil
  • Translate docs, test offline installs, or write a better knf_notes parser

"Built for the commons."

The commons means shared knowledge, shared code, shared resilience. It's an ancient concept β€” like the village well or a seed bank β€” remixed into digital space.

gr33n lives in this tradition: Free to use, fork, and rebuild. Not fenced off behind corporate toll booths.

GNU Affero General Public License v3.0 (AGPL-3.0)

Use it. Fork it. Share it. If you run it as a service β€” cloud, SaaS, or otherwise β€” you must release your modifications back to the community. No exceptions. No toll booths.

Just don't try to put a fence around the commons.

Built by farmers, hackers, and friends. With sunlight and rage.

── more in #ai-agents 4 stories Β· sorted by recency
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain β€” perfect for shipping the agent you just read about.

$git push zahid main
β†’ Live at https://your-agent.zahid.host βœ“
Get free account β†’ Pricing
from €0/mo Β· no card required
LIVE [news/open-source-agricult…] indexed:0 read:29min 2026-05-27 Β· β€”