Thread zip/lat/lng/radius_miles through the client and both tools; friendly guard for the zip-XOR-gps rule. Formatters surface distance, the searched center, and the nearest-source hint when nothing is in range. - client: best()/latest() take zip/lat/lng/radius_miles - server: location params + docstrings (note Ohio-concentrated coverage) - format: distance column + center/nearest rendering - README + CHANGELOG + advisor prompt library updated - tests: location formatting cases Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
10 KiB
Ag Advisor — Example Prompts (Grain Marketing)
Example end-user prompts for the Drawbar Ag Advisor, the AI agent that
consumes the ag-bids MCP tools (and the underlying ag-monitor /api/data/*
HTTP API). They're grouped into Planning (build a marketing strategy) and
Monitoring (track prices and act day-to-day), with the tools each prompt
leans on so the advisor knows which calls answer the question.
Copy this into the Drawbar repo (e.g. prompts/grain-marketing.md) as a prompt
library / eval set. Phrasing is intentionally farmer-natural — the advisor is
expected to translate it into tool calls.
What the advisor can see
| Capability | Tool(s) |
|---|---|
| Live local cash bids (per elevator, crop, delivery) | latest_prices, best_local_bid |
| Cash price history + basis trend per elevator | price_history |
| Basis movement (overview, then drill-down) | basis_movement → basis_detail |
| CBOT futures price + change (since open, on day) + carry | futures_quote, list_deliveries |
| National price received by farmers ($/bu) + MoM/YoY + seasonal | price_trend, price_series |
| Input costs — diesel ($/gal) + fertilizer ($/ton) + change + seasonal | input_cost_trend, input_cost_series |
| Local fertilizer/lime snapshot (DTN dealer feed) | current_input_price, current_lime_price |
| What's covered / is the data fresh | list_sources, list_commodities, list_deliveries, source_health |
| One-call morning brief | todays_summary |
Conventions the advisor should keep in mind:
- Basis is the lever. Positive basis move = cash strengthened vs futures;
negative = weakened.
basis_movementaggregates and can net divergent elevators to "flat" — follow up withbasis_detailwhen it looks surprising. - Cash = futures + basis. A sell decision is really two decisions (futures
level and basis), and the carry (
list_deliveries+futures_quoteacross months) tells you whether the market pays you to store. price_trend/input_cost_trendare the macro/seasonal benchmark — "is today cheap or dear vs history" — not a local bid. Pair them withbest_local_bid/latest_pricesfor the actionable number.- Grains:
corn,soy,wheat.geoforprice_trendisUSor a 2-letter state (e.g.OH,IA). Fertilizergeois an AgTransport region (defaultCornbelt).
Planning — build a marketing strategy
1. Build a pre-harvest plan
"I grow corn and soybeans in west-central Ohio. Help me build a pre-harvest marketing plan for this year's corn crop."
Advisor pulls: price_trend("corn", geo="OH", years=10) (where price sits vs
norm) · futures_quote("corn", delivery="Dec 2026") (new-crop level) ·
basis_movement("corn") (is basis a reason to wait or sell) ·
best_local_bid("corn") (today's actionable cash).
2. Sell now or store?
"I've got 20,000 bushels of soybeans in the bin. Should I sell now or hold into winter?"
price_trend("soy", geo="OH") (seasonal percentile — is now historically high or
low) · list_deliveries("soy") + futures_quote("soy", delivery=…) across months
(does the carry pay me to store) · basis_movement("soy") (is basis likely to
improve) · best_local_bid("soy").
3. Does the market pay me to store? (carry)
"Does the futures carry justify storing corn until March instead of selling at harvest?"
list_deliveries("corn") then futures_quote("corn", delivery=…) for the nearby
vs deferred months → compare the spread against storage cost.
4. Time a new-crop sale
"Is now a good time to make a new-crop corn sale for fall delivery?"
price_trend("corn", years=10) (seasonal context) · futures_quote("corn", delivery="Dec 2026") (change on day / since open) · basis_movement("corn", delivery="Oct 2026") · best_local_bid("corn").
5. Seasonality of basis / price
"Historically, what time of year is corn basis strongest around here, and when does the cash price tend to peak?"
price_series("corn", geo="OH") over multiple years (seasonal shape) ·
price_trend("corn", geo="OH") (this month's percentile vs the same month over
the last N years) · price_history("corn", days=…) for the recent basis arc.
6. Compare which crop to sell
"Relative to their 10-year norms, is corn or soybeans the better one to be selling right now?"
price_trend("corn", years=10) vs price_trend("soy", years=10) — compare
percentile-vs-normal and YoY, then best_local_bid for each.
7. Breakeven / cost side of the plan
"How have my input costs moved this year — what does that do to my corn breakeven?"
input_cost_trend("diesel") · input_cost_trend("urea"),
input_cost_trend("anhydrous"), input_cost_trend("dap"),
input_cost_trend("potash") (all $/ton, Cornbelt) — latest + YoY change feed the
cost side; combine with price_trend("corn") for the margin picture.
8. Prebuy fertilizer decision
"Should I prebuy urea and anhydrous now or wait until spring?"
input_cost_trend("urea") and input_cost_trend("anhydrous") (seasonal
percentile + YoY — are they historically cheap) · input_cost_series(…) for the
trend shape · current_input_price() for the latest local dealer quote.
9. Set price targets / a scale-up plan
"Give me three corn price targets to scale out the rest of my old-crop bushels, based on where price sits historically."
price_trend("corn", geo="OH", years=10) (normal, range, percentile) +
futures_quote("corn") + basis_movement("corn") → advisor proposes laddered
targets above the seasonal normal.
10. Wheat pre-harvest plan
"Build me a marketing plan for this year's wheat ahead of harvest."
price_trend("wheat", geo="OH") · futures_quote("wheat", delivery="Jul 2026") ·
basis_movement("wheat") · best_local_bid("wheat").
Monitoring — track prices and act
11. Morning brief
"Give me my grain marketing brief for this morning."
todays_summary() (one call) — then drill in where it flags something.
12. Best bid right now (location-aware)
"Where's the best corn bid within 40 miles of 45810?"
best_local_bid("corn", zip="45810", radius_miles=40) — restricts to nearby
elevators and shows the distance. From GPS instead:
best_local_bid("corn", lat=40.79, lng=-83.81). latest_prices("corn", zip="45810", radius_miles=40) lists every nearby elevator nearest-first. Without
a location these consider every scraped elevator.
Coverage note for the advisor: scraped cash bids are concentrated in Ohio today. If the farmer's zip/GPS is far from Ohio,
best_local_bidreturns "none in range" plus the nearest elevator's distance — say that plainly (it's a coverage gap, not a price of zero), and fall back toprice_trend(commodity, geo=<their state>)for the national/state benchmark.
13. Did futures move today?
"How far has corn moved today — off the open and on the day?"
futures_quote("corn") → reports change since open and change on the day.
14. Basis check
"How has corn basis moved over the last two weeks, and which elevator improved the most?"
basis_movement("corn", days=14) for the headline, then basis_detail("corn", days=14) for the per-elevator split.
15. Best home for a specific delivery
"Which elevator is paying the most for soybeans for January delivery?"
latest_prices("soy", delivery="Jan 2026") / best_local_bid("soy").
16. Is cash near a recent high?
"Is the local corn cash price near its high for the last month?"
price_history("corn", days=30) (recent arc + basis) · price_trend("corn", geo="OH") (seasonal percentile for context).
17. Spread between cash and CBOT
"Has my local basis widened or narrowed this month?"
basis_movement("corn", days=30) → if it nets flat or odd, basis_detail(…).
18. All elevators at a glance
"Show me today's corn bids across all my elevators."
latest_prices("corn") (snapshot table, all sources).
19. What can I price?
"What delivery months can I price corn for right now?"
list_deliveries("corn").
20. Data freshness / trust check
"Are any of my price feeds stale or failing?"
source_health() (and list_sources() for the full roster + last-success
times).
21. Fertilizer price watch
"Are fertilizer prices climbing — should I be worried about next year's input bill?"
input_cost_trend("urea"), input_cost_trend("dap"),
input_cost_trend("potash"), input_cost_trend("anhydrous") — latest $/ton +
MoM/YoY + seasonal; input_cost_series(…) for the trend.
22. Diesel watch for fieldwork
"What's diesel doing — anything I should factor into fall fieldwork costs?"
input_cost_trend("diesel") (U.S. retail $/gal, week-over-week + YoY).
Cross-cutting — how the advisor synthesizes a recommendation
These show the reasoning, combining several tools into one answer.
A "should I sell today" call:
"Should I sell corn today?"
best_local_bid("corn")— the actual number on the table.price_trend("corn", geo="OH", years=10)— is that number historically high or low for this month (percentile vs normal)?futures_quote("corn")— is the board strong/weak today, and which way is it moving (since open / on day)?basis_movement("corn")— is basis strengthening (a reason to wait) or weakening (a reason to capture now)?- Synthesis: "Cash is at the 78th percentile vs the last 10 Mays, board is up 6¢ on the day, and basis has firmed 4¢ over two weeks but looks toppy — taking a portion here and leaving the rest for the carry is reasonable."
A "store vs sell" call combines list_deliveries + futures_quote (carry) +
basis_movement (expected basis gain) + input_cost_trend("diesel") and storage
assumptions to weigh the cost of carry against the expected pickup.
Guidance for the advisor: always anchor a recommendation to a live number (
best_local_bid/latest_prices/futures_quote) and useprice_trend/input_cost_trendonly for context. State the basis and futures pieces separately so the user can act on whichever is actually driving the call.