Provenance-tagged agricultural intelligence for any crop, anywhere.
Pestren answers agronomic questions for any crop at any coordinate on earth — and every value it returns carries its source, a timestamp, a calibrated confidence, and a three-tier verification tag.
What you get
Three surfaces share one field catalog and one provenance model, so an answer, a raw field, and an agent tool call all cite the same ground truth:
POST /v1/ask — natural-language question in, a cited answer + recommended action out.
POST /v1/fetch — deterministic raw fields or presets, each provenance-wrapped, with a partial_failures contract.
MCP server — pestren_ask and pestren_fetch native to any MCP-aware model.
FAO, ESA Sentinel, NASA, SoilGrids, CABI, national ag departments — never a proprietary "AI-derived" number.
Per-field citations + 3 tiers
Every field ships its source_url and a literature / field-verified / lab-confirmed tag.
MCP-native distribution
Drop the tools into any agent loop; citations flow through like any other tool call.
Honest partial failures
Anything we can't fetch surfaces in partial_failures with a retryable flag — never a silent default.
Coverage
Global. Latitude [-60, 75], longitude [-180, 180]; out-of-bounds returns 400 coord_out_of_bounds. Any crop; verification depth grows region by region. 220+ fields across 7 layers; 12 presets — browse the full catalog at GET /v1/meta/fields.
Make your first /v1/ask call and read a cited answer in five minutes.
1 · Get a token
Grab an API token from your dashboard (see Authentication) and export it:
shell
export PESTREN_API_TOKEN="sk_live_…"
2 · Ask a question
curlPythonMCP
request.sh
curl -s https://api.pestren.com/v1/ask \
-H "Authorization: Bearer $PESTREN_API_TOKEN" \
-H 'content-type: application/json' \
-d '{"lat": 4.57, "lng": -75.66,
"question": "Coffee leaf rust risk here this week — should I act?"}'
example.py
import os, requests
r = requests.post(
"https://api.pestren.com/v1/ask",
headers={"Authorization": f"Bearer {os.environ['PESTREN_API_TOKEN']}"},
json={"lat": 4.57, "lng": -75.66,
"question": "Coffee leaf rust risk here this week?"},
)
print(r.json()["answer"], r.json()["confidence"])
claude-code
# after installing the MCP server
/pestren_ask lat=4.57 lng=-75.66 \
question="Coffee leaf rust risk here this week?"
3 · Read the response
You get a prose answer, an overall confidence bucket (high/medium/low), a citations[] array (one entry per source, each with a source_url, fetched_at, and verification tier), the fields_used[] that grounded the answer, and an optional recommended_action.
Every claim in the prose maps back to a citation a field officer can open. If a driver field couldn't be fetched, it appears in partial_failures — the answer is never silently padded.
Three ways in — all bearer-token based. The public catalog needs no auth.
Dashboard API token
Copy a token from your account and send it as a bearer header on every call. Tokens are only accepted over https (with a loopback exception for local development).
header
Authorization: Bearer <PESTREN_API_TOKEN>
Device-flow login
For CLIs and local MCP, run a one-time browser login that stores a credential file:
shell
pestren-mcp login # opens a browser, writes ~/.pestren/credentials
MCP OAuth
Remote MCP clients authenticate against the hosted endpoint https://api.pestren.com/mcp via OAuth — no token pasting.
Rotate & revoke
Rotate tokens from the dashboard; revoked tokens fail immediately with 401 unauthorized. Scope tokens per environment and never commit them.
GET /v1/meta/fields and GET /v1/meta/presets are public — no bearer required — so you can explore the catalog before you sign up.
A downgrade fires when a key field returns only literature tier, or a partial_failure hits a driver field. Confidence is a promise about the evidence, not the prose.
Named field bundles for common jobs. Pass preset instead of enumerating fields[].
Preset
Best for
pest_risk
This week's pest pressure + drivers.
disease_risk
Disease pressure + primary threat.
irrigation_plan
Soil moisture, ET0, rainfall, irrigation need.
soil_health
Texture, pH, organic carbon, drainage.
yield_forecast
NDVI trend, biomass, yield estimate + risk.
crop_verify
Crop, growth stage, sowing window.
precision_scouting
Risk polygons + NDVI for fleet tasking.
insurance_underwrite
Crop, sowing, flood/drainage, yield risk.
lending_collateral
Crop, acreage, NDVI trend, yield-risk band.
climate_risk
Aggregated climate-hazard exposure.
There's a per-call field cap. If a preset exceeds it, fields are truncated in catalog order and the omission is reported in notes. Browse presets at GET /v1/meta/presets.
Drop-in agronomy files an agent loads to reason about a crop or a practice — reusable across models and stacks.
What a skill is
A self-contained file describing an entity's agronomy: stages, thresholds, the sources behind them, and a verification tier. The agent reads the skill for reasoning; it calls /v1/fetch for live values.
skills/
skills/
crop.coffee.skill.md# agronomy, stages, thresholds, sources, tiercrop.maize.skill.mdpractice.irrigation.md# reusable across cropspractice.disease-scouting.md
Schema
Each skill declares an entity, its stages, decision thresholds, the sources that back them, and a default verification tier. Load it in Claude/GPT skills or a custom stack.
Skills + /v1/fetch compose: the skill is the reasoning layer, fetch is the live-values layer. Together they give an agent grounded judgment instead of guesses.
Batch / polygon: fetch for a resolved field_polygon to aggregate over the parcel, or a bare point for a single sample. In unverified regions a field's tier may drop to literature — always reported, never hidden.
The public catalog — no auth. Every field, described.
Returns each field's id, layer, unit, description, default source, typical confidence tier, and ttl_seconds. Companion endpoint GET /v1/meta/presets lists the bundles.
Smoke-test with MCP Inspector, then fix the usual suspects.
You should see two tools, three resources, and prompts visible — and a passing pestren_ask and pestren_fetch call returning provenance-wrapped JSON.
Confirm PESTREN_BASE_URL has no trailing slash and the token is exported in the same shell that launches the client. For hosted OAuth, re-run /mcp to refresh the grant.
First call after idle can exceed the default timeout — raise PESTREN_TIMEOUT_S (e.g. to 30).
A grower or agronomist asks pest / irrigation / yield questions in language and gets a cited answer, an action, and optional products.
Query
"Coffee at 4.57, -75.66 — leaf rust risk this week, and should I irrigate?"
Response & audit trail
A grounded answer + recommended_action, every claim citing CABI / Sentinel / NASA with tiers a field officer can re-open.
Why it works
The planner pulls the disease and water layers for the exact coordinate — not generic advice.
What it does NOT do: it's not a spray prescription of record, not a geocoder (you resolve address → lat/lng), and not a live pest-trap feed — add those alongside if you need them.
Drop the MCP tools + Skills into an agent loop; let the planner pick fields; keep citations flowing through tool calls.
Sample transcript
agent.log
user → Is my rice at 21.94, 87.75 at risk this week?
agent →pestren_ask(lat=21.94, lng=87.75,
question="pest/disease risk this week for rice?")
tool → { answer, confidence:"high", citations:[…], recommended_action }
agent → Elevated stem-borer pressure — scout now. (FAO, Sentinel ↗)
Load a crop.rice.skill.md alongside the tools so the agent reasons with the right thresholds, then fetches live values.