Hackathon Requirements

LLM: ✅ Amazon Nova Premier (AWS Bedrock)
AWS Services: ✅ Amazon Bedrock AgentCore (6 components) • Amazon Nova (Premier + Act SDK) • Strands Agent Framework
AI Agent Qualification: ✅ Reasoning LLM • Autonomous capabilities • External integrations (Amadeus, Google Places, Browser automation)
Functionality: ✅ Fully deployed on AWS (us-east-1) • Reproducible via CDK & Agentcore CLI • End-to-end agentic workflow


Inspiration

I've tried planning trips with ChatGPT and Gemini. They're impressive conversationalists, right up until you ask them to actually help book something:

Me: "Find me flights from New York to Paris for December 15th."

ChatGPT: "Based on typical pricing, you can expect to pay around $600-900 for economy class..."

Sounds helpful until you realize: None of this is real. The prices? Hallucinated from training data. The airlines? Might not even fly that route. Booking it? Back to opening Kayak like an animal.

Real travel agents are incredible—they know which airlines hide fees, which hotels actually honor their photos, the neighborhoods where tourists get fleeced. But they cost $50-200 per trip, and for those of us planning multiple trips a year, that adds up fast.

So here's the question: What if I could build a digital travel agent that actually queries real APIs, browses actual websites, finds restaurants with today's hours—and does all this while having a natural conversation with you? That's AI Travel Agent: an autonomous system that doesn't just hallucinate suggestions, it takes real actions.


What It Does

Travel Agent is an autonomous AI system that takes real actions during conversation:

Core Capabilities:

  • Searches real-time flights via Amadeus API (actual prices, airlines, schedules)
  • Browses Airbnb listings using Nova Act browser automation
  • Discovers restaurants & attractions through Google Places API
  • Generates complete itineraries with day-by-day plans
  • Remembers conversation context for follow-up questions
  • Streams progress updates so you see what's happening in real-time

Example Conversation:

Sarah: "Plan a romantic weekend in Paris for two, leaving from New York in mid-December."

Agent: [Autonomously searching...] "I found 8 direct flights from JFK to CDG. The best option departs December 15th at 7:30 PM for $647/person. For accommodations, here's a charming Airbnb in Le Marais with excellent reviews..."

Sarah: "What about restaurants near the hotel?"

Agent: [Remembers context, searches Google Places...] "Near Le Marais, I recommend L'Ami Jean for traditional French cuisine (4.6 stars, €€€)..."

Within minutes, Sarah has flights, accommodations, restaurants, and a day-by-day itinerary—all from conversation.

MVP Scope:

  • ✅ Real-time flight/hotel search (Amadeus test API)
  • ✅ Airbnb discovery (Nova Act browser automation)
  • ✅ Restaurant/attraction search (Google Places free tier)
  • ✅ Basic itinerary generation
  • ✅ Short-term conversation memory (7-day expiry)
  • ✅ User authentication (AWS Cognito)
  • ❌ Actual booking (search only)
  • ❌ Multi-city trips (single destination)
  • ❌ Long-term preference learning

How I Built It

Tech Stack

I built this on Amazon Nova Premier for reasoning (because it actually understands what "romantic weekend" means), Amazon Bedrock AgentCore for the heavy lifting (runtime, memory, browser tools—basically everything), and the Strands Agent Framework for clean Python abstractions. For data, I'm hitting Amadeus API for flights/hotels, Google Places for restaurants, and using Nova Act SDK to literally browse Airbnb like a human would. Everything deployed via AWS CDK & Agentcore CLI because clicking buttons in consoles is for chumps.

Architecture Decisions

Single Agent vs Multi-Agent
I went with one orchestrator agent instead of the "committee of specialists" approach. Why? Because having separate agents for flights, hotels, and restaurants sounds sophisticated until you realize they need to constantly message each other like a bad group chat. One agent is faster (no communication overhead), smarter (remembers your "romantic" theme across all searches), simpler (one place where decisions happen), and cheaper (one execution instead of three).

Why AgentCore?
I could have spent weeks building our own agent infrastructure—memory management, auto-scaling, observability, browser automation. Or I could use AgentCore, which provides all of that out of the box. I chose not being masochists. AgentCore gave us production-grade capabilities (conversation memory with proper scoping, native Nova Act integration, automatic CloudWatch logging) so I could focus on actually making the agent work instead of reinventing AWS's wheel.

Hybrid Tool Integration
I're pragmatists, not purists. For Amadeus (flights/hotels), I use their official REST API because it's structured and fast. For Google Maps, I go through AgentCore Gateway with MCP because dynamic tool discovery is genuinely clever. For Airbnb? They don't have a public API, so I use Nova Act to literally browse their website. Different problems, different solutions.

NDJSON Streaming
Here's the thing: when your agent is searching flights, browsing Airbnb, and querying Google Maps simultaneously, that takes 20-40 seconds. Without feedback, users think it crashed. So I implemented streaming events:

yield format_ndjson_event("status", {"message": "Searching flights..."})
yield format_ndjson_event("tool_execution", {"tool": "search_flights", "status": "running"})

The breakthrough was custom hooks that intercept tool execution:

class StreamingProgressHook(HookProvider):
    def on_tool_start(self, event): 
        # Push event to queue for frontend
    def on_tool_complete(self, event):
        # Report success/failure with timing

Without these hooks, users see 30 seconds of silence. With them, they see exactly what's happening.


Challenges I Ran Into

1. Unified Response Model

Users ask for diverse things: just flights, complete trips, specific restaurants, follow-ups. Each needs different data, but the frontend needs consistency.

Solution: I designed TravelOrchestratorResponse with optional fields:

