Skip to content

AI System

Agent-based AI system for generating travel product content, parsing trip descriptions, and providing an interactive travel consultant. Built on laravel/ai with OpenRouter as the default provider (config/ai.phpdefault); Gemini is used only for image tasks (default_for_images).

  • TCAI Chat Modal – Create or edit a SupplierTour with an interactive AI conversation that confirms destinations before generating (primary workflow)
  • Parse raw trip text (e.g., “Asia India 9N - 2 Delhi - 3 Jaipur”) into itinerary-only data
  • Refine individual product template fields with AI assistance (sparkles icons in admin)
  • Interactive travel planning via the standalone Travel Consultant chat page
Terminal window
# Default provider is openrouter (configured in config/ai.php)
OPENROUTER_API_KEY=your_key
OPENROUTER_BASE_URL=https://openrouter.ai/api/v1
OPENROUTER_MODEL="openai/gpt-4o-mini"
# Alternative provider for image tasks
GEMINI_API_KEY=your_key

Config File: config/ai.php

The UsesConfiguredModel concern reads config('ai.model') which resolves to OPENROUTER_MODEL env var.

Source: backend/app/Ai/Concerns/UsesConfiguredModel.php

All agents implement Laravel\Ai\Contracts\Agent and use the Promptable trait with the UsesConfiguredModel concern.

Agent Type Tokens Temp Timeout Purpose
TravelConsultantAgent Conversational + Tools 4000 0.7 120s Interactive travel planning with multi-turn chat and tool use
TripParserAgent Structured 16000 0.3 60s Parse raw trip text into product template data
TravelContentAgent Structured 4000 0.7 60s Generate marketing content from a title
FieldContentAgent Structured 2000 0.7 30s Refine/generate a single form field
HotelGeneratorAgent Structured 4000 0.7 120s Generate hotel data
TranslationAgent Structured 2800 0.3 120s Translate travel product content
DayContentAgent Structured 4000 0.3 90s Generate per-day content (label, title, description) when parser truncates
DayRephraseAgent Structured 4000 0.3 90s Rewrite each itinerary day’s description in brand voice, weaving in included-activity content
TripContentAgent Structured 2000 0.6 60s Generate marketing copy from a parsed itinerary summary (used by generateFromRawInput)
SupplierTranslationAgent Structured 8000 0.3 120s Translate supplier fields (hotels, activities, transfers) with a dynamic schema of requested fields
FlightRulesAuditorAgent Structured 2000 0.1 120s Turn the deterministic offers:verify-flights audit into a concise human review (never overrides the PHP verdict)
ContentRephraseAgent Structured + Tools 8000 0.7 120s Rephrase content fields using brand voice and content rules, validated post-generation by ContentValidator (details)

Source: backend/app/Ai/Agents/

Tool Purpose
SearchDestinationsTool Search POIs by keyword
SearchHotelsTool Search hotels by city
GetExistingTemplatesTool Find existing templates to avoid duplicates
GenerateFormContentTool Generate structured form data (title, descriptions, itinerary) for the TCAI chat modal – returns data without persisting to DB
CreateProductTemplateTool Create a ProductTemplate from trip description (standalone chat page)

Step-by-step tools for constructing itineraries with airport resolution and hotel matching. Used in the TCAI chat modal flow.

Tool Purpose
StartItineraryTool Create a builder session, store raw text and supplier IDs. Returns builder_id for subsequent calls.
SetArrivalCityTool Resolve first in-destination city to airport IATA code
SetDepartureCityTool Resolve last in-destination city to airport IATA code
MatchHotelsTool Fuzzy-match hotel names from raw text against supplier hotel database
BuildFullItineraryTool Build the complete itinerary in one call – parses text, generates content, applies airport overrides and hotel matches

The agent must call tools in this order: start_itinerary -> set_arrival_city / set_departure_city / match_hotels -> build_full_itinerary.

Source: backend/app/Ai/Tools/, backend/app/Ai/Tools/Itinerary/

Content Rephrase Tools (ContentRephraseAgent)

