T
TOMO
Developer Docs
BETA These docs are under partner review. Some features described are roadmap items, not yet shipped. Verify against your sandbox before relying on any contract.
● DRAFTv1.0.0entertainment.book_comedy_show

Intent Spec — entertainment.book_comedy_show

FULL ID:       entertainment.book_comedy_show
VERSION:       v1.0.0
STATUS:        draft
LAST UPDATED:  2026-05-12
DOMAIN:        entertainment
PRIMARY AGENT: EntertainmentAgent
TTBS WEIGHTS:  time=0.20 taste=0.45 budget=0.20 safety=0.15

User books a ticket to a stand-up comedy show, improv night, or open-mic at a venue. TASTE-dominant because comedy is fundamentally about performer match — the user is choosing a comedian, not a movie or a seat class. Distinct from entertainment.book_theatre_play (scripted live theatre) and entertainment.book_movie_ticket (recorded film).

Partner exemplars: BookMyShow, Paytm Insider, District by Zomato, individual comedy clubs (Habitat Mumbai, The Comedy Cellar, Punchliners), comic-direct sites (Naveen Polishetty's site, OML Insider).


SECTION 1 — INTENT IDENTITY

User wants to attend live comedy. Distinct from:

  • entertainment.book_movie_ticket — recorded film
  • entertainment.book_theatre_play — scripted theatre/drama
  • entertainment.book_concert_ticket — music concert
  • entertainment.book_event_venue — booking the venue (not a ticket to a show in it)
  • Streaming comedy specials → entertainment.subscribe_streaming (Netflix/Prime/SonyLIV)

Single intent per booking. Group bookings (≤20 seats) classify here; larger corporate book-outs escalate to entertainment.book_event_venue.


SECTION 2 — NATURAL LANGUAGE COVERAGE

CLASSIFIES IN

  • "Book Zakir Khan tickets for Friday"
  • "Stand-up comedy near me tonight"
  • "Naveen Polishetty live show in Hyderabad"
  • "Two tickets for Comicstaan tour"
  • "Open mic this weekend"
  • "Improv comedy at Habitat"
  • "Telugu stand-up show this Saturday"
  • "Tanmay Bhat live, get me the cheapest seat"
  • "Funniest show in town tomorrow"
  • "Comedy roast tickets"

CLASSIFIES OUT — BORDERLINE NO

  • "Watch a movie" → entertainment.book_movie_ticket
  • "Music concert" → entertainment.book_concert_ticket
  • "Drama / theatre play" → entertainment.book_theatre_play
  • "Book a venue for my friend's comedy event" → entertainment.book_event_venue
  • "Watch comedy on Netflix" → entertainment.subscribe_streaming

MULTI-INTENT TRIGGERS

  • "Comedy show + dinner nearby" → entertainment.book_comedy_show + food.book_dine_in
  • "Comedy + ride home after" → entertainment.book_comedy_show + mobility.book_intracity_ride (pickup time = show end)

SECTION 3 — INPUT (TOMO → PROVIDER)

{
  "intent": "entertainment.book_comedy_show",
  "request_id": "req_01J9Z...",
  "user_locale": "en-IN",
  "user_location": { "lat": 17.4475, "lng": 78.3563, "max_radius_km": 18, "city": "Hyderabad" },
  "preferences": {
    "comedian_name": "Zakir Khan",                  // OR null = open to any
    "language": ["hi", "en"],                       // BCP-47, ordered preference
    "show_format": ["stand_up"],                    // STRICT ENUM §6
    "content_rating_max": "adult_18",               // STRICT ENUM §6 (CBFC-style; some comedy is 18+)
    "showtime_window": {
      "start": "2026-05-15T18:00:00+05:30",
      "end":   "2026-05-15T23:30:00+05:30"
    },
    "seat_count": 2,
    "seat_section_preference": ["premium", "standard"],
    "alcohol_serving_acceptable": true,
    "accessibility": { "wheelchair_seats_required": 0 }
  },
  "ttbs_user_band": { "time": "balanced", "taste": "good", "budget": "good", "safety": "balanced" },
  "session_context": { "tomo_session_id": "ses_01J9Z...", "user_dna_hash": "dna_v3_a7c9..." }
}
Field Type Constraint Notes
intent string REQUIRED, STRICT ENUM Always entertainment.book_comedy_show
preferences.comedian_name string | null REQUIRED nullable Null = open; partner returns top shows in window
preferences.language array REQUIRED, BCP-47, ≥1
preferences.show_format array REQUIRED, ≥1, STRICT ENUM §6
preferences.content_rating_max enum REQUIRED, STRICT ENUM §6 Adult-only shows filtered out when max=U
preferences.seat_count int REQUIRED, 1-20 >20 → escalate to event_venue
preferences.alcohol_serving_acceptable bool REQUIRED Some venues are dry; affects filter

Anti-fabrication preamble: Provider may not list a show with a comedian who has not confirmed the date. Surge multipliers must be disclosed.


SECTION 4 — PROVIDER TOOLS

Tool 1: search_comedy_shows

PURPOSE:      Up to 20 shows matching window + comedian + format
SLA:          p50 ≤ 600ms, p95 ≤ 1500ms, p99 ≤ 3000ms
RATE LIMIT:   60 req/min
IDEMPOTENCY:  request_id; 30s cache
RETRY:        1 on 429, 2 on 5xx

Tool 2: get_seat_map

PURPOSE:      Live seat availability for a chosen show
SLA:          p50 ≤ 300ms, p95 ≤ 800ms
RATE LIMIT:   120 req/min
RETRY:        1 on 5xx

Tool 3: create_booking

PURPOSE:      Lock + confirm seats
SLA:          p50 ≤ 1500ms, p95 ≤ 4000ms
RATE LIMIT:   30 req/min
IDEMPOTENCY:  request_id
RETRY:        No retry

Tool 4: cancel_booking

SLA:          p50 ≤ 1000ms, p95 ≤ 3000ms
RATE LIMIT:   30 req/min
RETRY:        1 on 5xx

SECTION 5 — RESPONSE SHAPE

ComedyShowListing

ComedyShowListing:
  show_id: { type: string, constraint: REQUIRED }
  show:
    title: { type: string, constraint: REQUIRED, semantics: "official show title" }
    tour_name: { type: string, constraint: REQUIRED nullable, semantics: "e.g. 'Manpasand', 'Tathastu'" }
    comedians:
      type: array<Comedian>
      constraint: REQUIRED, ≥1
      shape:
        name: { type: string, constraint: REQUIRED }
        instagram_handle: { type: string, constraint: REQUIRED nullable }
        verified: { type: boolean, constraint: REQUIRED, semantics: "partner has confirmed date with talent" }
    show_format: { type: enum, constraint: REQUIRED, STRICT ENUM §6 }
    language: { type: enum, constraint: REQUIRED, BCP-47 }
    duration_minutes: { type: int, constraint: REQUIRED, 30-240 }
    content_rating: { type: enum, constraint: REQUIRED, STRICT ENUM §6 }
    content_warnings:
      type: array<enum>
      constraint: REQUIRED, may be empty
      values: [strong_language, sexual_content, political, religious, dark_humour, audience_participation]

  venue:
    venue_id: { type: string, constraint: REQUIRED }
    name: { type: string, constraint: REQUIRED }
    venue_type:
      type: enum
      constraint: REQUIRED, STRICT ENUM §6
      values: [comedy_club, theatre, bar_with_stage, hotel_ballroom, open_air, auditorium]
    address: { type: string, constraint: REQUIRED }
    location: { type: object, shape: { lat, lng }, constraint: REQUIRED }
    distance_from_user_km: { type: float, constraint: REQUIRED, 0-50 }
    alcohol_served: { type: boolean, constraint: REQUIRED }
    food_served: { type: boolean, constraint: REQUIRED }
    parking_available: { type: boolean, constraint: REQUIRED }
    accessibility:
      wheelchair_accessible: { type: boolean, constraint: REQUIRED }
      hearing_loop: { type: boolean, constraint: REQUIRED }

  showtime:
    start: { type: string, constraint: REQUIRED, ISO_DATETIME }
    end: { type: string, constraint: REQUIRED, ISO_DATETIME }
    advance_booking_cutoff: { type: string, constraint: REQUIRED, ISO_DATETIME }
    doors_open_minutes_before: { type: int, constraint: REQUIRED, 0-120 }

  pricing:
    sections:
      type: array<SectionPrice>
      constraint: REQUIRED, ≥1
      shape:
        section_id: { type: string, constraint: REQUIRED }
        section_label: { type: enum, constraint: REQUIRED, STRICT ENUM §6, values: [standard, premium, vip, fan_pit, meet_and_greet] }
        base_price_inr: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0 }
        convenience_fee_inr: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0 }
        gst_inr: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0 }
        total_per_seat_inr: { type: int, constraint: REQUIRED, INR_INTEGER }
    surge_active: { type: boolean, constraint: REQUIRED }
    surge_multiplier: { type: float, constraint: REQUIRED when surge_active=true, 1.0-3.0 }

  availability:
    seats_available_total: { type: int, constraint: REQUIRED, ≥0 }
    seats_available_by_section: { type: object<section_id,int>, constraint: REQUIRED }
    fast_selling: { type: boolean, constraint: REQUIRED, semantics: "TRUE only when seats_available_total / seats_total_capacity < 0.20" }

  policies:
    cancellation:
      cutoff_minutes_before_start: { type: int, constraint: REQUIRED, ≥0 }
      refund_percent: { type: int, constraint: REQUIRED, 0-100 }
    age_restriction_enforced: { type: boolean, constraint: REQUIRED }
    photography_allowed: { type: boolean, constraint: REQUIRED }
    re_entry_allowed: { type: boolean, constraint: REQUIRED }

  partner_reference:
    source: { type: string, constraint: REQUIRED }
    deeplink: { type: string, constraint: REQUIRED, HTTPS URL }

