A Travel Itinerary Planner Agent in Typescript with HazelJS A developer built an intelligent travel itinerary planner using HazelJS, an AI-native framework. The planner uses multiple agents with RAG capabilities to extract travel profiles, research destinations, and build personalized itineraries. The project demonstrates HazelJS's agent orchestration and production-ready patterns. In this post, we'll build an intelligent travel itinerary planner using HazelJS. This agent helps users discover destinations, create personalized itineraries, and get logistics suggestions—all while demonstrating HazelJS's powerful agent orchestration, RAG capabilities, and production-ready patterns. Our travel itinerary planner handles the complete travel planning workflow: HazelJS provides a production-ready framework for building AI-native applications. For this project, we leverage: @Agent , @Tool , and @Delegate decorators travel-itinerary-agent/ ├── src/ │ ├── agents/ Agent implementations │ │ ├── travel-intake.agent.ts │ │ ├── destination-research.agent.ts │ │ ├── itinerary-builder.agent.ts │ │ ├── logistics.agent.ts │ │ └── travel-advisor.agent.ts │ ├── providers/ LLM and embedding providers │ │ ├── travel-planning-llm.provider.ts │ │ └── local-embedding.provider.ts │ ├── data/ Travel fixtures │ │ └── travel-fixtures.ts │ ├── travel/ Controllers and services │ │ ├── travel.controller.ts │ │ └── travel-kb.service.ts │ ├── app.module.ts │ ├── health.controller.ts │ └── index.ts ├── package.json ├── tsconfig.json └── README.md The TravelIntakeAgent extracts structured information from natural language: @Agent { name: 'TravelIntakeAgent', description: 'Extracts destination, dates, budget, interests, travel style, and group size.', systemPrompt: 'You are a travel intake specialist. Extract the traveler profile before any itinerary is created.', maxSteps: 4, temperature: 0, } @Service export class TravelIntakeAgent { @Tool { name: 'extractTravelProfile', description: 'Extract structured travel planning information from a user request.', parameters: { name: 'message', type: 'string', description: 'The raw user request', required: true }, { name: 'userId', type: 'string', description: 'User id when available', required: false }, , } async extractTravelProfile input: { message: string; userId?: string } { const destination = this.extractDestination input.message ; const days = this.extractDays input.message ; const budget = this.extractBudget input.message ; const interests = this.extractInterests input.message ; const travelStyle = this.extractTravelStyle input.message ; return { userId: input.userId ?? 'traveler-demo', destination, days, budget, interests, travelStyle, // ... more fields }; } } The DestinationResearchAgent uses RAG to find destinations semantically: @Agent { name: 'DestinationResearchAgent', description: 'Retrieves destination information from the knowledge base based on interests, budget, and season.', systemPrompt: 'You are a destination research specialist. Use retrieved context only and cite source ids.', enableRAG: true, ragTopK: 3, maxSteps: 4, temperature: 0, } @Service export class DestinationResearchAgent { constructor private readonly knowledgeBase: TravelKnowledgeBaseService {} @Tool { name: 'searchDestinations', description: 'Search destinations based on interests, budget, season, and travel style.', parameters: { name: 'query', type: 'string', description: 'The destination search query', required: true }, { name: 'topK', type: 'number', description: 'Number of destinations to retrieve', required: false }, , } async searchDestinations input: { query: string; topK?: number } { return this.knowledgeBase.answer input.query, input.topK ?? 3 ; } } The ItineraryBuilderAgent creates realistic daily itineraries: @Agent { name: 'ItineraryBuilderAgent', description: 'Creates realistic daily itineraries with balanced activities and travel time.', systemPrompt: 'You are an itinerary planning specialist. Create balanced plans with variety, rest periods, and logical routing.', maxSteps: 5, temperature: 0, } @Service export class ItineraryBuilderAgent { @Tool { name: 'createItinerary', description: 'Create a day-by-day itinerary from travel constraints and interests.', parameters: { name: 'destination', type: 'string', description: 'Destination city or country', required: true }, { name: 'days', type: 'number', description: 'Number of days to plan', required: true }, { name: 'budget', type: 'number', description: 'Total trip budget', required: true }, { name: 'interests', type: 'array', description: 'Travel interests and preferences', required: true }, , } async createItinerary input: { destination: string; days: number; budget: number; interests: string ; } { const filteredAttractions = this.filterAttractions input.interests ; const itinerary = Array.from { length: input.days }, , index = { const day = index + 1; const date = this.getDateForDay day ; const dayActivities = this.selectActivitiesForDay filteredAttractions, input.budget / input.days, day ; return { day, date, activities: dayActivities.activities, estimatedCost: dayActivities.estimatedCost, notes: this.generateDayNotes day, input.days, input.destination , }; } ; return { destination: input.destination, days: input.days, budget: input.budget, interests: input.interests, itinerary, tripSummary: this.calculateTripSummary itinerary , travelTips: this.generateTravelTips input.destination , }; } } The LogisticsAgent provides practical suggestions for flights, accommodations, and transportation: @Agent { name: 'LogisticsAgent', description: 'Suggests flights, accommodations, and transportation options based on budget and travel style.', systemPrompt: 'You are a logistics specialist. Provide practical suggestions for flights, hotels, and local transportation.', maxSteps: 4, temperature: 0, } @Service export class LogisticsAgent { @Tool { name: 'suggestLogistics', description: 'Generate logistics suggestions for flights, accommodation, and transportation.', parameters: { name: 'destination', type: 'string', description: 'Destination city or country', required: true }, { name: 'days', type: 'number', description: 'Number of days of travel', required: true }, { name: 'budget', type: 'number', description: 'Total trip budget', required: true }, { name: 'travelStyle', type: 'string', description: 'Travel style budget, balanced, luxury, adventure, relaxed ', required: true }, , } async suggestLogistics input: { destination: string; days: number; budget: number; travelStyle: string; } { const suggestions = this.generateSuggestions input.destination, input.days, input.budget, input.travelStyle ; return { destination: input.destination, days: input.days, budget: input.budget, travelStyle: input.travelStyle, suggestions, totalEstimatedLogisticsCost: suggestions.reduce sum, s = sum + s.estimatedCost, 0 , bookingTimeline: this.generateBookingTimeline input.days , }; } } The TravelAdvisorAgent orchestrates the workflow using delegation: @Agent { name: 'TravelAdvisorAgent', description: 'Coordinates travel intake, destination research, itinerary building, and logistics suggestions.', systemPrompt: 'You are the travel advisor orchestrator. Extract constraints, retrieve destinations, build itineraries, and suggest logistics.', maxSteps: 8, temperature: 0, } @Service export class TravelAdvisorAgent { @Delegate { agent: 'TravelIntakeAgent', description: 'Extract destination, dates, budget, interests, and travel style from a user request.', inputField: 'input', } async analyzeTravelRequest input: string : Promise