All projects

05/2026 — 07/2026

TripNest AI

Production AI travel agent with real payments

Solo developer — design, build, deploy, operate

11agent tools
255automated tests
20/20RAG eval pass
9/9e2e booking flows
~$0.17LLM cost / user / mo

Overview

TripNest AI is my graduation project, built end to end and deployed to production (web app, real VietQR payment flow, Google/Facebook SSO). A user chats with the agent, gets explainable room recommendations via a 5-criteria Match Score, builds an itinerary, and completes a booking — all in one conversation.

The agent orchestrates 11 tools (room search, pricing, policy Q&A, itinerary builder, combo builder, weather, budget optimizer, preference saving…) over a knowledge base of 96 rooms across 10 Vietnamese cities, grounded by a RAG pipeline with a 20-question evaluation suite that must pass 20/20 before any KB change ships.

Beyond features, the project is instrumented like a product: per-turn token/cost/latency telemetry, an admin analytics dashboard with a booking conversion funnel, deterministic A/B prompt experiments, and a documented cost model (~$0.17 per active user per month after prompt caching).

≈10 weeks (05/2026 → 07/2026) · 450+ commits · production since June 2026

Key Features

  • Conversational booking: search → Match Score recommendation → itinerary → VietQR payment → confirmation, in one chat
  • Multi-provider LLM layer behind a feature flag (Claude Haiku 4.5 / GPT-4.1 mini) with a canonical message format — swap providers via one env var, safe A/B and rollback
  • LLM context management: history summarization, tool-result pruning, cache-friendly prompt structure, DB-persisted sessions with TTL eviction
  • Guest DNA personalization: implicit preference learning, explainable recommendations, multi-session memory
  • Atomic inventory: PostgreSQL advisory locks prevent overbooking under concurrent checkout (409/422 semantics)
  • Admin analytics: per-turn cost tracking, tool success rate, funnel, trace & guardrail views
  • Safety stack: pre-LLM credit-card blocking, prompt-injection defense, 5-layer anti-hallucination grounding

Architecture

User

web · chat widget

Next.js 14 Frontend

Vercel · SSE streaming UI

FastAPI Backend

Fly.io · AgentService · 11 tools

LLM Provider Layer

Claude Haiku 4.5 ⇄ GPT-4.1 mini (feature flag)

RAG Pipeline

LangChain + ChromaDB · 96 rooms / 10 cities

Supabase PostgreSQL

bookings · sessions · telemetry

VietQR

payment webhook (HMAC)

Tech Stack

FastAPINext.js 14Claude Haiku 4.5GPT-4.1 miniLangChainChromaDBSupabase PostgreSQLDockerFly.ioVercel

Database Design

TablePurpose
chat_sessionsPer-user conversation history in a canonical (provider-agnostic) message format, with title + TTL eviction
bookingsBookings with quantity; overbooking prevented atomically via PostgreSQL advisory locks
rooms / availability96-room inventory with per-date availability as the single source of truth
price_alertsPersisted price alerts scanned daily by a scheduler
loyalty_pointsVinClub-style points with row-level locking against race conditions
telemetryPer-turn token/cost/latency + tool success, feeding the admin analytics dashboard

Folder Structure

C2-App-031/
├── frontend/          # Next.js 14 (TypeScript) — chat widget, booking UI, admin dashboard
├── backend/           # FastAPI (Python 3.11+)
│   ├── routers/       #   REST + SSE endpoints
│   ├── services/      #   agent, LLM provider layer, availability, telemetry
│   ├── models/        #   SQLAlchemy models
│   └── knowledge_base/ #  RAG source documents (Q&A-formatted policies)
├── agent_docs/        # Context files for AI-assisted development
└── docs/              # PRD, tech design, API reference, eval evidence

Challenges & Solutions

Problem · The agent hallucinated rooms, prices, and policies — unacceptable when real money is involved.

Solution · Built a 5-layer grounding stack: city filtering, canonical policy retrieval from the KB, JSON stripping, unaccented Vietnamese matching, and eval gates (20/20 retrieval suite must pass before shipping KB changes).

Problem · Concurrent checkouts could overbook the same room on the same dates.

Solution · Made booking creation atomic with PostgreSQL advisory locks and explicit conflict semantics (409 on inventory conflict, 422 on capacity violations), verified by end-to-end tests.

Problem · LLM costs would not survive contact with real usage at consumer prices.

Solution · Prompt caching on the system prompt (~90% cheaper cached input), history summarization, and tool-result pruning — landing at ~$0.17 per active user per month, with per-model pricing tracked in telemetry.

Problem · Red-team testing showed the agent could be talked into confirming a payment that never happened.

Solution · Moved payment confirmation out of the LLM entirely: a server-verified sentinel is required before the agent may congratulate, and the post-payment turn is deterministic (no LLM in the money path).

Lessons Learned

  • Evals before features: the 20-question retrieval suite caught more regressions than any code review.
  • Store conversation history in one canonical format — swapping LLM providers became a one-line env change instead of a migration.
  • Anything touching money should be deterministic; the LLM proposes, the server decides.
  • Telemetry from day one turns 'it feels expensive' into 'turn 7 costs $0.004 and here is why'.

Future Improvements

  • Verify VietQR against a real bank account (currently sandbox-verified)
  • Multilingual embeddings in production (built, deferred: torch exceeds the 512MB deployment budget)
  • Distributed session store to scale past a single backend machine