Inspiration

A boutique hotel's concierge hands every guest the same list of restaurants and bars. The guest who lives in Dr. Martens and plays Amy Winehouse gets the same ten places as the couple who came for Bridgerton and Jo Malone. The concierge knows the list is generic; there is no time to rewrite it for every arrival.

What it does

Your Kind of Place is for the concierge and guest-experience desk of a boutique hotel. It takes the hotel's list and returns it per guest in track-changes mode: places this guest's taste points away from are struck through in red, places that fit this guest are inserted in green, and every change carries a margin note that says why. The places and the reasons come from Qloo's taste graph; the language model never picks a place or writes a reason.

  • Before and after on the first screen. The list every guest gets on the left, the same list for Guest 1 on the right, no click needed.
  • Two guests, one hotel. In London, Guest 1 (Amy Winehouse + Dr. Martens) and Guest 2 (Bridgerton + Jo Malone) start from the same ten places. Afterwards their two versions share 1 of 10. Guest 1 gets cocktail and rooftop bars (Sky Pod Bar, Savage Garden, Disrepute in Soho, Mr Fogg's Gin Parlour); Guest 2 gets Caviar House Piccadilly, Bustronome, 34 Mayfair, Oblix and Aqua Nueva.
  • At the hotel's level. Inserts never go below the list's own Qloo price level, and on an upscale list no pub replaces a restaurant. For a guest who loves Fela Kuti and Carhartt, an upscale London list now gains Ronnie Scott's, Dukes Bar and Punch Room instead of a row of Westminster pubs.
  • Margin notes from Qloo. Inserted: "Because the guest loves Dr. Martens · live music · elegant · late night", the favourite with the highest Qloo explainability score for that place, then the place's own Qloo tags, with the guest's Qloo affinity as a small bar. Struck: "Lowest taste affinity on this list for this guest", Qloo's affinity for exactly the places on the list.
  • A message the guest can read. "Message for the guest" writes a short letter with salutation, hotel name, arrival date and a Google Maps link for every place, in English, German or French (the guest's language can differ from the desk's). "Copy for WhatsApp", "Copy for email" or print; nothing is sent from the app.
  • Tomorrow's arrivals → morning report. Paste up to six arrival notes as the front desk wrote them ("Room 204: Ms Patel. Loves Amy Winehouse, always in Dr. Martens. Nut allergy."). An agent reads the favourites, the concierge confirms them, and the morning report has one edited list per room. What the edit doesn't use stays visible ("Not considered: Nut allergy", "anniversary", "Quiet room please"), and each room shows how many of its additions other rooms also got. The four sample rooms were chosen from twelve candidate profiles to show contrast, and the app says so; any notes can be pasted instead.
  • The hotel's own list. Paste up to 10 places. Each line is matched to a restaurant or bar in Qloo within 25 km ("Dishoom" → Dishoom King's Cross). Lines Qloo can't match, and the hotel's own places ("Our rooftop bar"), stay on the list and are never struck.
  • Restaurants & bars, or live music & nightlife. For an Amy Winehouse fan, the nightlife list gains The Underworld, Electric Ballroom and The World's End in Camden and Chalk Farm. A kind of place goes into the product only after it passes a blind test (below).
  • Agentic. A Google ADK agent takes free text ("Guest checking in tonight: loves Fela Kuti and Carhartt, shellfish allergy"), resolves the favourites in Qloo, asks when a name is ambiguous ("Dune (movie, 2021) · Dune (artist) · Dune (movie, 1984) · None of these"), runs the same edit, and lists what it didn't consider. Its tool calls stream to the screen while it works. A second ADK agent reads the arrival notes. The same capability is an MCP tool for agents a hotel already runs.
  • Day and night, three languages. A cream day look and a warm dark night look (following the system setting, remembered once switched), both checked for WCAG AA contrast at 1366 and 390 px; English, German and French throughout, including "How this works". Place names and Qloo's tags stay as Qloo has them.
  • Client demo. The gold button opens what a guest of Montreonto Hotels, a fictional hotel with houses in Toronto and Montreal, sees on their phone after check-in: the house list edited for them, with a Map link on every place (both cities passed the same blind test, 12 of 12): https://your-kind-of-place.vercel.app/client?city=Toronto
  • Links that open a view. The view lives in the URL, so these open directly: Guest 1 https://your-kind-of-place.vercel.app/?tab=g1&ex=0&lines=5 · both guests https://your-kind-of-place.vercel.app/?tab=both&ex=0&lines=5 · nightlife for an Amy Winehouse fan https://your-kind-of-place.vercel.app/?tab=own&city=London&kind=nightlife&fav=Amy%20Winehouse&id=10AE6E44-D058-4C1D-818F-FF4B37D069CB

