05/2026 — 07/2026
TripNest AI
Production AI travel agent with real payments
Solo developer — design, build, deploy, operate
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
Database Design
| Table | Purpose |
|---|---|
| chat_sessions | Per-user conversation history in a canonical (provider-agnostic) message format, with title + TTL eviction |
| bookings | Bookings with quantity; overbooking prevented atomically via PostgreSQL advisory locks |
| rooms / availability | 96-room inventory with per-date availability as the single source of truth |
| price_alerts | Persisted price alerts scanned daily by a scheduler |
| loyalty_points | VinClub-style points with row-level locking against race conditions |
| telemetry | Per-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