Inspiration
Every group chat hits the same wall: where do we go tonight? Someone picks the usual place and half the table is not happy. Chat assistants don't help much. They know nothing about the people, so they suggest famous places that ignore what each person likes and often cost more than the group wanted to spend. Then someone still has to chase everyone for money. We wanted an agent that plans for the whole group, from each person's real tastes, and closes the loop with payment.
What it does
- Add the people (2–8) and two or three things each of them loves (a band, a film, a book, a show), or just describe the plan in one sentence ("Team dinner in Milan, about €40 each. Sara: Radiohead, Murakami…").
- The agent resolves every favourite to a Qloo entity (with alternatives you can switch, e.g. Haruki vs. Takashi Murakami).
- For each person, Qloo Insights ranks real venues in the city by affinity to their taste. The agent scores every candidate for every person and ranks fairly: the least-happy person first, then the average, within the budget. It keeps only real restaurants / bars / museums using Qloo's primary genre and popularity. Group needs such as "vegetarian" or "live music" become Qloo tags that filter the venues, and a pick shows a ✓ badge only when Qloo's data for that venue supports the need.
- Each pick shows a per-person fit bar, the taste tags the group shares (e.g. Cinematic · Modern art · Film history for a Wes Anderson-designed bar), a grounded explanation, today's hours, what people mention, highlights, atmosphere and food, all from Qloo, plus map, website, menu and phone links.
- Side by side: the same brief answered by an LLM without Qloo, and every place it named is fact-checked against Qloo's place data: found in the city, in another city, not found, or over budget. The page says which model answered.
- Pick one and everyone pays their own share with PayPal (sandbox), by wallet or an inline card form, with a group pot and a receipt page verified live with PayPal.
Small towns work too: when Qloo can't resolve a town by name (e.g. Molfetta), the agent geocodes it with OpenStreetMap and searches within 12 km of its coordinates.
Measured: why Qloo matters here
We ran 10 dinner plans (Milan, London, New York, Paris, Barcelona; two groups of three people) through TastePay and through a free LLM given the exact same brief, then checked every place against Qloo (scripts/measure.ts, results in docs/proof/ of the repo):
- Places in the requested city: TastePay 30 of 30; the LLM 19 of 21 (90%).
- Over the per-person budget, where Qloo knows the price level: TastePay 0 of 23; the LLM 5 of 19 (26%).
- Based on each person's taste: TastePay ranks every pick on each person's Qloo affinity (mean group fit 0.80); the LLM has no taste data.
The LLM usually names real, famous places. What it can't do is know the people: it ignores what each of them likes and often breaks the budget. That's the gap Qloo fills.
How we built it
- Qloo:
/search(artist, movie, TV show, book, author, person, podcast, video game, brand) to resolve tastes;/v2/insightswithfilter.type=urn:entity:place,filter.location.queryorfilter.location+ radius,filter.tagsandsignal.interests.entities, once per person and for the whole group (two pages);/searchwithtypes=urn:entity:placefor the fact-check, near the requested city first (filter.location.query), then worldwide. Entity properties (primary genre, popularity, hours, keywords, descriptions, images) power filtering and the venue cards. - Group needs as Qloo tags: a plan can carry needs such as "vegetarian", "gluten-free", "kid-friendly" or "live music", typed in the form or read from the brief ("Sara is vegetarian", also in Italian). Each need is looked up at run time with
GET /v2/tags(filter.query,filter.tag.typeslimited to tag families that describe a venue), and only tags whose name says the same thing are kept. One/v2/insightssample of 50 venues in the city shows which of those tags venues actually carry; the most carried one becomes the filter (filter.tagswithoperator.filter.tags=intersection). If too few places pass, the least carried need moves to a boost inside the filter (signal.interests.tags); if none can be applied, the rest is ranked on taste alone, and the trace says so. A pick shows a ✓ badge naming the venue's own Qloo tag (for example "✓ Vegetarian meals") only when that venue's tags (or itsgood_for/live_musicproperties) support it. An optional group age bracket is passed assignal.demographics.age. - Agent: one Netlify Function per step (understand → resolve → constraints → rank → explain → compare) so each answers within the serverless time limit and the page shows the agent's trace live.
- LLMs: OpenRouter free models in a short chain with time budgets and answer validation (
openrouter/freeas last resort). Every LLM step has a deterministic fallback, so the Qloo plan never depends on a model. When no free model answers the comparison, the page shows an answer recorded earlier for the same built-in example, labelled with its model and date, and still fact-checks it live. - Payments: PayPal Orders v2 in the sandbox, created and captured server-side; PayPal Card Fields for card payments without a PayPal account.
- Frontend: vanilla HTML/CSS/JS, no build step; all model output inserted as text.
- Quality: 61 unit tests with synthetic fixtures (no Qloo data committed), live smoke tests across Milan, Rome, London, New York, Berlin and Molfetta, a live check of needs resolved to Qloo tags (Milan vegetarian, London live music, a need with no Qloo tag), the measured comparison above, and a dependency audit with zero known vulnerabilities.
Challenges we ran into
- Qloo's tag filter also returns malls, markets, hotels and wedding venues that merely contain a restaurant: we filter on each venue's
primary_genre, drop little-known places when enough remain, and read two pages for the group pool. - Bursts of Qloo calls get HTTP 429: at most two calls in flight, retries with back-off, and a plan that survives one failed person.
- Small towns are not resolvable by name: geocoding + radius search.
- Free LLMs are often rate-limited: time budgets, fallbacks and caching.
- Fact-checking names fairly: whole-word matching, so "Ratanà" is not confused with "Ratanakorn market". Measuring showed one more trap: a worldwide search for "Ristorante Cracco" returns Cracco Portofino first, so the real Milan restaurant looked like "another city". The fact-check now searches near the requested city first.
Accomplishments that we're proud of
- A complete product loop (taste → fair group plan → explanation → payment and receipt), live and usable without any key or login.
- A concrete, visible answer to "why not just ask an LLM?": the side-by-side fact-check against Qloo's place data, backed by a measured comparison anyone can rerun.
- Fairness built in: nobody's taste is sacrificed for the majority.
What we learned
- Taste is personal but plans are collective: per-person affinity plus a fairness rule beats a single blended signal.
- Grounding matters: Qloo's entity data improves the recommendations and lets us check what an LLM claims.
- Measure before claiming: our first fact-check over-reported the LLM's mistakes. Running it on real answers showed the real gap, taste and budget, and a bug in our own matching.
- Serverless agents need step-sized calls, budgets and graceful degradation.
What's next for TastePay
- "All or nothing" payments: authorize each share, capture only when everyone is in.
- Paying the venue directly (PayPal for marketplaces) or the organiser who books.
- Group invites by link, so each person adds their own tastes from their phone.
- More occasions (concerts, trips with itineraries) using Qloo's other entity types.
Pre-existing work and disclosure
Built during the hackathon (October 2026) with an AI coding assistant. Uses Qloo's hackathon API, OpenRouter (free models), PayPal sandbox, OpenStreetMap Nominatim (geocoding fallback) and Netlify. No Qloo response data is stored in the repository, apart from the summary of the 10 measured plans in docs/proof/ (venue names, cities, price levels, fit scores and verdicts). In the demo video, the short lifestyle clips were generated with Higgsfield (Kling); the app footage is a real recording.
Built With
- css3
- html5
- javascript
- netlify
- openrouter
- openstreetmap
- paypal
- qloo
- typescript
- vitest