Why it needs Qloo, and why not a language model alone. Without a taste signal there is nothing to edit by: in our test, a guest's list and the list with no taste signal overlapped only 0.12. Take Qloo away and the app has no per-guest affinity for the hotel's own places (so nothing decides what to strike), no explainability score (so nothing to write in the margin) and no price level (so nothing keeps an insert at the hotel's level). A language model alone could rewrite the list, but not with a measured reason per line; in this app the model only reads free text and calls tools, and the server replaces any agent sentence that names a number the tools didn't return or compares the list to anything.

Who pays (our intention, not tested with hotels yet). The hotel: a per-property subscription for the concierge and guest-experience desk, used every morning on tomorrow's arrivals. We have no customers and no pricing data yet, so we state no figures.

How we built it

Next.js (Vercel) ──server-side proxy──▶ FastAPI + 2 ADK agents (Cloud Run) ──▶ Qloo API
                                              ├─ Claude via LiteLLM (agents only)
                                              ├─ /mcp  edit_hotel_list(city, interests[], budget, hotel_list[], category)
                                              └─ private request-hash cache (never in the repo)
  • Qloo /search resolves favourites across artists, TV shows, films, brands and games (one exact, clearly dominant match is taken and its type shown; anything else becomes a question with the year for films and shows) and matches hotel-list lines to places.
  • Qloo /v2/insights, four ways:
    1. the city's top places with no signal (the default list),
    2. the guest's top 50 places with the favourites as signal.interests.entities and feature.explainability=true (which entries are safe, and the reasons),
    3. the same at the list's level with filter.price_level.min (the inserts),
    4. the guest's affinity for exactly the places on the list via filter.results.entities (which entries to strike first, and the bars).
  • Deterministic edit (backend/app/list_edit.py): strike entries outside the guest's top 50, lowest affinity first, up to "Lines that may change" (3/5/10); insert the best matches not yet on the list, at or above the list's median Qloo price level; never pad. Notes take the place's own Qloo tags (interest, ambience, late night).
  • Dining filter: Qloo's restaurant tag also returns hotels, department stores, arenas and fast food, and exclude.tags is ignored by the API, so we filter by properties.primary_genre, drop well-known chains, theme venues (Qloo decor tag "Themed") and anything at an airport or over 25 km from the centre (New York is queried as "New York City").
  • Agents: Google ADK LlmAgent with function tools (resolve_interest, default_list, taste_places, edit_list, explain_place, not_considered; record_guest for arrivals), streamed to the UI as newline-delimited JSON. The server checks the agents' work: a favourite or a "not considered" item from a note is kept only if it is written there (and a favourite only if not negated, "hates Coldplay"); the agent's sentence is replaced by a plain summary if it names a number the tools didn't return or uses a comparison word, in English, German and French.
  • Honest fallbacks: if Qloo is unreachable, saved answers are used and labelled "cached result"; arrivals work without the model ("Skip the agent").

Challenges we ran into

  • The first strike rule ("lowest on the list first") made every guest lose the same entries. Restricting Insights to the list's own places (filter.results.entities) gave a per-guest affinity, and now two guests strike different entries.
  • A hands-on test showed inserts below a luxury hotel's level (a tourist Irish pub replacing The Ledbury). We added the price-level rule and re-ran the blind test before keeping it (10 of 12, one fewer than without the rule).
  • Matching free-typed hotel lists: "Our rooftop bar" matched a competitor's "Magic Hour Rooftop Bar" until we matched on whole words and treated "our/my/hotel's/in-house" lines as the hotel's own.
  • Plain "New York" also returned places across New York State; querying "New York City" plus a 25 km radius fixed it.

What did not work

Five more kinds of place failed or were left out after the same blind test: parks (8 of 12), shops (9), cafés (5), spa (4) and sights (3); museums passed at 10 of 12 but two opposite guests shared most museums, so we left them out too.

Accomplishments that we're proud of

We measured before we built, on 12 pairs of deliberately opposite guests in San Francisco, Austin and London, with the threshold written down before each run:

  • a separate model matched each pair of lists to the right guest 10 of 12 times without knowing about Qloo, with the product's price-level rule (11 of 12 without the price-level rule);
  • the same queries 14 minutes later overlapped 0.99;
  • a guest's list and the no-signal list overlapped 0.12.

Kinds of place: live music & nightlife 10 of 12 (offered); museums 10 of 12 (passed, left out), parks 8, shops 9, cafés 5, spa 4, sights 3 of 12 (not offered). All of them are listed on https://your-kind-of-place.vercel.app/how.

Limits, stated in the app: fits this guest, not "better". Even similar tastes get different lists, so we claim nothing about similar guests. The judge was a model, and the sample is small.

What we learned

Qloo's explainability turns a ranking into a sentence a concierge can pass on ("Because the guest loves Amy Winehouse · live music · late night"), and an affinity restricted to a known set of places turns a recommendation engine into an editor.

What's next

Pick the right branch when a hotel-list name matches several places; connect to a hotel's PMS so arrival notes arrive by themselves; test with two pilot hotels before naming a price.

Sample guests are fictional. Artist, show and brand names only describe what a guest likes; no affiliation with or endorsement by them is implied.

Built With

Share this project:

Updates

Submission history