class TravelOrchestratorResponse:
    response_type: "flights" | "accommodations" | "restaurants" | "mixed_results" | "itinerary"
    response_status: "complete_success" | "partial_success" | "validation_error"
    flight_results: Optional[List[FlightResult]]
    accommodation_results: Optional[List[PropertyResult]]
    # ... etc

Every response uses this structure. Frontend checks response_type and renders accordingly.

2. Finding Real-Time APIs

Here's a fun fact: most travel APIs are either expensive (pay-per-call), outdated (cached data from 2023), or simply don't exist. Finding ones that are free, real-time, AND actually useful? That's the treasure hunt.

Amadeus (Flights/Hotels): They have a free test environment with 2,000 calls/month, which sounds generous until you realize it's test data—not every route exists, some prices are dummy data. But for a hackathon? Perfect. For production, you pay per use, which is fair but means I're explicitly in "proof of concept" territory here.

Google Places: The hero of this story. $200/month free credit (enough for thousands of searches), real-time data (current hours, actual ratings), and production-ready. I can scale this just by increasing quotas. This was our "actually works perfectly" integration.

Airbnb/Booking.com: No public API. At all. They protect their data like it's the nuclear codes. So I had to use Nova Act browser automation, which is basically having a robot browse their website. It works, but it's slow and fragile, which brings us to...

3. Nova Act Limitations

Nova Act promised "AI-powered browser automation," and while it delivers on the automation part, the AI aspect is... let's say "particular."

Step-by-step instructions required: You can't just tell it "search Airbnb for Paris." It needs atomic, explicit steps like you're teaching a very literal robot:

nova.act("Click destination search box")
nova.act("Type 'Paris, France'")
nova.act("Click check-in date picker")
nova.act("Select December 15th")
# ... 5 more steps to accomplish ONE search

Inexplicable failures: Sometimes it just... couldn't find the "Search" button. Despite the button being RIGHT THERE. Or it would get confused by date pickers. Or fail to click filter checkboxes. I spent hours debugging things that should be trivial. For the hackathon, I accepted these failures—when Airbnb search crashed, I just returned hotel results and moved on with our lives.

Painfully slow: Each Airbnb search takes 15-30 seconds. Five seconds to load, 2-3 seconds per interaction, 5-10 seconds to extract results. Not exactly snappy. So I designed the UX around "walk away" usage: user gives the agent a task, closes laptop, makes coffee, comes back to results. It's not ideal for an interactive chat experience, but it's the reality of browser automation. Sometimes you work around limitations instead of fighting them.

4. Streaming Implementation

Multi-tool searches need transparency or users think it crashed.

Custom hooks were critical: They intercept tool start/complete events and push to queue. Without them, streaming UX is impossible. They're the glue between AgentCore execution and frontend progress display.

Implementation challenges: Backend threading (agent in background, yielding events from queue), error handling mid-stream, React state management for streaming.


Accomplishments I'm Proud Of

🎯 Fully deployed production system on AWS—not a demo, a real application with authentication, auto-scaling, and monitoring

🤖 Real autonomous behavior—agent extracts parameters from natural language, orchestrates tools, handles errors, synthesizes results without hardcoded workflows

🔄 Custom streaming hooks—solved the transparency problem with elegant hook-based architecture

🏗️ Single-agent architecture that works—proved simpler is better than complex multi-agent coordination

📦 Complete infrastructure-as-code—entire system reproducible via cdk & shell scripts

🌐 Multi-source intelligence—successfully integrated 3 different patterns (REST API, MCP Gateway, browser automation) in one system


What I Learned

AgentCore is production-ready and I'm not: I initially worried about using a "new" platform, but AgentCore's auto-scaling, observability, and memory management just worked. The lesson? Don't spend weeks building infrastructure that AWS already battle-tested. Your time is better spent on the actual agent logic.

Nova Premier's reasoning genuinely impresses: It reliably extracted dates, locations, and party size from messy natural language. It knew when to ask clarifying questions versus making reasonable assumptions. It picked the right tools based on context. This is a significant step up from GPT-3.5-class models for agentic workflows—the reasoning actually feels... reasoned.

Browser automation isn't perfect, but neither is having no data at all: Nova Act is slow (15-30 seconds per search), fragile (needs step-by-step instructions), and occasionally just gives up. But when platforms don't offer APIs, you work with what you've got. For production, I'd prioritize official API partnerships. For hackathons, browser automation gets you 80% there.

Real-time APIs are worth their weight in gold: Google Places (2-3 seconds, 100% reliable, structured JSON) versus Airbnb scraping (15-30 seconds, 85% success rate, pray the HTML hasn't changed) is the difference between "this works" and "this mostly works if you're lucky." Browser automation is your last resort, not your strategy.

Single-agent architecture validated: I bet on one orchestrator agent handling everything instead of coordinating multiple specialists, and it paid off. Nova Premier's reasoning made the orchestration elegant—it could reference the "romantic" theme across flights, hotels, and restaurants without us hardcoding complex message passing. Sometimes simpler really is better.


What's Next for Travel Agent

Booking Integration: Move from search to actual reservations (Amadeus Booking API, hotel confirmations, OpenTable/Resy)

Long-Term Memory: Learn preferences over time ("You typically prefer aisle seats," "You've enjoyed Japanese cuisine")

Multi-City Planning: Tokyo → Kyoto → Osaka with optimized routing

Budget Optimization: Track spending, price alerts, value scoring

Visual Itinerary Builder: Drag-and-drop timeline, map view, distance calculations

Mobile App: Native iOS/Android with offline access and voice interface

Group Coordination: Multi-traveler preferences, split costs, shared editing

Weather Integration: Context-aware planning, packing suggestions, rerouting


Built With

Share this project:

Updates