-
-
The verdict: the pick that lifts the least-satisfied person.
-
Each person lists a few favourites; pick an occasion.
-
Same request answered by an LLM without Qloo.
-
Why not just average: who an average ranking leaves behind.
-
Per-person explanations from Qloo explainability.
-
Every agent step and every Qloo call, shown.
Inspiration
Every group chat has the same thread: "where should we eat?" Three people, three tastes, and the loudest person wins. Ask a general-purpose LLM and you get "something for everyone", which really means nothing for anyone in particular. The model cannot know how much you, a Bon Iver and Parasite person, will like a specific restaurant or film. Qloo can, and it can answer that separately for each person in the group. That is what turns "group recommendation" from a guess into something you can actually make fair.
What it does
Each person enters a name and two to five favourites: artists, films, shows, books, places, brands. You pick an occasion (dinner, night out, movie night, TV night or weekend trip), optionally a city and constraints (budget, vegetarian/vegan/gluten-free/halal, wheelchair access, family-friendly), and press Find common ground.
The agent then:
- resolves every favourite to a real entity in Qloo's taste graph,
- turns constraints like "vegetarian" or "wheelchair accessible" into real Qloo tags,
- builds a candidate pool from the group's combined taste and from each person alone, so a minority taste still gets candidates,
- asks Qloo how much each person would like every candidate, and which of their own favourites drove that score,
- ranks candidates by fairness: it maximises the satisfaction of the least-satisfied member (0.6 × minimum + 0.4 × mean, with a diversity penalty so the three options differ in kind).
You get three picks. Each one shows a satisfaction bar per person, a sentence for each person explaining why it fits them ("Your love of Bon Iver and Radiohead is what Qloo connects this film to"), and the Qloo links behind it. If one person is compromising, the app says so.
It also shows what a plain "average taste" ranking would have chosen and who it would have left behind. In our movie-night example, averaging picks Lady Bird and leaves Marco at 92%. Common Ground picks Captain Fantastic and keeps everyone at 93% or above.
An optional panel runs the same request through the LLM without Qloo. The difference is easy to see: the LLM-only answer mostly echoes the group's own favourites back and once invented a "film adaptation" of a TV series. There are no per-person scores and nothing is verified.
Finally, How the agent decided lists every agent step (and whether the LLM or the deterministic autopilot took it), every Qloo request with its key parameters, and how each favourite was resolved.
How we built it
- Runtime: a single Cloudflare Worker serves the UI (plain HTML/CSS/JS, no build step) and the
/api/planendpoint. - Agent: a tool-using agent on Workers AI (Llama 3.3 70B with function calling). The tools are
resolve_favourites,resolve_constraints,find_candidates,score_pool,rankandrelax. The LLM drives the loop when budget allows; a "light" tier lets the LLM classify favourites and phrase explanations while a deterministic autopilot runs the Qloo plan; with no LLM budget the whole thing runs deterministically with templated text. The product never breaks when the free AI allocation runs out. - Qloo usage:
/searchwith type hints to resolve free-text favourites,/v2/tagswithfilter.queryandfilter.parents.typesto map constraints to tags,/v2/insightswithsignal.interests.entities,filter.location.query,filter.tags,filter.price_level.maxandfilter.content_ratingto build candidates,- and the core:
/v2/insightswithfilter.results.entities+feature.explainability=true, called once per person, to score the same pool for every member and learn which favourites drove each score.
- Parameter safety: Qloo silently ignores parameters that are invalid for an entity type, so every request goes through an allowlist transcribed from the Entity Type Parameter Guide and fails loudly instead of degrading quietly.
- Fairness scoring: pure, unit-tested functions (normalisation per member, maximin score, regret, diversity, compromise flags). 31 unit tests run against a synthetic mock of Qloo, so the repo works without an API key.
- Honest narration: the LLM may only rephrase facts derived from Qloo (satisfaction, linked favourites, shared tags). It is told never to invent venues, plots or prices.
Challenges we ran into
- Cross-type signals. In a live run the LLM classified "Pride and Prejudice" and "Little Women" as books for a movie night. Qloo accepted the request but returned candidates without an affinity for that person, so they scored 0% everywhere. We now detect this, re-resolve that person's favourites as the occasion's own type, score again and say so in the notes.
- Response shapes differ from the docs in small ways. For example, the resolved city comes back under
query.localities.filter. We probed the live API endpoint by endpoint before trusting any field. - Free-tier limits. Workers AI's free daily allocation covers roughly 60 Llama-3.3-70B calls a day, so the agent counts calls in KV and degrades through three tiers instead of failing.
- Speed. One run makes about 15–20 Qloo calls plus a few LLM calls and takes 20–60 seconds. The UI shows progress, and the trace makes the wait legible.
Accomplishments that we're proud of
- The ranking is genuinely different from "average taste", and the app shows exactly when and why.
- Every explanation is traceable to a Qloo response. Nothing in a pick's explanation is invented.
- It runs end to end on free tiers, live, with a deterministic fallback.
What we learned
- Per-person scoring of a fixed candidate pool (
filter.results.entities) is the Qloo feature that makes group fairness possible; everything else is plumbing around it. - Restaurant and bar affinities cluster tightly, so fairness trade-offs show up most clearly for films and TV. Normalising per person matters.
- Building with an AI coding agent was fastest when every assumption about the API was checked against a live response before it reached the code.
What's next
- A shareable link per group, so each person adds their own favourites from their phone.
- Learning from the group's final choice ("we went with option 2") to tune the fairness weights per group.
- More occasions Qloo already covers: podcasts for a road trip, books for a book club, brands for a group gift.
Built With
- cloudflare-kv
- cloudflare-workers
- css3
- html5
- javascript
- llama
- qloo
- workers-ai
Log in or sign up for Devpost to join the conversation.