Case Study
I had the interaction model before the tools existed. So I built the tools.
- Project
- TravelBot
- AI Travel Planning App
- My role
- Product, Design & Engineering
- Solo · End to end
- Timeline
- 2023 to 2025
- Personal project
- Stack
- Python · Next.js
- OpenAI API · Custom agent framework




01 · Why I Built This
The travel tools that exist are built for mass markets. The trips I want to take are not.
The travel my family and I enjoy is exploratory. We want local culture, unexpected places, and fewer of the destinations that show up in every guidebook. That kind of trip needs judgment about what belongs, not another list sorted by rating.
Online travel tools are built around inventory: hotels, activities, and restaurants in ranked lists. That is a practical choice for a mass market. It also means the same categories and filters flatten the interesting edges off a trip.
The alternative was weeks of Reddit threads, spreadsheets, and too many open browser tabs. The information existed, but the pleasure had gone out of putting it together.
AI offered a way around both problems. If you can describe the kind of traveler you are, you do not need to start with filters. I also wanted to learn what that meant in practice, by shipping against the raw APIs while the technology was still new.
02 · The Vision
A living guide that gets more personal the longer you talk to it.
The first AI travel demos had the same shape: describe a trip, receive a wall of text, and stop. That is not how most people plan. Planning starts with a feeling, then gets refined through conversation, discovery, and small decisions over time.
OpenAI's first function-calling API suggested a different model. The assistant could call structured functions and update a persistent data model from natural language. It could change a living object instead of only producing text. The guide and the chat could sit side by side and inform each other.
What now looks like a chat plus an artifact was not an established UX pattern then. Claude Artifacts did not exist yet. I was designing toward the shape before it had a name.
The design principle
The trip is the app, not the chat.
The assistant exists to build something: a structured, visual guide that the traveler owns and keeps improving. The chat is the editing interface. The guide is the product. Each interaction either answers a question or changes the guide, and the system chooses which one.




03 · Speed as a Design Requirement
The feeling required speed, and the infrastructure did not exist yet.
Travel planning should feel like anticipation. You describe a trip and a guide appears with destinations, places, photos, and maps. There is a small jolt of excitement. That feeling is the product. If it takes minutes, the feeling is gone. You have built a better search engine, not a different experience.
The first response had to arrive in seconds, before attention moved on. The same was true for follow-up requests: add a beach town, find quieter hikes, or build a day-by-day schedule.
The architecture was specific. A fast first-pass agent identified destinations and interest categories, then created an agent for each one. Those agents ran in parallel and filled the guide while the user read the first response. Another agent drafted the itinerary from their output. A typical trip used more than a hundred specialized agents. The user saw none of it.
I evaluated LangGraph, AutoGen, and Crew. None could create the agents dynamically, after the first pass decided how many and what kind, and run them in parallel. I built the framework from scratch.
The constraint that drove everything
I needed agents to be created dynamically and run in parallel. The frameworks I found could do one or the other.
The first-pass agent determines the number and type of agents to run, so the system cannot know them in advance. They also need to run concurrently. That combination forced the custom framework. Updating only the affected parts of the trip model, instead of regenerating the guide, kept the experience stable.




04 · Design Principles






Five choices that kept the product from becoming a chatbot.
The trip stays at the center. AI helps shape it, and nothing in the interface should interrupt the feeling of anticipation.
The trip is the product, not the chat
A travel chatbot would have been simpler. The main surface is the guide: destinations, places, photography, maps, and the itinerary. The chat stays available as an editing tool. That makes the user feel like they are building something.
Iterative, not one-shot
Every response either answers a question or updates the guide. There is no mode switch. Ask about hiking conditions in March and you get an answer with web results. Ask to add a beach town and the guide changes: a destination page appears, places fill in, and the itinerary adjusts. The orchestration layer handles the difference without making the user name the response type.
Visual richness as a product requirement
Photography, maps, and curated links are part of the product. Planning is part of the pleasure of a trip, so the interface should make you want to be there. Removing the visual layer would have made the product easier to defend technically and less useful emotionally.
Partial updates, not regeneration
Adding one destination should not rebuild the whole guide. The data model changes only the affected parts, so the interface stays stable and responses stay fast. The guide gains depth without starting over.
Genius simplicity on the surface
The hundred concurrent agents, custom orchestration framework, and live data updates stay out of sight. The UI has three tabs: Explore, Plan, and Book, plus a chat bar at the bottom. The trip can get complicated without making the interface complicated.
05 · The Product
From a single thought to a day-by-day itinerary.
The journey starts with a natural-language description and ends with a multi-destination guide and a planned itinerary. The assistant is available throughout to refine the trip or answer questions.
Explore and curate
Travelers can heart places as they explore. Those favorites get priority when the itinerary is generated, so the system remembers what matters. A map is available from any screen and shows every place in the current guide.






Day-by-day planning
Tell the assistant how many days you have, or ask it to plan the trip. It builds the itinerary from the guide's places and assigns days, times, and durations. You can keep refining in chat or edit the plan directly by adding, removing, reordering, and retiming activities. Favorites get priority, and the rest fills in around them.






06 · Reflection
What I'd do differently, and what the project was really for.
I built the multi-agent framework as a reusable system: an abstract graph of nodes, edges, and branches that I could use again. The logic seemed sound. Invest in the infrastructure once and carry the benefit forward.
Looking back, the abstraction was not worth it for this project. It made iteration slower, and AI moves faster than a framework built to contain it. The models available now, including Claude 4.5 and GPT-5, can spawn and coordinate sub-agents in ways I did not imagine when I designed those graphs. Some of the choices are already out of date.
I would put the multi-agent system directly in the application code. Good architecture still matters, but in a field moving this fast, being able to change the structure is more useful than a beautiful generalized abstraction.
What this project was really for
In the early days of a fundamental technology shift, there is no substitute for building close to the API.
You cannot understand what function calling enables by reading about it. You learn what multi-agent orchestration means when the system breaks under real conditions and you have to fix it. I built TravelBot to scratch a personal itch and to develop product judgment close to the raw infrastructure, before the patterns had settled into names.
More case studies: XOIP AI Voice Agent and Cerbex Hotel Marketplace