SeatMap, Booking, CancellationResult — same shape as entertainment.book_movie_ticket §5; see that spec for full schemas.

FORBIDDEN FIELDS

  • paid_placement_score, ad_bid, sponsored_rank, promotion_priority, kickback_amount
  • artificial_urgency_text (no "Hurry!" without numeric inventory backing)
  • ai_generated_photo for comedian / venue imagery
  • commission_padded_price
  • unverified_talent_listing — listings where verified=false cannot be ranked above verified ones

SECTION 6 — CONTROLLED VOCABULARIES

preferences.show_format:
  values:
    stand_up:        "Solo stand-up comedy"
    sketch_comedy:   "Sketch / character comedy"
    improv:          "Improvisational comedy"
    open_mic:        "Open mic / mixed performers"
    roast:           "Roast event"
    podcast_live:    "Live podcast recording"
    comedy_festival: "Multi-comic festival lineup"

content_rating_max / content_rating:
  values:
    U:        "Universal — family-friendly"
    UA:       "Parental guidance under 12"
    adult_16: "Adult content, 16+"
    adult_18: "Adult content, 18+"

venue.venue_type:
  values: { comedy_club, theatre, bar_with_stage, hotel_ballroom, open_air, auditorium }

pricing.sections.section_label:
  values:
    standard:        "Standard seating"
    premium:         "Premium (closer / better view)"
    vip:             "VIP (front rows / reserved area)"
    fan_pit:         "Standing room near stage"
    meet_and_greet:  "Includes post-show meet & greet"

