🗺️ WanderGenie - High-Level Architecture
┌─────────────────────────────────────────────────────────────────────────────┐
│ USER INTERFACE │
│ (Next.js + Tailwind) │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Chat Pane │ │ Itinerary │ │ Interactive │ │ Booking │ │
│ │ "5 days in │ │ Timeline │ │ Map │ │ Links │ │
│ │ NYC..." │ │ Component │ │ (Mapbox/OSM) │ │ + Calendar │ │
│ └──────┬───────┘ └──────▲───────┘ └──────▲───────┘ └──────▲───────┘ │
│ │ │ │ │ │
│ │ └──────────────────┴──────────────────┘ │
│ │ trip.json updates │
└─────────┼─────────────────────────────────────────────────────────────────┘
│
│ WebSocket / REST API
│
┌─────────▼─────────────────────────────────────────────────────────────────┐
│ BACKEND ORCHESTRATOR │
│ (FastAPI + LangGraph) │
│ │
│ ┌───────────────────────────────────────────────────────────────────┐ │
│ │ LangGraph State Machine │ │
│ │ │ │
│ │ START → Planner → Researcher → Packager → Validator → END │ │
│ │ │ │ │ │ │ │
│ │ └──────────┴────────────┴───────────┘ │ │
│ │ Shared State: trip.json │ │
│ └───────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ TOOL REGISTRY │ │
│ │ • poi_search() • build_flight_link() │ │
│ │ • get_open_hours() • build_hotel_link() │ │
│ │ • distance_calc() • export_calendar() │ │
│ │ • validate_schema() • make_geojson() │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
│ │ │
│ │ │
┌─────────▼──────────┐ ┌──────▼─────────┐ ┌──────▼──────────┐
│ AGENT LAYER │ │ MEMORY LAYER │ │ EXTERNAL APIs │
└────────────────────┘ └─────────────────┘ └──────────────────┘
🤖 Agent Architecture (3 Agents)
┌──────────────────────────────────────────────────────────────────────────┐
│ LANGGRAPH WORKFLOW │
└──────────────────────────────────────────────────────────────────────────┘
USER PROMPT: "5 days in NYC from Buffalo, Dec 20-25, with teen"
│
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ AGENT 1: PLANNER │
│ ┌────────────────────────────────────────────────────────────────┐ │
│ │ Role: Intent Parser & Trip Designer │ │
│ │ Input: Raw user text │ │
│ │ Output: Structured intent JSON │ │
│ │ { │ │
│ │ "city": "New York City, NY", │ │
│ │ "origin": "Buffalo, NY", │ │
│ │ "start_date": "2025-12-20", │ │
│ │ "nights": 5, │ │
│ │ "party": {"adults": 2, "kids": 1}, │ │
│ │ "prefs": {"pace": "moderate", "interests": ["views","food"]}│ │
│ │ } │ │
│ └────────────────────────────────────────────────────────────────┘ │
│ LLM: Claude (Bedrock) / GPT-4o-mini │
└──────────────────────────┬───────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ AGENT 2: RESEARCHER │
│ ┌────────────────────────────────────────────────────────────────┐ │
│ │ Role: POI Discovery & Enrichment │ │
│ │ Input: intent JSON │ │
│ │ Process: │ │
│ │ 1. Call OpenTripMap API → get POI candidates │ │
│ │ 2. Query VectorDB → enrich with booking notes, tips │ │
│ │ 3. Query GraphDB → cluster by neighborhood, find similar │ │
│ │ Output: poi_candidates[] │ │
│ │ [{ │ │
│ │ "name": "Statue of Liberty", │ │
│ │ "lat": 40.6892, "lon": -74.0445, │ │
│ │ "tags": ["landmark", "view"], │ │
│ │ "duration_min": 180, │ │
│ │ "booking_required": true, │ │
│ │ "booking_url": "https://...", │ │
│ │ "notes": "Ferry queues; go early" │ │
│ │ }] │ │
│ └────────────────────────────────────────────────────────────────┘ │
│ LLM: Claude + APIs │
└──────────────────────────┬───────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ AGENT 3: PACKAGER-EXECUTOR │
│ ┌────────────────────────────────────────────────────────────────┐ │
│ │ Role: Itinerary Builder & Output Generator │ │
│ │ Input: poi_candidates[] + intent │ │
│ │ Process: │ │
│ │ 1. Cluster POIs by day (proximity, hours, preferences) │ │
│ │ 2. Generate time blocks (09:00-18:30, insert lunch/breaks) │ │
│ │ 3. Query GraphDB → minimize cross-town travel │ │
│ │ 4. Calculate distances → add travel estimates │ │
│ │ 5. Build flight/hotel deep links │ │
│ │ 6. Generate map GeoJSON │ │
│ │ 7. Create calendar events (.ics or Google Calendar) │ │
│ │ Output: Complete trip.json │ │
│ │ { │ │
│ │ "days": [...], │ │
│ │ "links": {"flights": "...", "hotels": "..."}, │ │
│ │ "map_geojson": {...}, │ │
│ │ "calendar_export": {...} │ │
│ │ } │ │
│ └────────────────────────────────────────────────────────────────┘ │
│ LLM: Claude + Deterministic Tools │
└──────────────────────────┬───────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ VALIDATOR (Tool, not full agent) │
│ • JSON schema validation │
│ • Check overlaps, hours, distances │
│ • Auto-patch minor issues │
│ • Return warnings for UI │
└──────────────────────────┬───────────────────────────────────────────────┘
│
▼
trip.json → UI
🧠 Memory Layer Architecture
┌─────────────────────────────────────────────────────────────────────────┐
│ MEMORY SYSTEMS │
└─────────────────────────────────────────────────────────────────────────┘
┌──────────────────────────┐ ┌──────────────────────────┐ ┌───────────────────┐
│ VECTOR DATABASE │ │ GRAPH DATABASE │ │ STATE STORE │
│ (Supabase pgvector) │ │ (Neo4j Aura Free) │ │ (Supabase) │
├──────────────────────────┤ ├──────────────────────────┤ ├───────────────────┤
│ │ │ │ │ │
│ Collection: poi_facts │ │ ┌─────────────────┐ │ │ trip.json │
│ ┌──────────────────────┐ │ │ │ (:City) │ │ │ { │
│ │ • name │ │ │ │ │ │ │ │ trip_id, │
│ │ • city │ │ │ │ ▼ │ │ │ user_id, │
│ │ • coords │ │ │ │ (:Neighborhood) │ │ │ state, │
│ │ • booking_required │ │ │ │ │ │ │ │ version, │
│ │ • booking_url │ │ │ │ ▼ │ │ │ intent, │
│ │ • hours_text │ │ │ │ (:POI) │ │ │ poi_candidates,│
│ │ • tags[] │ │ │ │ │ │ │ │ days[], │
│ │ • popularity │ │ │ │ ▼ │ │ │ links │
│ │ • body (text) │ │ │ │(:TicketProvider)│ │ │ } │
│ │ • embedding (vector) │ │ │ └─────────────────┘ │ │ │
│ └──────────────────────┘ │ │ │ │ Checkpointer: │
│ │ │ Relationships: │ │ LangGraph state │
│ Collection: rules │ │ • IN_NEIGHBORHOOD │ │ per execution │
│ ┌──────────────────────┐ │ │ • SIMILAR_TO │ │ │
│ │ • rule_text │ │ │ • REQUIRES_TICKET │ └───────────────────┘
│ │ • city (optional) │ │ │ • NEAR │
│ │ • tags[] │ │ │ │
│ │ • embedding │ │ │ Queries: │
│ └──────────────────────┘ │ │ • Find POIs in same │
│ │ │ neighborhood │
│ Use Cases: │ │ • Get SIMILAR_TO │
│ • Augment POI data │ │ alternatives │
│ • Find booking tips │ │ • Cluster by proximity │
│ • Retrieve constraints │ │ • Get ticket vendors │
│ • Context for packing │ │ │
└──────────────────────────┘ └──────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ TOOL REGISTRY │
│ (Called by LangGraph Agents) │
└─────────────────────────────────────────────────────────────────────────┘
POI & ENRICHMENT TOOLS PLANNING TOOLS OUTPUT TOOLS
┌─────────────────────────┐ ┌─────────────────────┐ ┌──────────────────┐
│ poi_search() │ │ distance_calc() │ │ build_flight_ │
│ → OpenTripMap API │ │ → Haversine │ │ link() │
│ │ │ │ │ │
│ get_open_hours() │ │ validate_schema() │ │ build_hotel_ │
│ → Curated data │ │ → JSON Schema │ │ link() │
│ │ │ │ │ │
│ vectordb_retrieve() │ │ check_overlaps() │ │ export_calendar()│
│ → Similarity search │ │ → Time logic │ │ → .ics or │
│ │ │ │ │ Google Cal │
│ graphdb_query() │ │ pack_day() │ │ │
│ → Cypher queries │ │ → Greedy algo │ │ make_geojson() │
│ │ │ │ │ → Map features │
└─────────────────────────┘ └─────────────────────┘ └──────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ EXTERNAL SERVICES │
└─────────────────────────────────────────────────────────────────────────┘
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ LLM PROVIDER │ │ POI DATA │ │ BOOKING LINKS │
├──────────────────┤ ├──────────────────┤ ├──────────────────┤
│ │ │ │ │ │
│ AWS Bedrock │ │ OpenTripMap API │ │ Google Flights │
│ • Claude 3 │ │ • Free tier │ │ (deep link) │
│ • Fallback: │ │ • POI search │ │ │
│ OpenAI │ │ • Coordinates │ │ Booking.com │
│ GPT-4o-mini │ │ • Categories │ │ (deep link) │
│ │ │ • Hours │ │ │
└──────────────────┘ │ │ │ Attraction sites │
│ Fallback: │ │ • Statue Cruises│
┌──────────────────┐ │ nyc_pois.json │ │ • SUMMIT │
│ MAP PROVIDER │ │ (offline cache) │ │ • etc. │
├──────────────────┤ │ │ │ │
│ │ └──────────────────┘ └──────────────────┘
│ Mapbox GL JS │
│ OR │ ┌──────────────────┐
│ Leaflet + OSM │ │ CALENDAR │
│ │ ├──────────────────┤
│ • Pins │ │ │
│ • Clustering │ │ Google Calendar │
│ • Route lines │ │ • OAuth 2.0 │
│ │ │ • Create events │
└──────────────────┘ │ │
│ Fallback: │
│ .ics download │
│ │
└──────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ REQUEST → RESPONSE FLOW │
└─────────────────────────────────────────────────────────────────────────┘
1. USER INPUT
│
├─→ "Planning to visit NYC for 5 days from Buffalo with a teen"
│
▼
2. PLANNER AGENT
│
├─→ Parse intent
├─→ Extract: city, dates, party, preferences
├─→ Output: intent JSON
│
▼
3. RESEARCHER AGENT
│
├─→ Call OpenTripMap(city="NYC", interests=["teen-friendly"])
├─→ Query VectorDB("NYC attractions teen friendly", k=12)
├─→ Query GraphDB(MATCH (p:POI)-[:IN_NEIGHBORHOOD]->(:Neighborhood)...)
├─→ Merge & dedupe results
├─→ Output: poi_candidates[] (20-30 POIs)
│
▼
4. PACKAGER-EXECUTOR AGENT
│
├─→ Score POIs (interest_match + popularity - travel_penalty)
├─→ Greedy pack by day:
│ • Day 1: Lower Manhattan cluster
│ • Day 2: Midtown cluster
│ • Day 3-5: Upper Manhattan, Brooklyn, etc.
├─→ Insert time blocks (09:00, lunch 12:30, 14:00, etc.)
├─→ Calculate distances (GraphDB + Haversine)
├─→ Build links: Google Flights(BUF→NYC), Booking.com
├─→ Generate GeoJSON for map pins
├─→ Create calendar events
├─→ Output: Complete trip.json
│
▼
5. VALIDATOR (Tool)
│
├─→ Validate JSON schema
├─→ Check overlaps, closing times
├─→ Verify distances reasonable
├─→ Auto-patch if fixable
├─→ Output: {ok: true, warnings: [...]}
│
▼
6. RESPONSE TO UI
│
└─→ {
"days": [Day 1, Day 2, ...],
"links": {"flights": "...", "hotels": "..."},
"map_geojson": {...},
"calendar_export": {...}
}
7. UI RENDERS
│
├─→ Timeline component shows day blocks
├─→ Map shows pins + routes
├─→ Booking buttons active
└─→ "Add to Calendar" ready
🔄 Edit Flow (Conversational Updates)
USER: "Swap Day 3 afternoon for MoMA"
│
▼
BACKEND receives: {trip_id, edit_instruction, current_trip.json}
│
▼
PLANNER AGENT
│
├─→ Parse edit intent
├─→ Identify target: Day 3, afternoon block
├─→ New requirement: replace with MoMA
│
▼
RESEARCHER AGENT
│
├─→ Find MoMA details (coords, hours, duration)
├─→ Query VectorDB for MoMA tips
│
▼
PACKAGER-EXECUTOR AGENT
│
├─→ Load existing trip.json
├─→ Remove Day 3 afternoon block
├─→ Insert MoMA (check hours, adjust times)
├─→ Recalculate distances
├─→ Update map GeoJSON (move pin)
├─→ Update calendar events (patch Day 3)
├─→ Output: Updated trip.json (incremental)
│
▼
VALIDATOR
│
├─→ Verify Day 3 still valid
│
▼
RESPONSE to UI
│
└─→ Partial update: {days[2]: {...}} + new map + calendar patch
🏗️ Infrastructure & Deployment
┌─────────────────────────────────────────────────────────────────────────┐
│ DEPLOYMENT ARCHITECTURE │
└─────────────────────────────────────────────────────────────────────────┘
┌──────────────────────────┐
│ FRONTEND (Vercel) │
│ │
│ • Next.js app │
│ • Static assets (S3) │
│ • CDN edge caching │
│ • WebSocket for updates │
└────────────┬─────────────┘
│
│ HTTPS / WSS
│
┌────────────▼─────────────┐
│ API GATEWAY (AWS) │
│ │
│ • /chat │
│ • /trip/{id} │
│ • /edit │
│ • /status/{id} │
└────────────┬─────────────┘
│
│
┌────────────▼─────────────────────────────────────────┐
│ BACKEND (AWS Lambda + EC2 or Container) │
│ │
│ ┌──────────────────────────────────────────┐ │
│ │ FastAPI + LangGraph Runtime │ │
│ │ • Agent orchestration │ │
│ │ • Tool registry │ │
│ │ • State management │ │
│ └──────────────────────────────────────────┘ │
│ │
│ Option 1: Lambda (lightweight tools only) │
│ Option 2: ECS/Fargate (full graph runtime) │
│ │
└──────────────────────────────────────────────────────┘
│
│
┌────────┴─────────┬──────────────┬─────────────┐
│ │ │ │
▼ ▼ ▼ ▼
┌─────────┐ ┌─────────────┐ ┌─────────┐ ┌──────────┐
│Supabase │ │ Neo4j Aura │ │ Bedrock │ │OpenTripMap
│ │ │ │ │ │ │ API │
│pgvector │ │ (Cloud) │ │ Claude │ │ │
│+ State │ │ │ │ │ │ │
└─────────┘ └─────────────┘ └─────────┘ └──────────┘
SECRETS MANAGEMENT
┌──────────────────┐
│ AWS Secrets Mgr │
│ • OpenAI key │
│ • Bedrock creds │
│ • Supabase URL │
│ • Neo4j creds │
└──────────────────┘