A constraint-first travel planning agent powered by AI with real-time web search. Built for web and extensible for CLI.
Unlike typical travel planners that immediately generate generic itineraries, Planfirst thinks before planning by following a strict agentic workflow.
- Clarification: Intelligently extracts trip details from your initial message and only asks for what's missing (season, duration, budget, interests, etc.)
- Feasibility Check: Uses real-time web search to evaluate travel advisories, weather, and conditions for the specific travel period
- Assumptions: Makes all planning assumptions explicit (e.g., transport modes, accommodation styles) and requires user confirmation
- Planning: Researches current prices and creates a detailed day-by-day itinerary with:
- Activities with cost estimates and notes
- Travel times and costs
- Accommodation recommendations
- Daily tips (money-saving hacks, hidden gems, fast routes, must-try food)
- General trip tips (visa info, SIM cards, cultural etiquette, essential apps)
- Complete budget breakdown
- Refinement: Allows adjustments for safety, speed, comfort, or location preferences
- Framework: FastAPI (Python 3.12+)
- Database: PostgreSQL with SQLAlchemy 2.0 (Async) & Alembic migrations
- Auth:
- JWT-based authentication with refresh tokens
- Google OAuth 2.0 integration
- Bcrypt password hashing
- Multi-device session management
- AI/LLM: OpenRouter API (supports multiple models including Gemini 3 Flash)
- Web Search: DuckDuckGo Search (duckduckgo-search)
- Package Manager:
uv
- Framework: Next.js 15+ (App Router)
- UI Library: React 19
- Styling: Tailwind CSS 4
- Package Manager:
pnpm
- Container: Docker Compose (PostgreSQL)
- Database: PostgreSQL 15+
planfirst/
βββ backend/ # FastAPI application
β βββ app/
β β βββ agent/ # Travel planning agent logic
β β β βββ agent.py # Main TravelAgent orchestrator
β β β βββ models.py # Pydantic models for phases
β β β βββ prompts.py # Phase-specific prompts
β β β βββ tools.py # Web search & tool execution
β β β βββ sanitizer.py # Input sanitization (prompt injection defense)
β β β βββ openai_client.py # LLM client wrapper
β β βββ api/
β β β βββ v1/
β β β βββ auth.py # Auth endpoints (register, login, OAuth)
β β βββ db/
β β β βββ models.py # SQLAlchemy models (User, Trip, TripVersion, etc.)
β β β βββ crud.py # Database operations
β β β βββ database.py # DB connection setup
β β βββ schemas/ # Pydantic request/response models
β β βββ services/ # Business logic layer
β β βββ core/ # Security & config
β β βββ config.py # App settings
β β βββ main.py # FastAPI app entry point
β βββ alembic/ # Database migrations
β βββ scripts/ # Utility scripts
βββ frontend/ # Next.js application
β βββ src/
β βββ app/ # App router pages
β βββ components/ # React components
β βββ lib/ # Utilities & API client
βββ docker-compose.yml # PostgreSQL container
βββ gemini.md # Project patterns & standards
- Python: 3.12+
- Node.js: 20+
- Docker & Docker Compose: For PostgreSQL
- uv: Python package manager (Install uv)
- pnpm: Node.js package manager
Create a .env file in the project root:
# Database
DATABASE_URL=postgresql+asyncpg://postgres:postgres@localhost:5433/planfirst
# Security
SECRET_KEY=your-super-secret-key-here-change-in-production
ALGORITHM=HS256
# OpenRouter API (for LLM)
OPENROUTER_API_KEY=sk-or-v1-your-key-here
# Google OAuth (optional)
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
GOOGLE_REDIRECT_URI=http://localhost:8000/api/auth/google/callback
# Frontend
FRONTEND_URL=http://localhost:3000Start PostgreSQL:
docker-compose up -dcd backend
# Install dependencies
uv sync
# Run database migrations
uv run alembic upgrade head
# Start the API server
uv run uvicorn app.main:app --reload --port 8000The API will be available at http://localhost:8000
- API Docs: http://localhost:8000/docs
- Health Check: http://localhost:8000/health
cd frontend
# Install dependencies
pnpm install
# Start the dev server
pnpm devThe frontend will be available at http://localhost:3000
You can test the agent directly via a script:
cd backend
uv run python scripts/test_agent.pyPlanfirst supports two authentication methods:
- Email/Password: Traditional registration and login with JWT tokens
- Google OAuth: Sign in with Google account
Both methods issue:
- Access Token: Short-lived (15 minutes), used for API requests
- Refresh Token: Long-lived (30 days), used to obtain new access tokens
Refresh tokens support:
- Multi-device sessions
- Device tracking (user agent, IP)
- Individual or bulk revocation (logout from one device or all)
- β Smart clarification (extracts info from initial prompt, asks only what's missing)
- β Real-time web search for current prices, events, advisories
- β Risk assessment for weather, accessibility, health, infrastructure
- β Explicit assumption generation with user confirmation
- β Day-by-day itinerary with activities, costs, tips
- β Budget breakdown (flights, accommodation, transport, meals, activities)
- β Plan refinement (adjust for safety, speed, comfort, location)
- β Prompt injection protection (input sanitization)
- β User Management: Users, preferences, refresh tokens
- β Trip Versioning: Separate trip identity from planning iterations
- β JSONB Storage: Fast iteration with phase-specific data (constraints, risk, assumptions, plan, budget, days)
- β 5-Phase Workflow: Tracks clarification β feasibility β assumptions β planning β refinement
- β JWT-based auth with refresh tokens
- β Google OAuth 2.0
- β Password hashing (bcrypt)
- β CORS configuration
- β Session middleware for OAuth state
- β Input sanitization (anti-injection)
| Command | Description |
|---|---|
uv sync |
Install/update dependencies |
uv run alembic revision --autogenerate -m "message" |
Create new migration |
uv run alembic upgrade head |
Apply all migrations |
uv run alembic downgrade -1 |
Rollback last migration |
uv run uvicorn app.main:app --reload |
Start dev server |
uv run python scripts/test_agent.py |
Test agent directly |
| Command | Description |
|---|---|
pnpm install |
Install dependencies |
pnpm dev |
Start dev server |
pnpm build |
Build for production |
pnpm lint |
Run ESLint |
| Command | Description |
|---|---|
docker-compose up -d |
Start PostgreSQL |
docker-compose down |
Stop PostgreSQL |
docker-compose logs -f postgres |
View PostgreSQL logs |
docker-compose ps |
Check container status |
- Backend README: backend/README.md
- Project Standards: gemini.md
- Agent Documentation: AGENTS.md
- Frontend UI for chat-based planning
- Trip history and saved plans
- User preferences integration
- Export itineraries (PDF, calendar)
- Collaborative trip planning
- Mobile app
MIT