content_warnings:
  values: { strong_language, sexual_content, political, religious, dark_humour, audience_participation }

SECTION 7 — TTBS DIMENSIONS

TIME (weight = 0.20):
  signals_used: [distance, showtime fit, advance_booking_cutoff proximity]
  weighting: { distance: 0.30, fit: 0.50, cutoff_proximity: 0.20 }

TASTE (weight = 0.45):
  signals_used:
    - comedian_name exact match
    - language match
    - show_format match
    - content_rating ≤ user max
    - DNA history (comedians/venues user has booked before)
  weighting:
    comedian: 0.45
    format: 0.20
    language: 0.20
    rating_ok: 0.10
    venue_familiarity: 0.05
  user_band_handling:
    fast: relax exact comedian match
    balanced: standard
    flexible: widen show_format set

BUDGET (weight = 0.20):
  signals_used: [pricing min, surge_active]
  weighting: { base_price: 0.70, surge_penalty: 0.30 }

SAFETY (weight = 0.15):
  signals_used:
    - venue.accessibility match
    - policies.age_restriction_enforced (when user_dna indicates minor in party)
    - comedians[].verified (FALSE = filter out)
  weighting:
    accessibility: 0.40
    age_appropriate: 0.30
    verified_talent: 0.30

SECTION 8 — COMPLETION CONTRACT

