Inspiration

It started with my sister. Every time she wanted her hair done, booking took days: a DM, a reply hours later, a few rounds about length, price and which Saturday, then bank details for the deposit and a screenshot to prove she'd paid. Most of the stylists she and her friends go to, across Italy, France, Belgium and Luxembourg, take bookings only through Instagram DMs and WhatsApp, and both sides complain about it.

Then she sent me a reel from a UK nail tech showing the other side. A client booked by DM and went into the calendar before her bank-transfer deposit arrived. On the day, the nail tech waited, charged a late fee, cancelled for lateness, and only then checked the bank: the deposit had never been sent. The client had never really booked. Their conclusion: "if you have a booking site, that can't happen."

Booking by DM splits every appointment into a chat thread and a payment, and the stylist has to match the two by hand. One slip costs an empty chair and a day's income.

Kitoko already fixes this on a booking page: real prices, real free times, and no slot without a paid deposit. But clients don't start on a page. They start with "are you free Saturday?" in a DM.

So we built an AI front desk that answers right there. It already knows her prices, hours, service lengths and cancellation rules, so it replies instantly in the client's language with the real price and the next times that actually fit. The client picks one and pays the deposit with PayPal in the same chat. What used to take days of back-and-forth is confirmed in minutes, and the slot only exists once the deposit is paid. Our vision is that it works wherever clients write first: today on her page and WhatsApp, next inside Instagram DMs.

What it does

The stylist puts one link in her Instagram bio. It opens her page with the receptionist built in. The same receptionist also works on WhatsApp.

A client writes in any language and gets an answer right away. The receptionist:

  • quotes the real price (length and size change the price of braids);
  • offers only start times where the whole appointment fits;
  • holds the chosen slot (15 minutes on the web, 30 on WhatsApp);
  • sends a PayPal link for the deposit.

The booking is confirmed only when PayPal says the deposit is paid. No deposit, no booking.

If the client cancels or wants another day, the receptionist applies her cancellation policy. Inside the free window, the deposit goes back through PayPal. Too late, and the deposit stays with her. It quotes the rule instead of improvising.

The stylist gets a dashboard:

  • A live calendar (Bryntum) showing each booking's deposit status.
  • A sick day in one sentence. "I'm sick Friday" messages everyone booked that day, offers new times, rebooks the clients who accept and refunds the others.
  • An assistant for her money. "What did I make this week?", "Send Fatou an invoice for the balance", "Show me this week's refunds". The answers filter her money table (AG Grid). Refunds and payouts wait for her tap.
  • Payouts. After each appointment, her share goes to her PayPal account.

Other AI assistants can book too, through our MCP server. Ask Claude for "knotless braids in Milan on Saturday under €150". It compares stylists, holds a slot and hands you a PayPal approval link. You approve the payment; the agent never pays on its own.

How we built it

AI. Claude with tool use. Claude Haiku 5.5 answers clients: fast, multilingual, with prompt caching. Claude Sonnet 5.5 runs her assistant and writes the sick-day messages. The model knows nothing about prices, slots or policies on its own. Every fact comes from a tool backed by Kitoko's booking engine, a TypeScript package for time zones, opening hours, service options and deposit rules. Web chat, WhatsApp and MCP are thin adapters around the same agent.

Money lives in the database. It sits in Postgres functions on Supabase. Tools pass a booking id, never an amount. On a cancellation, the database computes the refund itself:

$$ \text{refund} = \text{paid} - \text{refunded so far} - \text{kept}(h) $$

where $h$ is the hours left before the appointment and $\text{kept}(h)$ follows her own cancellation tiers. An exclusion constraint makes double booking impossible, even when a chat client and an MCP agent grab the same slot at the same moment. Holds expire through pg_cron, and Supabase Realtime pushes every change to the calendar.

PayPal (sandbox):

  • Orders v2 + JS SDK v6 for deposits, with Pay Later
  • Webhooks, signature-verified and processed once per event
  • Refunds by cancellation policy
  • Payouts to the stylist
  • Invoicing v2 for the balance
  • Transaction Search to check her money against PayPal's records
  • Agent Toolkit for her assistant's PayPal tools (transactions, refunds, disputes, invoices), behind our own ownership checks

Every PayPal write carries a PayPal-Request-Id, so a retry never charges or refunds twice.

The app is Next.js on Vercel. In production, the platform collecting deposits and paying stylists out needs PayPal marketplace approval.

Challenges we ran into

  • Amounts had to leave the app. Kitoko's original checkout computed the refund in the app. That was fine while only our code called it, but not once an AI could call the same function. We moved the math into the database, so the tools can only name a booking.
  • One payment, confirmed twice. Our server confirms right after the buyer approves, and PayPal's webhook confirms again. Both paths had to be idempotent before the sick-day cascade behaved.
  • No Claude adapter in the Agent Toolkit. We mapped its tool schemas to Claude's format ourselves and put every call behind our own checks.
  • Sandbox reporting lags by hours. Earnings combine our records with PayPal's.
  • Judges share one demo. The demo resets itself every night, and a manual reset works at most once every 5 minutes.

Accomplishments that we're proud of

A client can book and pay in Italian without a human touching anything, and the stylist watches it land in her calendar. The nail tech's story can't happen here.

The sick-day cascade: one sentence from her, and the messages, rebookings, refunds and calendar changes all follow.

What we learned

The agent got better once we took decisions away from it. When the price, the slot and the refund come from tools, the model can focus on the conversation, and the stylist can trust what it says.

Human approval isn't friction. A PayPal screen at the end of the chat is what makes it reasonable to let an AI book for you.

What's next for Kitoko Receptionist

Next:

  • put it in front of real stylists, starting with the ones whose DMs inspired it;
  • live PayPal with marketplace onboarding, so stylists are paid directly;
  • a real WhatsApp number (the demo uses a simulator);
  • Instagram DMs, where most of these conversations start;
  • the receptionist inside Kitoko itself.

Built With

  • bryntum
  • claude
  • mcp
  • next
  • next-intl
  • paypal
  • paypal-js-sdk
  • paypal-webhooks
  • postgresql
  • supabase
  • tailwindcss
  • vercel
  • whatsapp
Share this project:

Updates

Submission history