Section titled “Content Rephrase Tools (ContentRephraseAgent)”
Tool Purpose
GetBrandVoiceTool Fetch global + service-specific brand voice
GetContentRulesTool Fetch per-field constraints (length, format, forbidden words)
GetEntityContextTool Load entity data with relationships
SearchSimilarContentTool Find similar entities to differentiate content
GetExampleContentTool Fetch high-quality examples as style reference

Validation is not an agent tool: after generation, ContentValidator (backend/app/Services/Ai/ContentValidator.php) runs a deterministic PHP check inside ContentRephraseService. The former in-agent ValidateContentTool self-correction loop was removed.

See Content Management for the full tool workflow.

Source: backend/app/Ai/Tools/Content/

Orchestrates content generation for product templates. All methods accept an optional TcaiProfile for style customization.

Method Agent Used Description
generateContent(title, profile?) TravelContentAgent Generate marketing fields from a product title
generateFromRawInput(rawText, profile?, locale?) TripParserAgent + TripContentAgent Parse raw trip text into full template data with resolved itinerary. Used by GenerateFormContentTool in the TCAI chat flow.
generateItineraryFromRawInput(rawText, profile?, locale?) TripParserAgent Generate itinerary-only data (no marketing content). Used by the standalone “Generate Itinerary” action.
refineField(fieldName, currentValue, instructions, context, profile?) FieldContentAgent AI-assisted refinement for a single form field

generateFromRawInput post-processes itineraries through ItineraryResolver to normalize the schema, ensure route continuity between days, and resolve city names to POI IDs via database lookup and Google Places. It includes a fallback parser for shorthand formats like 5N, 7D, and dash-separated N City patterns (e.g., 3 Bogota - 2 Medellin).

Source: backend/app/Services/ProductTemplateAIService.php

Wraps TravelConsultantAgent with three modes:

Method Purpose
prompt(message, profile?) One-shot text response (standalone chat page)
startConversation(message, user, profile?, locale?) Start a new streaming conversation. Prepends locale context. Returns StreamableAgentResponse.
continueConversation(message, conversationId, user, profile?, locale?) Continue an existing conversation by ID. Returns StreamableAgentResponse.

The streaming methods use RemembersConversations on the agent to maintain multi-turn chat history. Conversation state is tied to the authenticated user via forUser() / continue().

Source: backend/app/Services/TravelConsultantService.php

Cache-based state management for the itinerary builder tool pipeline. Each builder session stores arrival/departure airports, stops, raw text, locale, and supplier IDs with a 30-minute TTL.

Method Description
create() Create a new session, return UUID builder ID
get($builderId) Retrieve session state from cache
setRawText($builderId, $text, $locale) Store raw trip text for content generation
setSupplierIds($builderId, $ids) Store supplier IDs for hotel matching
setArrival($builderId, $city) Resolve arrival city to airport-linked POI
setDeparture($builderId, $city) Resolve departure city to airport-linked POI
getSummary($builderId) Return route summary string

Source: backend/app/Services/ItineraryBuilderService.php

Deterministic fuzzy matching of hotel names mentioned in raw itinerary text against the supplier hotel database. Uses string similarity scoring (threshold >= 0.6) to find best matches.

Input: Raw text + array of supplier IDs

Output: Map of poi_id => supplier_hotel_id for the best match at each location

Used by MatchHotelsTool during the TCAI builder flow and by HandlesTcaiContent when applying generated content to the form.

Source: backend/app/Services/HotelMatcherService.php

Support class that bridges AI output and the itinerary data model:

  • normalizeRawItinerary() – converts AI raw output to proper schema
  • ensureRouteContinuity() – fills gaps between days with connecting routes
  • resolveItineraryLocations() – resolves city names to POI IDs via database/Google Places

Source: backend/app/Support/ItineraryResolver.php

TCAI (Travel Consultant AI) Profiles store reusable personality and style configurations that customize agent behavior. Profiles also power the brand voice and content rephrasing system.

