Case 02

An assistant that can’t overcharge

A tool-calling assistant that takes a traveller from a question to a payable trip pack, without setting a price or taking money itself.

Live · since Sep 2026

Owner and lead engineer · built with a second engineer

On the travel-commerce platform in case 01, I own and lead an AI booking assistant, built with a second engineer. A traveller can ask a question in their own language and leave with a payable trip pack, while the server sets the price and the existing checkout takes the payment.

problem
Travellers had to search, compare and add extras in separate flows. A chat that books for them must not invent prices, touch payment, or reveal another traveller’s bookings.
built
With a second engineer, I built a streaming, language-aware chat whose model acts through 20+ typed tools inside rate, step and time budgets, handing a server-priced trip pack to the existing checkout.
outcome
Search, trip-pack building and a reviewable human handoff happen in one conversation. Anyone can search; owned bookings and pack changes need sign-in; prices come from the server.
Fig. 02.1The model works inside budgets through typed tools; the server owns price and checkout.

A traveller chats with a streaming, language-aware assistant. Each caller is limited to 20 requests a minute, and requests are refused if the limiter is unavailable. The model works inside a budget of 12 steps and 60 seconds a reply; read tools stop waiting after 30 seconds, while write tools are exempt and run to completion. Beyond writing text, it acts only through more than 20 typed tools, including search, bookings, draft packs, places and a consent-based handoff drafted for review; which tools are offered depends on sign-in and configuration. Anyone can search and read guidance; owned bookings and pack writes require sign-in. The server prices and holds the pack and returns a pay link to the existing checkout, outside the chat; the chat opens no payment session.

  1. ChatStreaming and language-aware
  2. Rate limit20 a minute; fails closed
  3. Server-held packServer prices and holds the pack
  4. Existing checkoutPay link, outside the chat
  1. 20 requests a minute; if the limiter is unavailable, requests are refused rather than let through.
  2. 12 steps and 60 s bound each reply. Read tools stop waiting at 30 s; write tools are exempt and run to completion.
  3. The server prices and holds the pack and returns a pay link; the chat opens no payment session.
Fig. 02.2 · Film · 0:11
A chat passes a per-caller rate limit into a budget fence, where the model works inside step and time budgets through typed tools. Sign-in gates owned bookings and pack writes. The server prices and holds the pack, and the existing checkout takes payment outside the chat. Parts are highlighted in reading order, not execution order.Animated diagram with a fixed layout. A chat connects to a rate limit, then down into a dashed budget fence around the model, which holds the readouts 12 steps, 60 s a turn and 30 s a read and a chip for 20+ typed tools; a dashed sign-in chip is joined to the fence. Below, a server-held pack connects to the existing checkout. One marker travels the path and each part is highlighted in turn; the film ends on its opening diagram.
Transcript

0.0–0.7: The full story strip is drawn: a chat and a rate limit; a dashed budget fence around the model, with the readouts 12 steps, 60 s a turn and 30 s a read and a chip for 20+ typed tools; a dashed sign-in chip joined to the fence; then the server-held pack and the existing checkout.

0.7–2.8: The chat is highlighted, and a marker travels to the rate limit, which is highlighted: each caller gets 20 requests a minute, and if the limiter is unavailable, requests are refused rather than let through.

2.6–5.45: The marker runs down into the fence and reaches the model, and the fence is highlighted: 12 steps and 60 seconds bound each reply. A read tool stops waiting after 30 seconds, while write tools are exempt and run to completion. Beyond writing text, the model acts only through more than 20 typed tools, such as search, bookings, draft packs, places and handoff.

5.4–6.55: The sign-in chip is highlighted: owned bookings and pack writes are offered only to a signed-in traveller, while search and travel guidance stay open. Sign-in decides which tools are offered; it is not a step every request passes.

6.35–7.65: The marker leaves the model through the fence to the server-held pack, which is highlighted: the server prices and holds the pack, and the model does not set the price.

7.5–10.05: The marker reaches the existing checkout, which is highlighted: the server returns a pay link to the site’s existing checkout, outside the chat. The chat opens no payment session.

10.05–11.0: The highlight clears and the opening strip holds again.

Parts are highlighted in reading order, not execution order. The states shown are examples. This is an illustrative flow based on verified code paths, not a recording of a real conversation.

One conversation, one payable pack

A traveller asks in their own language. The assistant searches hotels and places, reads travel guidance, and, once the traveller has chosen, offers add-ons such as an eSIM or an airport transfer before building a trip pack. A traveller who wants a multi-component package is guided through the site’s existing package builder instead.

The trip pack is the payment envelope. The server prices it, holds it, and returns a pay link to the site’s existing checkout. The chat never opens a payment session, and payment reuses the per-item fulfilment the platform already had rather than a new path.

Typed tools, offered by context

Beyond writing text, everything the model does goes through typed tools: more than 20 across search, owned bookings, add-ons, editable draft packs, packages, places and handoff. Which tools it is offered depends on sign-in and configuration: place tools appear only when place search is configured, and anonymous visitors are not offered tools that read their bookings or write to a pack.

Identity comes from the signed-in session on the server, not from anything the model says. Searching and reading guidance stay open; looking up your own bookings and writing to a pack or draft require sign-in.

  1. Open to every visitor

    Hotel and place search and travel guidance work without an account.

  2. Behind sign-in

    Booking lookup and pack or draft changes are offered only to a signed-in traveller, scoped by the server-side session.

  3. Consent first, then a draft

    With the traveller’s consent, the handoff tool prepares a draft for a person to review. It never claims that a message was sent.

Budgets that fail in the right direction

Each caller gets 20 requests a minute. The limiter fails closed: if it cannot be enforced, chat requests are refused rather than let through, because this endpoint calls a metered model.

Inside a turn, the model gets at most 12 steps and 60 s. A read tool that runs past 30 s stops holding the reply: the tool tells the model to say the lookup did not come back in time rather than report no results, while the underlying query may still finish in the background.

Five write tools are deliberately exempt. Stopping the wait would not stop the write, and telling a traveller that a pack change timed out could lead them to make it twice. Prices are checked on the server before a pack is saved, and the tool returns the saved total; the model writes the conversation, but the server is the source of truth for price.

Written down first, then tested

The assistant was specified in written designs before implementation. One revision changed the final step: an earlier design ended with the chat handing out a payment-provider link for a single hotel booking; the revised design made the trip pack the payment envelope, so add-ons share one payment and checkout stays outside the chat.

The assistant has 15+ service test files, including tests that pin the system prompt’s rules and language behaviour. They test rules and tools; they do not measure model quality.

The parts of the product I worked on

Scope follows my ownership boundary.

Owned and led

  • The assistant’s architecture, tool layer and delivery.
  • Technical direction, working with a second engineer.

Designed

  • Rate, step and time budgets, with exempt writes.
  • Sign-in gating for owned bookings and pack writes.
  • The trip pack as the handoff to the existing checkout.

Specified and tested

  • Written designs, including the pack payment revision.
  • Assistant service tests, including prompt rules.
  • TypeScript
  • Next.js
  • AI SDK
  • tRPC
  • Zod
  • Redis
  • Sentry