A Python backend server powered by LangGraph and FastAPI for intelligent travel planning workflows. This API is designed to be consumed by a frontend application hosted in a separate repository.
TravelAgencyBE/
├── src/
│ ├── api/
│ │ ├── routes/ # API endpoint definitions
│ │ │ ├── health.py # Health check endpoint
│ │ │ └── ... # Add more route files here (e.g., travel.py, bookings.py)
│ │ └── __init__.py
│ ├── core/
│ │ ├── config.py # Application configuration & environment variables
│ │ └── __init__.py
│ ├── models/
│ │ ├── schemas.py # Pydantic models for request/response validation
│ │ └── __init__.py
│ ├── services/
│ │ └── __init__.py # Business logic & LangGraph workflows go here
│ ├── utils/
│ │ └── __init__.py # Helper functions and utilities
│ ├── main.py # FastAPI application entry point
│ └── __init__.py
├── tests/ # Unit and integration tests
├── .env.example # Example environment variables
├── .gitignore # Git ignore patterns
├── requirements.txt # Python dependencies
├── pyproject.toml # Modern Python project configuration
└── README.md
Purpose: Define your REST API endpoints here.
Each file should contain related endpoints using FastAPI routers:
health.py- Health check endpoint (already implemented)- Add files like
travel.py,bookings.py,chat.pyfor different features
Example:
# src/api/routes/travel.py
from fastapi import APIRouter
router = APIRouter()
@router.post("/plan")
async def plan_trip(request: TripRequest):
# Your endpoint logic here
passPurpose: Core application configuration and settings.
config.py- Centralized configuration using Pydantic Settings- Environment variables
- API keys
- CORS settings
- LangGraph parameters
Purpose: Data models and schemas for validation.
schemas.py- Pydantic models for:- API request bodies (what the frontend sends)
- API response bodies (what you return)
- Internal data structures
- LangGraph state objects
Example:
class TripRequest(BaseModel):
destination: str
budget: float
preferences: list[str]Purpose: Business logic and LangGraph workflow implementations.
This is where you'll implement your LangGraph agents and workflows:
- Create graph-based workflows using LangGraph
- Define nodes (processing steps)
- Define edges (transitions between steps)
- Implement agent logic with LLMs
Example structure:
# src/services/travel_planner.py
from langgraph.graph import StateGraph
from src.models.schemas import TravelState
class TravelPlannerGraph:
def __init__(self):
self.graph = self._build_graph()
def _build_graph(self) -> StateGraph:
workflow = StateGraph(TravelState)
workflow.add_node("analyze_request", self._analyze)
workflow.add_node("search_options", self._search)
# ... more nodes
return workflow.compile()
async def plan_trip(self, user_input: str):
return await self.graph.ainvoke(initial_state)Purpose: Reusable helper functions and utilities.
- Date/time helpers
- Data formatters
- Custom validators
- Third-party API clients
Purpose: FastAPI application entry point.
- Creates and configures the FastAPI app
- Sets up CORS middleware
- Registers route handlers
- Configures logging
- Defines startup/shutdown events
Purpose: Test files using pytest.
- Unit tests for individual functions
- Integration tests for API endpoints
- LangGraph workflow tests
- Python 3.12 or higher
- pip (Python package manager)
- Git
git clone <repository-url>
cd TravelAgencyBEWindows:
python -m venv .venv
.venv\Scripts\activatemacOS/Linux:
python -m venv .venv
source .venv/bin/activatepip install -r requirements.txtCreate a .env file in the project root by copying the example (if available):
# Create .env file with the following content:Important: Make sure to use the following format for the .env file:
# API Settings
APP_NAME="Travel Agency Backend"
API_VERSION="v1"
APP_DEBUG=True
# Server Settings
HOST="0.0.0.0"
PORT=8000
# CORS Settings (JSON format for list)
ALLOWED_ORIGINS=["http://localhost:3000","http://localhost:5173"]
# OpenAI Settings
OPENAI_API_KEY=your_openai_api_key_here
OPENAI_MODEL=gpt-4o-mini
# LangGraph Settings
MAX_ITERATIONS=10
RECURSION_LIMIT=25Configuration Notes:
ALLOWED_ORIGINSmust be in JSON array format:["http://localhost:3000","http://localhost:5173"]APP_DEBUGshould beTrueorFalse(capitalized boolean)- Replace
your_openai_api_key_herewith your actual OpenAI API key
Make sure your virtual environment is activated (you should see (.venv) in your terminal prompt).
uvicorn src.main:app --reloadOr alternatively:
python -m uvicorn src.main:app --reloadThe server will start at http://127.0.0.1:8000
Health check:
curl http://localhost:8000/v1/healthOr open your browser and visit:
- API Documentation: http://localhost:8000/docs
- Health Check: http://localhost:8000/v1/health
- Define the data models in
src/models/schemas.py - Implement business logic in
src/services/(LangGraph workflows) - Create API endpoints in
src/api/routes/ - Register the router in
src/main.py - Write tests in
tests/
Format code:
black src/ tests/Lint code:
ruff check src/ tests/Run tests:
pytestLangGraph workflows are implemented in src/services/ and exposed through FastAPI endpoints in src/api/routes/.
Typical flow:
- Frontend sends request to
/v1/travel/plan - Route handler in
src/api/routes/travel.pyreceives request - Calls LangGraph workflow in
src/services/travel_planner.py - LangGraph processes through multiple nodes/steps
- Results returned to frontend
# src/services/travel_planner.py
class TravelPlanner:
async def plan(self, request: TripRequest) -> TripPlan:
# LangGraph workflow implementation
pass
# src/api/routes/travel.py
from src.services.travel_planner import TravelPlanner
planner = TravelPlanner()
@router.post("/plan")
async def plan_trip(request: TripRequest):
result = await planner.plan(request)
return resultKey environment variables:
APP_NAME- Application name (default: "Travel Agency Backend")API_VERSION- API version prefix (default: "v1")APP_DEBUG- Enable debug mode and verbose logging (True/False)HOST- Server host (default: "0.0.0.0")PORT- Server port (default: 8000)ALLOWED_ORIGINS- CORS allowed origins in JSON array format (e.g., ["http://localhost:3000"])OPENAI_API_KEY- Your OpenAI API key for LangChain/LangGraphOPENAI_MODEL- Model to use (default: gpt-4o-mini)MAX_ITERATIONS- Max iterations for LangGraph workflows (default: 10)RECURSION_LIMIT- Max recursion depth for LangGraph (default: 25)
Once running, visit:
- Interactive docs: http://localhost:8000/docs (Swagger UI)
- Alternative docs: http://localhost:8000/redoc (ReDoc)
Issue: JSONDecodeError when parsing ALLOWED_ORIGINS
- Solution: Make sure
ALLOWED_ORIGINSis in JSON array format in your.envfile:NOT:ALLOWED_ORIGINS=["http://localhost:3000","http://localhost:5173"]
ALLOWED_ORIGINS=http://localhost:3000,http://localhost:5173
Issue: ValidationError for app_debug field
- Solution: Ensure
APP_DEBUGuses capitalized boolean values:NOT:APP_DEBUG=True # or False
APP_DEBUG=trueorAPP_DEBUG=yes
Issue: Module not found errors
- Solution: Make sure you activated the virtual environment:
- Windows:
.venv\Scripts\activate - macOS/Linux:
source .venv/bin/activate
- Windows:
Issue: Port already in use
- Solution: Either stop the process using port 8000, or change the
PORTin your.envfile
- FastAPI - Modern async Python web framework for building APIs. Provides automatic data validation, API documentation, and better performance than Flask
- Uvicorn - ASGI server that runs the FastAPI application and handles HTTP requests
- LangGraph - Workflow orchestration framework for building stateful, multi-step LLM applications
- LangChain - Framework for developing applications powered by language models
- Pydantic - Data validation using Python type hints. Automatically validates request/response data
- pytest - Testing framework for Python
- Keep routes thin - Put logic in services, not route handlers
- Use Pydantic models - Validate all inputs/outputs
- Type hints everywhere - Improves IDE support and catches bugs
- Log important events - Use the configured logger
- Write tests - Especially for LangGraph workflows
- Environment-based config - Never hardcode secrets
- Create feature branch
- Implement changes following project structure
- Add tests
- Run linting and formatting
- Submit pull request
MIT