fb50c103d3
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>
232 lines
10 KiB
Markdown
232 lines
10 KiB
Markdown
# 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_movement` aggregates and can net divergent
|
|
elevators to "flat" — follow up with `basis_detail` when it looks surprising.
|
|
- **Cash = futures + basis.** A sell decision is really two decisions (futures
|
|
level *and* basis), and the carry (`list_deliveries` + `futures_quote` across
|
|
months) tells you whether the market pays you to store.
|
|
- `price_trend`/`input_cost_trend` are the **macro/seasonal benchmark** — "is
|
|
today cheap or dear vs history" — not a local bid. Pair them with
|
|
`best_local_bid`/`latest_prices` for the actionable number.
|
|
- Grains: `corn`, `soy`, `wheat`. `geo` for `price_trend` is `US` or a 2-letter
|
|
state (e.g. `OH`, `IA`). Fertilizer `geo` is an AgTransport region (default
|
|
`Cornbelt`).
|
|
|
|
---
|
|
|
|
## 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_bid` returns "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 to `price_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?"
|
|
|
|
1. `best_local_bid("corn")` — the actual number on the table.
|
|
2. `price_trend("corn", geo="OH", years=10)` — is that number historically high
|
|
or low for this month (percentile vs normal)?
|
|
3. `futures_quote("corn")` — is the board strong/weak today, and which way is it
|
|
moving (since open / on day)?
|
|
4. `basis_movement("corn")` — is basis strengthening (a reason to wait) or
|
|
weakening (a reason to capture now)?
|
|
5. 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 use
|
|
> `price_trend`/`input_cost_trend` only for *context*. State the basis and
|
|
> futures pieces separately so the user can act on whichever is actually driving
|
|
> the call.
|