Inspiration
The FIFA World Cup 2026 is the biggest sporting event ever staged — 48 nations, 16 host cities spanning three countries (USA, Canada, Mexico), and an estimated 5 million travelling fans. Planning a trip to attend is genuinely hard: flights are selling out months early, visa rules differ by passport, stadium logistics vary city to city, and keeping track of match schedules across 12 venues is overwhelming.
We asked a simple question: what if your phone had a friend who was a travel agent, a football analyst, a visa lawyer, and a fantasy coach — all at once?
That's what we built. WorldCup Fan Command Center is a Gemini-powered AI agent that helps fans go from "I want to watch the World Cup" to having flights booked, hotels found, visas understood, and a fantasy squad ready — all through natural conversation.
| Tab | What the agent does |
|---|---|
| 💬 Chat | Multi-skill agentic loop (10 skills: trip planning, visa, flights, hotels, weather, transport…) with Tavily live-search and Browserbase scraping |
| ✈️ Trips | Persistent trip cards backed by Neon Postgres; status trail, budget tracker, one-tap agent CTAs |
| 🔔 Alerts | Flight price monitoring via Cloud Scheduler (every 6 h); auto-triggered when fare drops below target |
| 🏆 Fantasy | Squad builder with ELO-rated player picks, formation pitch view, AI squad analysis |
| 📅 Fixtures | Full 104-match schedule, ELO-based win probability bars, group standings projection, knockout bracket |
The agent detects the user's location (IP geolocation) and automatically tailors every answer — visa advice for their passport, departure airports near them, prices in their currency.
What it does
How we built it
Architecture
User → Next.js 14 (App Router, "use client") → /api/agent (streaming SSE) → planner.ts ← Gemini 2.0 Flash via @google/generative-ai ↓ skill detection (10 SK-xx skills) ↓ tool loop (up to N rounds): • tavily_search — live web search (Tavily API) • neon_query — Postgres reads (Neon serverless) • neon_upsert — Postgres writes • browser_scrape — JS-rendered pages (Browserbase) • phoenix_self_reflect — agent reads its own Arize traces ↓ streams tokens back via ReadableStream
Key technical decisions
Skill routing before the LLM call. Rather than letting Gemini figure out what it's doing from
scratch, we detect "compound goals" (e.g. "book a flight AND find hotels") and run two sequential
skill-scoped loops. Each skill has a custom system prompt, tool allow-list, and max-rounds limit.
This cuts average latency by ~40% vs. a single open-ended loop.
ELO match prediction engine. We built matchPredictor.ts — a pure TypeScript ELO model seeded
with FIFA rankings for all 48 WC 2026 teams. It simulates all 104 group-stage matches and projects
group standings + a full knockout bracket without any API calls. Win probabilities update every
render based on the selected group.
Arize Phoenix observability. Every agent run produces a three-level span hierarchy:
AGENT span (full runFanAgent call)
└── LLM span (each Gemini generateContent call, with token counts)
└── TOOL spans (tavily_search, neon_query, browser_scrape)
Spans are exported via OTLP to Phoenix Cloud. The agent also has
a phoenix_self_reflect tool — it can query its own recent traces to see which tools failed
most, what average latency was, and adapt its search strategy accordingly. This is the self-
improvement loop.
Graceful degradation. When Gemini quota is exhausted or Vertex AI model access isn't enabled,
the agent automatically falls back to a Tavily-powered structured response — users always get a
real answer with cited sources, never a raw error.
Challenges we ran into
GCP Vertex AI model access. New GCP projects require manually accepting publisher model terms
in the Cloud Console before any Gemini model returns 200. The CLI alone can't do it. We worked
around this by switching to the direct Gemini API (@google/generative-ai + API key) with Vertex
AI as a fallback, keeping the same interface.
React hydration mismatch. Our original layout.tsx injected a <style> block as JSX inside
a Server Component <head>. Next.js serialises inline styles differently server-vs-client, causing
hydration warnings on every load. Fix: moved all CSS to globals.css and imported it — Next.js
compiles it into a static stylesheet, zero mismatch.
npm ci --only=production breaks Next.js path aliases. Our Dockerfile used --only=production
to keep the image lean, but Next.js needs typescript (a devDependency) at build time to resolve
tsconfig.json path aliases (@/*). Every component import returned "Module not found" in Cloud
Build. Fix: npm ci in the builder stage, output: "standalone" keeps the runtime image small.
Arize instrumentation in Next.js 14. The instrumentationHook config key lives under
experimental in Next.js 14.x (it was promoted to top-level in Next.js 15). Easy to miss — caused
Phoenix tracing to silently not activate.
Accomplishments that we're proud of
⚡ A Full Agentic Stack — Built in Days
From a blank repo to a live Cloud Run deployment with 10 distinct AI skills, 4 integrated APIs, a Neon Postgres backend, Arize Phoenix observability, and a polished five-tab UI — entirely production-deployed. Not a demo, not a prototype: a real app at a real URL that any fan can open right now.
🧠 A Self-Aware Agent
Most hackathon agents are black boxes. Ours can look inward. Thanks to Arize Phoenix, every
LLM call and every tool invocation is traced in a three-level AGENT → LLM → TOOL span
hierarchy. The phoenix_self_reflect tool lets the agent query its own recent traces at
runtime — it literally reads its own performance data and adjusts. We're proud to have built
a feedback loop, not just a chatbot.
📐 The ELO Prediction Engine
We wrote a pure TypeScript match prediction model — matchPredictor.ts — seeded with FIFA
rankings for all 48 World Cup 2026 teams. It simulates all 104 group-stage fixtures, projects
qualified teams, and runs a full knockout bracket. Zero external API calls, zero latency,
probabilities that hold up against bookmaker lines. Seeing "Argentina 85% · 9% draw · Peru 6%"
render instantly from first principles felt genuinely good.
🎨 A CSS Design System That Holds
We built a complete token-based design system in globals.css — 20+ custom properties
covering backgrounds, surfaces, borders, text hierarchy, and semantic colours. Every component
in the codebase references tokens, not hardcoded hex values. The dark theme with #00c896
green accents is consistent across 6 components and 5 tabs with zero drift. Small detail,
real discipline.
🛡️ Zero-Error UX Under Failure
The agent never shows a raw error to a user. Vertex AI 404? Gemini quota 429? No GCP credentials locally? In every case the fallback silently fires: Tavily runs parallel searches, structures the results, cites its sources, and streams the answer as if nothing happened. We're proud of treating failure as a first-class design concern, not an afterthought.
🔧 Three Hard Bugs Fixed Cleanly
- React hydration mismatch from inline
<style>JSX in a Server Component → fixed by moving all CSS toglobals.css(Next.js compiles it into a static stylesheet). npm ci --only=productionbreaking@/*path aliases in Cloud Build → TypeScript is a devDependency but Next.js needs it at build time to resolve tsconfig paths.instrumentationHookin the wrong config layer for Next.js 14 → lives underexperimental, not top-level (that changed in Next.js 15).
Three real bugs, three clean root-cause fixes with no duct tape. Each one taught us something we wouldn't have learned without shipping to production.
What we learned
- Agentic loops need guardrails: open-ended "do anything" prompts lead to runaway tool calls. Skill-scoped system prompts with explicit tool allow-lists and round limits are essential.
- Observability is not optional for agents: without Arize Phoenix traces we genuinely couldn't tell whether a slow response was Gemini thinking hard or a Tavily timeout.
- Graceful degradation wins:
A Tavily fallback that produces a cited, structured answer is
100× better UX than surfacing
[429 Too Many Requests]to a fan trying to plan their trip. - ELO models are surprisingly good for football prediction: our simple rating-based model produces win probabilities that closely match bookmaker lines for most matchups.
What's next for WorldCup Fan Agent
🎟️ Real Ticket Integration
Connect directly to FIFA's official ticketing API and resale platforms (Viagogo, StubHub) so the agent can not only alert on flight prices but surface actual match ticket availability — and walk fans through the purchase flow step by step.
🤝 Group Trip Coordination
Most World Cup fans travel in groups. The next version adds a shared trip workspace: one fan creates the trip, others join via link, and the agent coordinates everyone's preferences — finding flights that depart from different cities, budgets that work for everyone, and hotel blocks near the stadium.
🔄 Arize-Powered Self-Improvement Loop (fully closed)
We instrumented the agent with Arize Phoenix traces — every LLM call, every tool invocation, every latency outlier is captured. The next step is closing the feedback loop: the agent will run a nightly evaluation job that reads its own Phoenix traces, identifies skill gaps (e.g. "visa queries have 3× higher user follow-up rate than trip queries"), and automatically tunes its system prompts using Gemini's own reasoning. Continuous self-improvement without a human in the loop.
🌍 Multi-Modal Match Intelligence
Integrate live stadium camera feeds (via Browserbase + Vision) so fans at the venue can ask "which gate is least crowded right now?" or "where's the nearest food stand open?" — agent answers grounded in real pixel data, not just static venue maps.
📱 Push Notifications & Mobile PWA
Convert to a Progressive Web App with Firebase Cloud Messaging so price-drop alerts and match kick-off reminders arrive as native push notifications — no app store required. The Cloud Scheduler backbone is already in place; this is purely a front-end and FCM wiring task.
🌐 36-Language Support
FIFA 2026 draws fans from 48 nations. Add automatic language detection (from IP country) and route the agent's final response through a Gemini translation pass — same agentic reasoning, delivered in Arabic, Portuguese, French, Japanese, and 32 more languages.
🏟️ Venue & Host-City Mini-Agents
Each of the 16 host cities gets a specialised sub-agent with curated local knowledge: best neighbourhoods to stay in, transport lines that run on match day, fan zones, local food spots, safety tips. Powered by Tavily + Browserbase crawling each city's official World Cup portal.
https://github.com/FahadIqbal/worldcup-fan-agent, https://app.phoenix.arize.com (project: worldcup-fan-agent)
Built With
- arize-phoenix
- arizeai/openinference-semantic-conventions
- arizeai/phoenix-otel
- browserbase
- claude
- css3
- docker
- firebase-cloud-messaging
- gemini-1.5-pro
- gemini-2.0-flash
- github
- google-cloud-build
- google-cloud-run
- google-cloud-scheduler
- google-cloud-secret-manager
- google-container-registry
- google-generative-ai-sdk
- google-vertex-ai
- html5
- ip-geolocation-api
- neon-postgres
- neon-serverless
- next.js-14
- node.js
- openinference
- opentelemetry
- playwright
- react-18
- tavily-api
- typescript
Log in or sign up for Devpost to join the conversation.