Inspiration
Most of our group members have gone on vacations where downtime seemed to extend for unbearably long periods. We have also fallen victim to shoddy vacation planning, whether due to unforeseen natural phenomena or irreconcilable differences in vacationing. Even more underwhelming is when a trip doesn't even make it out of the group chat.
To prevent these scenarios, we decided to create Japlan, an iMessage bot that streamlines the vacation planning process, while also gamifying attractions and promoting friendly competition.
Rather than building another travel app that everyone has to download, make an account for, and remember to check, we wanted to build where the trip already lives: the group chat.
Japlan is built around two core choices: Linq makes iMessage the application, while Gemini acts as the reasoning layer behind it. The user experience stays extremely simple: add one number to the group chat and keep texting normally while Gemini decides when it needs tools like Foursquare, Ticketmaster, or Browserbase to turn those messages into grounded plans.
What it does
Japlan is a bot that lives in your trip group chat. Using it is as simple as texting its phone number and adding it into a groupchat or private DM, where it automatically introduces itself and starts planning trips based on survey responses.
It asks the organizer where you're going, then DMs everyone a few quick questions, including dietary restrictions, spending habits, vacation pace and personality traits. Depending on the mode of travel you choose for it, it can accommodate groups, teams or individuals.
Generally, every morning it sends each person their own list of attractions built around where you actually are and how you like to travel.
You can claim points for an attraction by texting its unique code, and you can also send a photo as evidence for more points. Suggest a place and it lands on the plan with your name on it. Split up for the afternoon and each group gets its own schedule.
At the end, the group is presented with a vacation wrapped page, including a leaderboard, where you went, how far you walked, and other fun moments.
Japlan also connects the group chat to services people would normally have to open separately. Ticketmaster gives it real events around the group's destination and dates, Foursquare provides place discovery, and Browserbase lets the agent research the open web when a clean API does not exist: for example, checking an Enterprise rental or a local attraction's booking page.
The important part is that the user never has to think about which integration is being used.
They can simply text:
"anything good happening Saturday?"
or:
"can we rent a car instead?"
Gemini decides what information it needs, calls the appropriate tools, and returns the result to the same iMessage conversation.
Japlan is also designed around the reality that the original itinerary will probably break. If an activity closes, weather changes, or the group changes its mind, the same system can research alternatives while preserving the rest of the trip instead of forcing everyone back into manual planning.
How we built it
Japlan runs on an iMessage API through Linq, Next.js, Postgres, Gemini, Browserbase, Foursquare, and Ticketmaster.
Linq: iMessage is the application
We did not want Linq to simply be a notification channel for a travel app.
There is no separate chat interface. The iMessage thread is the interface.
Private DMs let Japlan learn each traveller independently, while the shared group chat becomes the coordination layer for the actual trip. Messages, links, and photos become application inputs without requiring users to learn bot commands.
That gives us a natural multi-user loop:
Private DMs
→ learn each traveller
Group chat
→ understand the shared trip
Links / messages / photos
→ update context
Japlan
→ researches and reasons
Same group chat
→ returns the plan
Most messages do not require a bot response. Japlan can use them as context and only intervene when it actually has something useful to contribute, which helped it feel much closer to another member of the group chat than a traditional chatbot.
Under the hood, Linq webhooks are normalized into a small internal event model so the rest of Japlan does not depend on raw provider payloads. We distinguish between direct messages, group messages, media events and reactions, then associate each event with the correct trip and traveller before it reaches Gemini.
Linq webhook
↓
normalize event
↓
resolve trip + member
↓
load relevant context
↓
Gemini agent
↓
tool calls / reasoning
↓
send response through Linq
Gemini: reasoning, not just generation
Gemini is not used as a text generator placed at the end of the pipeline.
It acts as the reasoning and orchestration layer over a registry of typed tools.
get_trip_context()
search_places()
search_events()
research_live_place()
verify_task_photo()
An incoming iMessage is paired with a compact snapshot of the current trip and the available tools.
Gemini can then decide to call a tool, inspect its structured result, call another tool if necessary, or produce the final response.
iMessage
↓
Gemini
↓
tool call
↓
validate arguments
↓
execute tool
↓
normalize result
↓
Gemini
↓
repeat or respond
Every agent run is bounded to a maximum of 8 tool iterations. Tool arguments are validated before execution, repeated identical calls can be rejected or reused, and third-party responses are normalized before they return to Gemini.
This gives Gemini freedom to determine what information it needs without allowing the agent to research indefinitely.
For example:
"what should we do this afternoon?"
Gemini
→ get_trip_context()
→ search_places()
→ research_live_place()
→ recommendation
while:
"anything happening Saturday night?"
Gemini
→ search_events()
→ recommendation
Grounded itinerary generation
One of our biggest technical decisions was to not ask Gemini to hallucinate a vacation from model knowledge.
Our itinerary pipeline is:
Foursquare discovery
↓
Browserbase live-web enrichment
↓
Ticketmaster event candidates
↓
structured candidate set
↓
Gemini reasoning
↓
source-backed itinerary
Foursquare discovers places in parallel, while Browserbase researches and enriches candidates with information from the live web.
Ticketmaster contributes real event candidates that can become fixed anchors in the trip.
Gemini is constrained to selecting from the resulting candidate IDs instead of simply inventing venues.
If availability or another fact cannot be established, we represent it as unknown instead of allowing the model to confidently fill in the blank.
Browserbase: the long tail of the real world
Structured APIs work well when they exist, but travel is full of businesses that only expose important information through their websites.
Browserbase gives Gemini a generic tool for that long tail.
We use a faster bounded Search/Fetch workflow for normal research, with a deeper Stagehand browser path when a site requires more involved interaction.
Instead of dumping raw HTML back into Gemini, Browserbase output is normalized into small objects containing fields such as:
name
price
location
hours
availability
source URL
That made the model substantially more reliable.
It also means the same architecture can research a local attraction, a restaurant booking page, or a service such as Enterprise without building a separate integration for every website.
Inspectable agent reasoning
We built a Research Inspector that exposes the technical pipeline behind an itinerary:
- URLs researched
- Browserbase actions
- candidates discovered
- tool calls
- Gemini selections
- Browserbase session metadata
This was useful both for debugging and for making the system explainable. If Gemini chooses an attraction, we can trace which source-backed candidate it came from instead of treating the model as a black box.
Gemini multimodality
Gemini also powers the visual side of Japlan.
When somebody completes a sidequest and sends a photo through iMessage, Gemini receives both the image and the original task.
The model evaluates whether the image is plausibly related to the challenge and returns a structured result that the scoring system can use.
This means Gemini plays two fundamentally different roles inside Japlan:
- agentic reasoning and tool orchestration
- multimodal understanding of real-world trip submissions
Challenges we ran into
Things broke without ever telling us. For several hours the bot would receive a message, do absolutely nothing with it and report no error anywhere we could find one, which meant we eventually resorted to logging before and after every single step in the chain just to discover where execution was quietly dying.
For a while, the photo checker rejected every single image we sent it, partly because we had asked the model whether the photo proved the task rather than whether it merely related to it, and partly because iPhone photos arrive rotated in a way the model ignores entirely, so it was judging half our pictures sideways.
Most of the initial survey turned out to be decorative rather than functional, since a significant portion of questions were being ignored by everything downstream, which meant the bot appeared thoroughly personalized while actually paying attention to almost nothing anyone had told it.
Finally, the bot needed to go through many iterations before its current amicable and pragmatic state, including an infuriating argumentative Gen-Z version and multiple iterations where it would simply spew gibberish due to improper inputs.
Moving from simple Gemini calls to an agent introduced another problem: models are very willing to keep researching after they already have enough information. We addressed that with bounded execution, typed tool arguments, normalized results, and repeated-call detection.
We also learned that sending raw web data directly back to Gemini made reasoning much less predictable. Converting Browserbase and API responses into small structured candidate objects dramatically improved reliability.
On the Linq side, we learned that putting an agent in a group chat introduces an unusual UX problem: sometimes the smartest response is no response at all. Making Japlan selective about when it speaks made the experience significantly more natural.
Accomplishments that we're proud of
Japlan works in a real group chat with ambitious or apathetic vacationers in it, and nobody involved has to download an app, make an account, or learn anything beyond texting a two character code when they finish something, and interacting with a forthcoming and transparent bot.
We can also demonstrate that the personalization of individual schedules when required is genuine rather than cosmetic, because two people who answered the survey in opposite ways get meaningfully different days on the same trip.
Most satisfying of all, it takes time to plan an ideal day rather than simply listing things at you, since it carries a rough sense of how long each task will take, how far apart everything sits, and how much of a day any particular group actually wants filled.
We are especially proud that Linq and Gemini solve different parts of the same problem rather than existing as separate sponsor integrations.
Linq gives Gemini the messy, multi-person context where trips actually happen. Gemini turns that context into structured tool use across Foursquare, Ticketmaster, and Browserbase. The result can move from a casual message like:
"anything happening Saturday?"
to grounded research and back to a useful group decision without anybody leaving the conversation.
What we learned
Telling an AI to do something is not exactly the same as making it do that thing, which we discovered when we mentioned that a relaxed trip should lead to gentler tasks and the model responded by making every task boring for every person on every trip we generated.
The biggest lesson was that the best use of Gemini was not asking it to know everything.
Gemini was much more useful when it could decide what information it needed, call a narrowly defined tool for that information, and then reason over grounded results.
We also learned that deterministic software should still handle the things deterministic software is good at. Database state, task ownership, exact timing, and source validation should not become probabilistic just because an LLM is available.
And on the product side, we learned that sometimes the easiest interface for an AI agent is no new interface at all.
The group chat already contains the people, preferences, links, screenshots, arguments, and decisions. Linq gave us a way to turn that existing conversation into the application itself.
What's next for Japlan
In the future, would like to let the bot chime in occasionally on its own initiative, though very carefully and on a strict budget, because nothing gets a group chat bot discarded faster than talking considerably more than anybody asked it to.
Beyond that, we are looking at better place data, proper routes running between the tasks rather than wandering around them, and a well-designed web summary accessible during the trip.
We also want the same Gemini tool architecture to handle increasingly dynamic replanning: when a reservation falls through or the group changes its mind, Japlan should be able to inspect the current trip, research grounded replacements, and repair the day without forcing the group back into manual planning.
Longer term, transportation, events, reservations, and other travel services should become invisible tools behind the same interface.
The goal is simple:
add one number to the group chat, and keep talking normally.
Built With
- browserbase
- foursquare
- gemini
- linq
- next
- open-meteo
- react
- stagehand
- supabase
- typescript


Log in or sign up for Devpost to join the conversation.