POST /api/v1/cpc/mcp_provider/<your_partner_id>
Body:
{
  "intent":           "entertainment.book_comedy_show",
  "external_id":      "<booking_id>",
  "request_id":       "<request_id>",
  "amount_inr":       720,     // NET (base × seat_count + supplier-kept convenience)
  "gst_inr":          130,
  "tips_inr":         0,
  "pass_through_inr": 0,
  "closed_at":        "2026-05-15T20:30:00+05:30",
  "status":           "completed",
  "seat_count":       2,
  "show_format":      "stand_up",
  "comedian_name":    "Zakir Khan"
}

HMAC, 5-min replay, NET-only commission.


SECTION 9 — WIDGET

ComedyShowWidget (planned). Falls back to generic ListingsWidget.

Field mapping:
  - show.tour_name + comedians[0].name → header
  - venue.name + distance_from_user_km → subline 1
  - showtime.start + show.duration_minutes + content_rating → subline 2
  - pricing.sections[min].total_per_seat_inr → "From ₹X"
  - availability.fast_selling → red "Fast selling" pill (only when true AND ratio < 20%)
  - comedians[].verified=true → verified-tick badge on poster

SECTION 10 — CACHING POLICY

Call TTL
search_comedy_shows 60s
get_seat_map NO CACHE
create_booking NO CACHE
cancel_booking NO CACHE
Comedian / venue metadata 6h

SECTION 11 — ERROR CODES

Code HTTP Meaning Retry
INVALID_REQUEST 400 Malformed No
RATE_LIMITED 429 Throttle 1, 2s
INTERNAL_ERROR 500 Partner failure 2, exp
SIGNATURE_INVALID 401 (webhook) HMAC fail No
NO_SHOWS_IN_WINDOW 200 (empty) Valid, no matches n/a
COMEDIAN_NOT_TOURING 200 (empty) Requested comedian has no shows in window n/a
SHOW_SOLD_OUT 409 (create) Seats gone No
SEATS_PARTIALLY_UNAVAILABLE 409 (create) Partial availability returned No
BOOKING_WINDOW_CLOSED 410 (create) Past advance_booking_cutoff No
AGE_VERIFICATION_FAILED 403 (create) adult_18 + minor in party No
CANCELLATION_WINDOW_CLOSED 410 (cancel) Past cancellation cutoff No

SECTION 12 — SANDBOX → PRODUCTION CHECKLIST

[ ] All four tools implemented; shapes per §5
[ ] At least 2 real venues + 5 real shows in window
[ ] comedians[].verified=true backed by confirmation evidence (email/DM screenshot from talent)
[ ] All controlled vocabularies respected
[ ] HMAC signing verified
[ ] amount_inr is NET in CPC
[ ] No forbidden fields
[ ] SLA p95 met
[ ] Idempotency tested
[ ] Compliance docs: GSTIN, entertainment license, alcohol license where applicable, privacy policy URL

SECTION 13 — ANTI-FABRICATION RULES

RULE 1: No paid_placement / ad / kickback. Single occurrence rejects response.

RULE 2: comedians[].verified=true requires evidence on file (talent confirmation,
        contract, or talent-agent confirmation). Listings of unverified or
        speculatively-listed talent = suspension after first complaint.

RULE 3: fast_selling=true ONLY when seats_available_total / seats_total_capacity < 0.20.
        Same enforcement as movie_ticket.

RULE 4: surge_multiplier must be a real number reflecting actual markup. Hidden
        surge = suspension.

RULE 5: AI-generated comedian photos forbidden. Use official press/social shots
        under licence.

RULE 6: content_rating must be honest. Listing an 18+ show as U to capture broader
        search = customer harm = suspension.

RULE 7: Reviews / ratings (if added in v1.1) must be unrounded floats from real
        attendees.

RULE 8: No "Top Pick" / "TOMO Recommended" badges. TTBS source-blind.

RULE 9: artificial_urgency forbidden. fast_selling boolean is the only allowed
        scarcity signal.

RULE 10: content_warnings must be honestly disclosed. Hiding political /
         religious / sexual_content warnings = customer harm + suspension.

VERSION HISTORY

v1.0.0 — 2026-05-12 — Initial spec. NET commission base. TASTE-dominant (0.45) —
                       comedy is a performer-match decision.