Demo project: AI-powered Travel Planning Assistant with multi-agent orchestration, interruption/cancellation support, and LangGraph integration skeleton.
- Overview
- Repository Contents
- Quickstart (Run locally)
- Architecture Overview
- Agent Design & Workflows
- Interruption / Double-Texting Behavior
- LangGraph Integration
- Environment Variables
- Demo Scenarios & Sample Queries
- How to swap demo-mode for real APIs
- Docker (optional)
- Troubleshooting
- Credits & License
This project is a hackathon-ready demo of a Travel Planning Assistant with three main parts:
- Frontend: React + Vite + Tailwind single-page chat UI (left sidebar, center chat, right itinerary) with light/dark themes inspired by provided screenshots.
- Backend: FastAPI server that hosts a demo orchestrator (Coordinator + Flight Agent + Hotel Agent) and implements Server-Sent Events (SSE) streaming for partial & final results.
- LangGraph integration skeleton: a commented, optional module that shows how to swap the demo orchestrator for LangGraph-based nodes and workflows.
The default repo runs entirely in demo-mode (no paid API keys required) and simulates streaming partial results and cancellation behaviour to make your demo crisp, deterministic, and fast.
If you uploaded a ZIP of the project, it is available here for convenience:
/mnt/data/fly-hotel-whisper-main.zip
travel-planner/
├─ backend/
│ ├─ app/
│ │ ├─ main.py # FastAPI app (endpoints: /chat, /stream/{session}, /cancel)
│ │ ├─ agents_demo.py # Demo Coordinator + Flight/Hotel agents (async simulated streaming)
│ │ ├─ api_utils.py # SSE helper & session/task management helpers
│ │ ├─ demo_data.py # Sample FLIGHTS and HOTELS used in demo-mode
│ │ └─ langgraph_integration.py # Skeleton and instructions for LangGraph
│ ├─ requirements.txt
│ └─ .env.example
├─ frontend/
│ ├─ package.json
│ ├─ vite.config.ts
│ ├─ tailwind.config.cjs
│ ├─ postcss.config.cjs
│ └─ src/
│ ├─ main.jsx
│ ├─ index.css
│ ├─ App.jsx
│ ├─ components/ # Sidebar, ChatWindow, MessageBubble, InputBar, ItineraryPanel, FlightCard, etc.
│ ├─ utils/api.js # startChat, startStream (SSE), cancelSession
│ └─ demoData.js
└─ README.md
Minimum requirements: Python 3.10+, Node 18+, npm/yarn
cd backend
python -m venv .venv
source .venv/bin/activate # macOS / Linux
# OR .venv\Scripts\activate (Windows)
pip install -r requirements.txt
# start the backend
uvicorn app.main:app --reload --port 8000This starts the demo backend on http://localhost:8000.
cd frontend
npm install
npm run devOpen the frontend (Vite) URL printed in the terminal (usually http://localhost:5173). The UI will be in demo-mode and will connect to the local backend via SSE.
This demo implements a compact multi-agent architecture with the following components:
- Coordinator (backend): receives user queries, detects intent (flight / hotel / both), and orchestrates agent runs.
- Flight Agent (backend): simulated flight search that streams partial flight cards.
- Hotel Agent (backend): simulated hotel search that streams partial hotel cards.
- Frontend: shows agent status pills, streaming partial results, preserves partials on cancellation, and supports light/dark themes.
- SSE Streaming:
GET /stream/{session_id}streams JSON events of typessystem,flight_partial,flight_done,hotel_partial,hotel_done.
State is stored in an in-memory SESSIONS dictionary for demo purposes. Each session holds a queue (asyncio.Queue) used by SSE, current running asyncio Task, a cancellation Event, and an array of preserved partials.
For production, replace SESSIONS with Redis or a persistent database for durability and multi-instance support.
- Input: free-text user query (e.g., "Find flights from Delhi to Dubai next Friday")
- Responsibility: intent detection (keywords), start Flight and/or Hotel agents (possibly in parallel), stream partials to frontend, and gracefully handle cancellations.
- Simulates network/LLM latency and emits a sequence of
flight_partialevents (one flight card at a time). When finished, emitsflight_donewith the final items. - Each partial item includes
partial: true. When finalized, items are re-emitted or markedpartial: false.
- Same behavior as Flight Agent but with hotel cards (
hotel_partial,hotel_done).
Key challenge solved in demo:
- Detection: When a new
POST /chatarrives for an existingsession_id, backend sets acancel_eventfor the in-progress task(s). - Cancellation: Running coroutines observe
cancel_eventand cancel gracefully. The backend will cancel tasks and close SSE when appropriate. - Partial Result Preservation: Partial items streamed before cancellation are preserved in
SESSIONS[session_id]["partials"]and remain visible in the frontend labeled as(partial). - Continuation: Frontend displays preserved partials and user can resume or re-run the previous query; Coordinator can re-invoke agents with preserved context.
Frontend flow on interruption:
- User sends new message while search is running.
- Frontend posts to
/chat; backend setscancel_eventon running task and streams asystemevent:"🔄 New request received — switching tasks...". - Frontend closes old SSE, preserves UI partials, and opens a new SSE stream for the new session_id returned.
backend/app/langgraph_integration.py contains two things:
- Skeleton — commented pseudocode showing how to map Coordinator, FlightAgent, and HotelAgent into LangGraph nodes and edges. This demonstrates how to use LangGraph's execution, streaming, and state features.
- Optional runnable example (gated) — a code path that only runs when
USE_LANGGRAPH=truein environment. This example explains how to create LangGraph nodes that call an LLM (OpenAI) and/or tools (web search, provider SDKs).
How to enable:
- Install LangGraph:
pip install langgraph langchain-openai(or follow provider-specific docs). - Set
OPENAI_API_KEYinbackend/.env. - Update
langgraph_integration.pywith provider-specific tool adapters and enable the feature flag.
Important: LangGraph's API & package names may evolve; follow LangGraph docs and examples linked in the file.
A sample .env.example is included in backend/.
For demo-mode you do not need real API keys. Use placeholders (or leave unset) unless you want to enable LangGraph or real travel APIs.
Example (safe placeholders):
When you later switch to real APIs, set the real keys in a secure environment and do NOT commit them to git.
Use these flows during your demo. They show streaming, partials, and interruption behavior.
- Type:
Find flights from Delhi to Dubai tomorrow→ press Enter. - Frontend should show agent status:
✈️ Flight Agent — Searching...and then stream partial flight cards.
- After flights start, type:
Also find hotels in Dubai for those dates→ press Enter. - Backend cancels or re-routes as configured. You should see a system message about switching tasks and preserved partials remain.
- Start:
Find flights to Goa next weekend. - Immediately:
Make it Mumbai instead. - The system cancels current run, shows
interruptedstatus for cancelled agent (red pill), preserves partials, and starts a new search for the updated destination.
-
Replace
agents_demo.pyfunctions with actual API calls or LangGraph nodes that call tools/LLMs. -
For flights/hotels, consider providers:
- Amadeus for flights and some hotel data
- Booking.com or Hotels.com via partner APIs or RapidAPI
- Skyscanner via RapidAPI
- Google Places / Maps for place images and distances
-
Update
api_utilsand SSE contract if you need different payload shapes. Keeppartialflags so frontend logic remains unchanged. -
For production: persist sessions in Redis and run the app behind a process manager (gunicorn/uvicorn workers). Use HTTPS.
You can containerize both services. Example docker tasks to add (not included by default):
backend/Dockerfilefrontend/Dockerfiledocker-compose.ymlcombining both services and a Redis instance for session state
- SSE not working: ensure backend CORS allows your frontend origin and your browser supports EventSource. Check console logs for network errors.
- No partials appear: confirm the backend
agents_demois running and streaming items. Check backend logs. - Cancelled tasks not finishing: ensure Python version >=3.10 and that
asynciocancellation points exist in any long-running loops.
This demo was generated to help with a multi-agent travel planning hackathon project. Use and modify freely for hackathons and prototypes. Add an open-source license of your choice for production use.
If you want, I can now:
- Generate
README.mdas a downloadable file (zip the repo) or - Paste any of the missing frontend or backend files directly into the chat so you can copy/paste them into your project.
Which would you like next?