One request through the agent · worked example, not a recorded conversation

  1. Visitor

    我明天想去台北看展覽,幫我規劃一日行程

    “I want to see exhibitions in Taipei tomorrow. Plan me a day.”

  2. 01
    get_current_time("Asia/Taipei")

    “Tomorrow” becomes a date. The instructions forbid working out relative dates in its head.

    system.md · tool rules

  3. 02
    plan_itinerary(date="YYYY-MM-DD", start_time="13:00", end_time="20:00")

    Real events on that date from the catalogue the crawlers merge, scored, spread across districts, timed one after another.

    event_tools.py · plan_itinerary

  4. 03
    get_transit_access(event_uid)

    MRT stations within 600 m and bus stops within 400 m of each venue, from TDX.

    event_tools.py · _nearby_metro_stations, _nearby_bus_stops

  5. 04
    recommend_hotels(event_uid)

    Places to stay near the chosen event, picked only from the whitelist of legal stays.

    system.md · “展演錨定式” planning

  6. ExhiBeat AI · reply

    Day 1
    1. [展演] ‹event› | 時間:‹start–end› | 地點:‹venue› | 交通:‹MRT station›
    2. [展演] ‹event› | …
    3. [旅宿] ‹legal stay near an event› | …

    Numbered stops in a fixed format, so the web app can turn the reply into itinerary cards.

Worked example, not a recorded conversation · the request is prompt P09 from the agent’s benchmark; each step follows its instructions and tools · ‹slots› are filled from the live catalogue
← All work

AI agent component · team project

ExhiBeat

The AI agent of a Taipei exhibitions-and-events platform: it finds shows, plans the day and suggests a stay nearby.

GitHub

My part
The AI agent component
Time
2026
Where
YTP 2026 · team project
Kind
Product · AI agent
Tags
AI agent · Google ADK · Gemini · Recommender

Context

ExhiBeat gathers Taipei’s exhibitions and performances from many sites into one place to search, compare and plan. Its AI agent turns a request in plain language into events, a timed route and nearby legal places to stay.

A YTP 2026 hackathon project, built by a team. My part was the AI agent component.

My part

  • The agent backend on Google ADK and Gemini, with its tool chain
  • Transit for every venue: nearby MRT stations and bus stops, from TDX
  • A recommender, and one scoring core shared by the agent and the recommender
  • Semantic embeddings for retrieval, and caches that keep geocoding under its rate limit
  • Personalised recommendations with a local fallback, and the deployed agent backend
  • A ten-prompt benchmark for the agent

The system

  1. Web appReact + Vite
  2. API proxyFastAPI, Cloud Run
  3. AgentGoogle ADK + Geminimy commits
  • Time and weather · 2

    get_current_timeget_weather

    reads: Open-Meteo

  • Events · 6

    sync_event_catalogsearch_eventsrecommend_eventssearch_events_near_placeget_event_detailget_nearby_events

    reads: merged exhibition data · SQLite · embeddings

  • Getting there · 1

    get_transit_access

    reads: TDX (MRT, bus) · Nominatim

  • Places to stay · 2

    recommend_hotelscheck_hotel_legality

    reads: legal-stay whitelist

  • Plans · 4

    add_to_favoritesget_favoritesplan_itinerarygenerate_itinerary

    reads: favourites · events

The agent and its 15 tools, from the repository · the agent backend and every tool first landed in my commits; teammates refined several later · the crawlers, data and web app are the team’s

Making of

  1. 01 Problem

    The geocoder said 429

    Placing venues on the map meant looking up addresses with a free geocoding service, which started refusing requests: HTTP 429, too many.

    Source · backend/adk_agent/gemini_agent/tools/event_tools.py · commit d0cc565, 2026-04-25

  2. 02 Decision

    Ask less, and wait when told

    Coordinates for Taipei’s districts and its popular venues are cached in the code, lookups are spaced a second apart, and a refused request is retried with a growing wait.

    Source · commit d0cc565, 2026-04-25

The cover used for this project on lists is a generated illustration, not a photograph of the system.