Good-Seat AI Watch
Fetches the cheapest current listings for an event and uses an ai: arm to
classify whether any of them is notably good value FOR ITS SECTION. Goes
beyond raw price-vs-threshold checks — a $40 upper-corner seat isn't a deal,
but a $90 lower-bowl seat (typical floor $150+) is.
What it does
On each fire:
- The check calls a ticket-pricing endpoint that returns the cheapest 20
listings as a JSON array, published as
{{check.listingsJson}}. - The
when:block has ONE arm — anai:arm whose prompt: - Describes typical price floors per section (lower bowl, mezz, upper). - States the value criteria (≥ 30% below typical floor, decent section, no obstruction tags). - Asks the AI to returntriggered=trueonly if at least one listing matches ALL criteria. - If the AI says yes, notify with the AI's reasoning + the full listings
array. Otherwise the
else:arm matches and nothing fires.
Why an AI arm here
The "is this seat a deal?" decision can't be captured cleanly in a condition:
expression because:
- Price-per-section matters, not absolute price.
- "Limited view" / "partial view" tags should disqualify even cheap listings.
- Different venues have different price floors — a New York lower bowl is not a Cleveland lower bowl.
A literal expression covering all that becomes a 5-clause chain that misses edge cases. The AI handles it in one prompt at the cost of ONE LLM call per fire.
Data-source setup
Same scraper / endpoint as event-price-watch, with
ONE additional requirement: the response must include listingsJson —
either a JSON-array string or a structured array — containing the cheapest N
listings. The AI reads this directly via Mustache interpolation in the
prompt.
A minimal listing record looks like:
{ "section": "108", "row": "12", "price": 95, "note": "" }
Add note for obstruction tags ("limited view"), delivery for ticket
delivery method, etc. — the AI consumes whatever you give it.
Expected published bindings:
| Binding | Expected value |
|---|---|
{{check.eventName}} |
Display name of the event. |
{{check.eventDate}} |
Event date for the AI prompt. |
{{check.listingsJson}} |
JSON-encoded array of the cheapest N listings. |
{{ai_reasoning}} |
Set by the AI-arm; explains the match. |
Edit before installing
In monitor.yaml:
check.args.url— replace with your scraper / API endpoint. SubstituteREPLACE_EVENT_ID.- The AI prompt — adjust the typical-price-floor table for your venue category (NHL > MLB > MLS for floors; arena vs stadium also matters). Be specific about what counts and what doesn't.
when[0].do[0].body— adjust copy.
Schedule guidance: a few times per day. Each fire is one LLM call so cost adds up at high cadence. Daily + within 24h of event = cheaper rule-of- thumb.
Requirements
- AI assistant configured (Server Settings → AI Assistant). If no AI is
configured, the
ai:arm returns false safely (no false fires).
Tools used
http— core InTouch HTTP task type.- AI assistant (any provider — Anthropic, OpenAI, Gemini, Ollama).
Pattern showcase
This is the AI-judged value pattern. Use it whenever the "is this a deal?" judgment is fuzzy enough that a literal condition can't capture it, but the data fits in a small JSON blob the AI can read. Same shape works for: cheap flights in your routes, RFQs that look worth pursuing, support tickets that look like real fires, etc.
Related monitors
event-price-watch— raw threshold, no AI.gameday-firesale-watch— day-of relative discount.hn-keyword-watch— different shape, same ai-arm pattern.