-
-
Three friends in Lagos name their favourites and an affordable vibe
-
A harder group: Nollywood thrillers, action and romance, with almost no overlap
-
Ranked by group fit: the score of whoever likes a pick least, with per-person fit and reasons
-
The agent writes a short plan with one line per person, from Qloo-ranked data
-
Everyone is scored on every film with Qloo, so the middle ground wins: Léon at 59% for all three
-
Every tool call the agent made, from resolving favourites to the group ranking
Inspiration
What it does
How we built it
Challenges we ran into
Accomplishments that we're proud of
What we learned
What's next for Common Ground
Inspiration
Planning a night out is easy until everyone likes different things. In a group chat the loudest person picks, or the group settles on the place nobody minds and nobody loves. A plain LLM makes this worse in a quiet way: ask it for "a restaurant three friends will like" and it gives you a confident, generic answer that has nothing to do with what those three people actually like.
We wanted an agent that knows each person's taste, finds the overlap, and is honest when someone might be left out. That needs real cultural taste data, which is what Qloo has.
What it does
Everyone in the group names a few favourites: artists, films, books, TV shows, places. You pick what you are planning (dinner, movie night, music, book club or a trip), and optionally a city and a vibe such as "affordable, somewhere we can talk after exams".
Common Ground then:
- Finds each favourite on Qloo, and says plainly when one cannot be found.
- Asks Qloo what each person would like, one person at a time, using only that person's favourites as signals.
- Scores every person on every option. A person's own list only covers their top results, so for the rest of the shared pool the agent asks Qloo again with that person's favourites and
filter.results.entitiespinned to those options. Every fit is a real Qloo affinity, never a 0 that just means "not on my list". - Ranks by group fit, which is the score of whoever likes a pick least. A place only ranks high if nobody is left out, and anyone below 35% is flagged ("might suit Tunde less, worth a quick check").
- Explains each pick per person, with reasons built from Qloo data: which of their favourites Qloo says led to the pick (explainability), or the taste tags it shares with them.
- Writes a short, warm plan for the top three picks, with one line per person.
- Shows its work. Every tool call is listed under "How the agent got here".
Example: three friends in Lagos who love Burna Boy, Wizkid, Tems, Things Fall Apart and Half of a Yellow Sun get affordable Lagos restaurants, with Burg.Co at 91% group fit. For movie night, an action fan, a romance fan and a Nollywood thriller fan share almost nothing, yet they get Léon: The Professional, with all three between 59% and 68%. Before we scored everyone on every option, that same group got three picks that each suited only one person.
What makes it Qloo-powered
Without Qloo there is nothing to rank. The ranking, the per-person scores, the "might suit less" flags and the reasons all come from Qloo data:
/searchresolves free-text favourites to Qloo entities across artists, films, books, TV, places and destinations./v2/insightsruns per person withsignal.interests.entities, plusfilter.location.queryfor dinner andfilter.price_level.min/maxfor budget.filter.results.entitiesscores each person on the whole shared pool.feature.explainabilitytells us which favourites led to each result, so a reason is a fact rather than a guess.- A crowd query with everyone's favourites at once adds extra candidates.
/v2/tagslets the agent turn "japanese" or "jazz" into a tag filter.
The language model never chooses or scores places. It calls the tools, then writes the plan from the ranked data, and it is told never to invent places, titles or numbers.
How we built it
- App: Next.js 14 and TypeScript, deployed on Vercel.
- Agent: Vercel AI SDK with tool calling, running
openai/gpt-oss-120bon Groq. Its tools areresolve_group,find_group_picksandfind_tags. Everything users type is wrapped as untrusted data in the prompt. - Planner: a deterministic pipeline in plain functions. It resolves favourites, gets per-person insights, builds a shared pool without the group's own favourites, fills in scores with pinned insights, runs a min-first group ranking, then builds the reasons. If the model is unavailable, the same pipeline writes a plain plan, so the app always answers.
- Budget in code: "cheap", "affordable" or "student" in the vibe sets
filter.price_level.max=2. "Upscale" or "fine dining" sets the minimum to 3. If nothing matches, it falls back to any price with a note. A model never decides that "affordable" means a casino. - Qloo client: server-side only, so the key never reaches the browser. It keeps an in-memory cache with a 10-minute TTL and never writes Qloo data to disk. Calls are spaced to stay under the key's 5 requests a second, a 429 is waited out once, and a dropped request is retried before an item is reported as not found.
- Tests: 57 tests run on an invented mock dataset, so they need no keys. They cover the group ranking, score normalisation, the reasons, input validation, the response parsers, the agent tools and the planner, including "never suggest a favourite back" and "everyone is scored on every pick".
Challenges we ran into
- Groups whose tastes do not overlap. Our first version ranked the union of everyone's top lists. When tastes differed, every candidate was missing from somebody's list and scored 0, so the "fair" ranking had nothing to work with. Pinning each person's insights to the shared pool with
filter.results.entitiesfixed it. - Suggesting your own favourite back. Qloo can return a signal entity among the results. A group that names Pride and Prejudice does not need to be told to watch it, so favourites are now removed from the pool.
- Rate limits on two sides. The Qloo key allows 5 requests a second, and a plan makes about 15 calls. Groq's free tier allows 8,000 tokens a minute. We paced the Qloo calls, cut the model's tool output down to what it needs, and kept the deterministic plan as a fallback.
- Free-text favourites. "Pride and Prejudice" is a book, two films and a TV series. Users can say what kind each favourite is, and the trace shows exactly what each one matched.
Accomplishments that we're proud of
The ranking is fair by construction. A pick one friend loves and another would hate cannot beat a pick everyone likes well enough, and when somebody might be left out, the app says so by name.
What we learned
"Group fit" is a better question than "best match". Asking Qloo about each person separately and then taking the minimum gave far better plans than one combined query, and it made the explanations honest.
What's next for Common Ground
- Share a link to the group, so each friend adds their own favourites from their phone.
- Book or buy straight from a pick.
- Remember a group's past outings, so the next plan adds variety.
Built With
- gpt-oss-120b
- groq
- next.js
- node.js
- qloo
- tailwindcss
- typescript
- vercel
- vercel-ai-sdk
Log in or sign up for Devpost to join the conversation.