What inspired me

Independent musicians and comedians pick tour cities by instinct, then pitch the same famous brands as everyone else. A general chatbot can't fix that, because it has no data on where a particular act's audience actually is, so it names the biggest cities and the best-known brands. Qloo does have that data, so I wanted to see what a tour manager could do if every decision came from taste data.

What it does

Afinlo is an AI tour manager that knows your fans. Name an artist or comedian and where they're touring, anywhere in the world. Afinlo maps where their fans are, plans the route, finds the venues and brands those fans already love, and drafts the hold requests and sponsor pitches. Each tour has its own team of AI agents you can talk to: ask why a city is on the route, ask for 8 shows instead of 7, or ask for a pitch in Spanish.

How I built it

Qloo first. Every venue, brand and act comes from Qloo, and every tour lists its Qloo requests. Plain, unit-tested TypeScript does the scoring, so the same Qloo answers always give the same plan:

$$\text{Fan Heat} = 100 \cdot \frac{a - a_{\min}}{a_{\max} - a_{\min}} \qquad \text{Tour score} = 0.75\,H + 0.25\,S$$

Here $a$ is a city's Qloo affinity within the area, $H$ is its Fan Heat, and $S$ is its market size on the same 0–100 scale. A tour draws on 2,737 cities across 184 countries (Natural Earth), one per metro area, with no two stops within 150 km.

A real multi-agent team. A tour manager built on LangGraph hands work to four specialists: route planner, venue booker, sponsor scout and promoter. They can run in parallel, and each has its own prompt, tools and context. Conversations are saved in Postgres, and older messages fold into a running summary.

Code keeps the AI honest. The model only words what the tools found. A change to the tour is a proposal the user applies. Drafts are checked in code before they're saved, and any sentence claiming money, ticket sales or a brand having agreed is removed from the reply.

The interface. Next.js 16 and React 19, with MapLibre GL for the fan heatmap and route, and GSAP and Lenis for the landing page.

Challenges I faced

  • Qloo's data varies by act. Some comedians have no location data, so Afinlo falls back to acts with overlapping audiences and labels that clearly instead of guessing.
  • Heatmap cells aren't cities. The strongest affinity can sit in a tiny town, so Afinlo scores real tour markets, one per metro.
  • Affinity is relative. It's a rank within the area you ask about, so each tour's area is a single heatmap query, and cities are only compared within it.
  • Thin venue data. Qloo tags few venues in some cities, so Afinlo widens to live-music and event venues there, and says so when there are none.
  • Keeping a model grounded. Testing against the live model showed agents reciting definitions in sponsor emails and misaddressing drafts. I fixed these and built an evaluation that checks each reply against the tour's own data.

What I learned

Fan Heat measures taste, not ticket demand, and the product has to say so. Being honest about what the data can't prove made Afinlo more useful, not less.

I also learned that agents get reliable when code owns the facts and the model owns the wording. The best improvements came from tighter tools, not longer prompts.

And cost is a design problem. Splitting each agent's instructions into a fixed part and a changing part let OpenAI's prompt cache serve 84% of input tokens in my evaluation run, measured call by call.

Built With

Share this project:

Updates

Submission history