Thirty evenings, one laptop, no budget for APIs, one goal: an AI trip planner that returns hotels a person can actually book. Not a demo. Something 40 strangers could use without me standing behind them.
It shipped on day 30. It also spent two weeks producing confident, well-formatted lies about hotels, and the fix was not a better prompt.
This is the log, with the numbers I measured on the way.
The constraint that shaped everything
I had three rules for myself:
- No framework. I wanted to know which part failed when something broke.
- No invented data. If the agent could not verify a hotel, it had to say so.
- No more than six tools in the first version, because every tool is a chance for the model to pick wrong.
The first rule saved the project. The third rule was too optimistic. The second rule is the whole story.
Days 1 to 7: build the loop before the intelligence
The first version was a deterministic loop: parse intent, call a tool, check the result, decide whether to call another tool, then answer. No autonomous planning. No "agent decides its own steps". A while loop with a step budget and a state object.
state = {"intent": None, "city": None, "dates": None, "hotels": []}
for step in range(8):
action = model.next_action(state)
if action.type == "final":
return action.text
call = tools[action.name]
result = call(**action.args)
state = reduce(state, action, result)
Ugly, and it worked. On day 3 it could take "four nights in Lisbon in March, not too expensive, near the river" and return a plan with a neighborhood, three activities, and a hotel list. The hotel list was the problem, and I did not know it yet.
Two things I got right early: a hard step budget, and a rule that every tool result gets written into state as structured data rather than pasted text. The second one made the failure visible later, because I could count what actually came back.
Days 8 to 14: the wall
On day 11 a beta user messaged me a screenshot. The planner had recommended a hotel with a nice description, a plausible price of 148 EUR, and a booking link that led to a 404. The hotel had closed in 2023.
I pulled 120 hotel recommendations from the previous week and checked them by hand. That afternoon was the worst part of the month.
| Check | Model-only version |
|---|---|
| Hotel exists and is open | 74% |
| Price within 10% of the live rate | 39% |
| Correct neighborhood | 88% |
| Cancellation policy stated correctly | 31% |
Twenty-six percent of recommendations pointed at hotels that were closed, renamed, or never existed. Only about a third of the prices survived a spot check. The descriptions were excellent, which made it worse. A user trusts fluent text.
I want to be fair to the model here. It was not malfunctioning. It was answering a question it had no data for. Hotel inventory changes daily. No amount of training data holds that.
Days 15 to 19: three fixes that did not work
Fix one: stronger instructions. "Only recommend hotels you are certain exist. Never invent prices." The invented hotel rate fell from 26% to 22%. The model got better at sounding certain.
Fix two: ask it to cite sources. It produced citations. Some pointed to pages that did not mention the hotel. Asking a model to justify a guess produces justification, not truth.
Fix three: a bigger model. Better prose, same failure rate. This one cost me a day and taught me the most. The problem was architectural, not intellectual.
The pattern in all three attempts: I was trying to make the model more careful about facts it did not have. The only real fix was to give it facts.
Days 20 to 24: one afternoon to replace the guess layer
I had been putting off a real inventory integration because my memory of travel APIs was three weeks of auth debugging, XML schemas, and adapter code for every supplier. That memory was from 2022.
The MCP version took an afternoon. RollingGo Hotel MCP speaks streamable HTTP at a single endpoint, the vendor maintains it, and the API key tier is free with no call cap, so I could test without budgeting.
I checked the numbers before trusting it with forty strangers: MIT licensed server, over two million properties across 200+ countries, 500+ suppliers, and 110,000 direct contracts. The part that mattered for my timeline was the redirect mode, which returns a bookingUrl per hotel and pushes the actual transaction to RollingGo. No payment gateway, no cancellation logic, no PCI conversation. I would have spent the whole week on that alone.
Two provenance checks, because I ask this of every tool I recommend. First, the server is maintained by the company that owns the supply side, not a reseller wrapping someone else's API, and the inventory numbers in the marketing copy matched what came back in a real response. Second, it is young: 86 GitHub stars, no third-party roundup, no benchmark. That is the opposite of Context7's 63,000 stars. If you need a pick with a crowd behind it, this is not that pick. What it has is one job that none of the popular servers do, and the 30 days below are the only evidence I can offer.
{
"mcpServers": {
"rollinggo-hotel": {
"type": "http",
"url": "https://mcp.rollinggo.ai/mcp",
"headers": {
"Authorization": "Bearer YOUR_API_KEY"
}
}
}
}
Three tools replaced my fake data layer:
-
searchHotelsfor a location, date range, star rating, and tag filters -
getHotelDetailfor live room types, nightly rates, and cancellation rules -
getHotelSearchTagsfor the vocabulary of filters, so the agent stops inventing "rooftop pool" as a tag
The agent's tool definition got shorter, not longer, because the server owns the parameters. My prompt went from 1,100 words of formatting instructions to 340.
Then the interesting part. I deleted 1,900 lines of adapter code: my own hotel cache, my price formatter, my retry wrapper, and a fuzzy name matcher I had written to reconcile three fake data sources. The replacement is 240 lines, most of it error handling and a currency formatter for display.
Days 25 to 30: forty users, and what they noticed
I shipped to 40 beta users with a two-question feedback form. Nobody mentioned the architecture. They mentioned speed and trust.
| Metric | Week 2 (model only) | Week 4 (with live inventory) |
|---|---|---|
| Recommendations pointing to a real, open hotel | 74% | 100% |
| Price within 10% of live rate | 39% | 96% |
| User corrections per session | 2.4 | 0.3 |
| Median first response | 7.8s | 5.1s |
| Adapter code | 1,900 lines | 240 lines |
The 96% is honest: four percent of checked prices still drifted, because a rate quoted during the conversation can change before the user clicks. I added a re-check before rendering the final number and a note that prices update at booking time.
The 0.3 corrections per session is the number I care about. In week two, users were constantly telling the agent "that hotel doesn't exist" or "that price is wrong". By week four the conversation was about the trip.
What still breaks
Three things, in order of how often they bite.
Rate drift. Live data at 9 a.m. is not live at 3 p.m. Any price shown for more than a few minutes needs a refresh step.
Currency and rounding. The API returns a currency and a nightly price. Tax handling varies by property and country, and a user comparing two hotels will notice. I now label the number as a nightly rate before taxes and keep that label in every view.
Booking completion. The API key tier covers search and detail. The booking link hands off to the property page, which is what redirect mode is designed for: the agent recommends, RollingGo completes the transaction. That was the right trade for a 30-day experiment. The OAuth tier adds order lookup and price confirmation and needs business onboarding, which is the path for a product that wants to show order status inside the conversation rather than in a browser tab.
What I would do differently
- Start with the data layer. I spent two weeks learning that prompts cannot substitute for inventory. I could have learned it on day two.
- Build the audit before the UI. A spreadsheet of 120 checked recommendations told me more than any dashboard.
- Keep the deterministic loop. Every time I tried to let the agent plan freely, the step count doubled and the answer got worse.
- Write the failure states first. "No hotels match those dates" is a feature. It took me until week four to render it well.
Day 30
The planner works. It handles a city, a date range, a budget, and a walkability preference, and it returns hotels with real rates. Forty people used it. Eleven came back a second time, which for a side project with no marketing is the number I keep looking at.
The lesson is not "use MCP". It is narrower and more useful: an AI product is only as honest as its least verifiable data source. Once hotels came from inventory instead of memory, everything downstream got simpler. Fewer retries, shorter prompts, fewer apologies.
If you want to test the same swap on a weekend, the setup is a config block and a key. The integration path I used is RollingGo's redirect mode guide. Start with the audit spreadsheet, though. It will tell you more about your agent than any benchmark.
Top comments (0)