Table: tcai_profiles – columns: name, description, custom_instructions (text), brand_voice (JSON), service_type (nullable enum), is_default (boolean)

  • service_type discriminator: null = global brand voice, or a ContentServiceType value (hotel, activity, transfer, cms_home, cms_about_us, cms_legal) for service-specific guidelines
  • brand_voice JSON stores structured fields: tone, target audience, vocabulary, forbidden words, personality traits, communication standards, formatting rules, before/after examples
  • getBrandVoicePrompt() compiles the structured brand_voice + custom_instructions into a single prompt string
  • TcaiProfile::getDefault() returns the global default profile
  • TcaiProfile::getDefaultForServiceType($type) returns the default profile for a specific service type
  • markAsDefault() sets this profile as default (unsets others in a transaction)
  • Has many ProductTemplate records via tcai_profile_id FK
  • Managed in admin at /admin/tcai-profiles (4-tab form: Profile, Brand Voice, Examples, Custom Instructions)

See Content Management for brand voice configuration details, content rules, and the rephrasing system.

Source: backend/app/Models/TcaiProfile.php

The primary TCAI workflow is an interactive chat modal embedded in the SupplierTour create/edit forms. When an admin pastes raw tour info and clicks “Generate with TCAI”:

  1. A Filament action modal opens containing the TcaiChat Livewire component
  2. The agent calls itinerary builder tools in sequence: start_itinerary (stores raw text + supplier IDs), set_arrival_city, set_departure_city, match_hotels
  3. The agent presents the plan with matched hotels for admin confirmation
  4. On confirmation, PHP intercepts the message directly (bypasses AI) and calls BuildFullItineraryTool to generate form data
  5. A green “Apply to Form” button appears – clicking it dispatches a tcai-content-generated event
  6. The HandlesTcaiContent trait (shared by CreateSupplierTour and EditSupplierTour) receives the event and populates all form fields including repeaters (itinerary, hotel assignments, activity assignments, transfer assignments)

PHP confirmation interception: When the user sends a confirmation message (“yes”, “ok”, “si”, etc.) and a builder_id exists, TcaiChat bypasses the AI agent entirely and calls BuildFullItineraryTool directly in PHP. This ensures reliable “yes” handling without depending on the AI to interpret confirmations correctly.

Tool progress streaming: During the builder tool sequence, tool results (arrival set, departure set, hotel matches) are streamed to the chat UI so the admin sees progress.

Key components:

  • TcaiChat Livewire component – manages chat state, streams AI responses via wire:stream, intercepts confirmations, tracks itineraryBuilderId
  • HandlesTcaiContent trait – event listener that maps AI output to Filament form fields, handles UUID-keyed repeater state, applies hotel matches from HotelMatcherService
  • BuildFullItineraryTool – orchestrates content generation using stored builder state (raw text, airports, hotel matches)

Source: backend/app/Livewire/TcaiChat.php, backend/app/Filament/Resources/Suppliers/SupplierTours/Concerns/HandlesTcaiContent.php

Chat-style Livewire page at /admin/ai/travel-consultant (nav group: “AI Tools”). Users select a TCAI Profile from a dropdown and interact with the TravelConsultantAgent. This page uses CreateProductTemplateTool which persists directly to the database (unlike the chatbox modal flow).

Permission required: use_travel_consultant

Sparkles icon buttons on ProductTemplate form fields open a modal with an instructions textarea and TCAI profile selector. Calls ProductTemplateAIService::refineField() and updates the form field in place.

Permission Scope
view_tcai_profile View TCAI profiles
create_tcai_profile Create TCAI profiles
update_tcai_profile Update TCAI profiles
delete_tcai_profile Delete TCAI profiles
use_travel_consultant Access Travel Consultant chat page
  • Content Management – Brand voice, content rules, and AI rephrasing
  • Product Templates – AI content generation for templates
  • Roles and Permissions – TCAI permissions
  • Suppliers – Multi-supplier tours and service assignments
  • Source: backend/app/Ai/ – all agents, tools, and concerns
  • Source: backend/app/Ai/Tools/Itinerary/ – itinerary builder tools
  • Source: backend/app/Services/ProductTemplateAIService.php
  • Source: backend/app/Services/TravelConsultantService.php
  • Source: backend/app/Services/ItineraryBuilderService.php
  • Source: backend/app/Services/HotelMatcherService.php
  • Source: backend/app/Livewire/TcaiChat.php
  • Source: backend/app/Filament/Resources/Suppliers/SupplierTours/Concerns/HandlesTcaiContent.php
  • Source: backend/app/Support/ItineraryResolver.php