Back to the work

TallerDesk

A booking assistant for car repair workshops in Spain. An AI bot takes the customer's problem on Telegram or WhatsApp, checks real capacity, and books the job straight onto the owner's board. Every garage also gets its own online booking page, so car owners can pick a slot themselves. Live as a public demo garage.

A booking request moving through TallerDeskA customer describes a brake noise and says it's urgent. The bot asks the model to pull out the car, the problem and the urgency, then offers slots that are actually free once bays and mechanics' shifts are accounted for. The customer picks one, the bot books it, and the job lands on the owner's board with a phone notification.CustomerBotAI modelBookingOwner“Ruido al frenar, es urgente”Extract car, problem, urgencyBrakes, urgentReal free slots, checked against bays and shiftsPicks Thursday 10:00Create appointment and jobJob on the board, notified by phone
A booking request, drawn the way telecom engineers draw call flows.Message between systemsThe AI model decides

The problem

A workshop owner already runs a business, not a help desk. A customer texting “my brakes are making a noise” needs a slot on the calendar, not a ticket in a queue. And that slot is only real if a bay is free and a mechanic is actually on shift to work it — anything else is a booking that falls apart when the car shows up.

What I built

A booking assistant for Telegram and WhatsApp that takes the customer’s description, pulls out the car, the problem and how urgent it is, and offers slots checked against the workshop’s real capacity: which bays exist, and which mechanic is rostered on each one at that hour. Once the customer picks a slot, the job appears directly on the owner’s kanban board and the owner gets a phone notification, instead of landing in a separate inbox or ticket queue.

Chat isn’t the only way in. Every garage that signs up also gets its own public booking page: the car owner opens the garage’s link, sees an online calendar tied to that garage, and books an appointment without messaging anyone. It draws on the same capacity engine as the bot, so it only shows slots a bay and a mechanic can cover, and the booking lands on the same board.

Since the first version it has grown into something a shop could actually run: a Spanish and English dashboard with a language switch, a daily lunch break (the siesta) in working hours, regional public holidays that close the shop automatically and can be edited or overridden with special hours, voice notes transcribed on the way in, and a public demo garage anyone can try at the live site without signing up.

Architecture

This grew out of an existing help-desk codebase rather than a rewrite, and it runs as its own self-contained stack: its own database, bot, dashboard and network, reached through a tunnel with no open ports on the server. The diagram above traces one booking end to end, from the customer’s message through classification to a job on the board.

The language model sits behind a small provider layer, so the same intake runs on a free hosted model, Gemini or OpenAI, chosen by configuration.

Key decisions

No agent inbox. The workshop this is built for doesn’t want a help desk software subscription — it wants a board it already looks at all day and a notification on a phone it already carries. So there’s no separate inbox to check, no agent seats to manage. The bot handles the conversation; the owner sees a job appear where jobs already live.

Bookings are checked against real capacity, not just working hours. Early versions offered any slot inside the shop’s opening hours. That’s wrong the moment a shop has more than one bay or more than one mechanic — a slot only exists if a bay is free and someone is rostered to work it at that time. The booking engine reads the weekly shift rota, the lunch break and the holiday calendar before it offers anything, so what the customer sees is what the shop can actually deliver.

One language per conversation. Language used to be re-guessed on every message, so a chat could flip between Spanish and English mid-booking. It is now fixed after the first message that describes the car and the problem (unless the customer explicitly asks to switch), and every reply, reminder and owner notification follows it.

A public bot has to survive the public. The demo bot costs a model call per message, so it has a per-chat and per-shop rate limit that cuts a flood off before any model call is made. A live burst test confirmed the excess messages never reached the model. Bot tokens are scrubbed from stored logs after I found them in a request URL.

A regression suite that drives the whole path, not just units. The bot suite runs the entire intake-to-booking conversation — problem, extraction, slot offer, slot pick, booking, owner confirmation — against a disposable database that gets dropped and rebuilt for each run, with the language model replaced by a scripted stand-in keyed on the incoming prompt. That keeps the tests fast and deterministic: no network calls, no flaky model output, and a result that’s the same on every run. The dashboard suite adds guards for the mistakes a translated product is prone to, such as hard-coded text in the wrong language and missing translation keys.

Run it like it could be someone’s business. Nightly database backups are verified after they’re written, with a restore procedure I rehearsed into a scratch database and checked row for row. Disk use is bounded by log rotation and retention, and the backups are the first thing sacrificed if the host runs low on space.

How Claude was used

I wrote down the working agreement and the domain rules first — what a booking requires to be valid, what the dashboard must never show in the wrong language — and kept that document current as the codebase grew. Claude wrote most of the handlers and templates against that brief; I decided what the booking engine had to guarantee before it would offer a slot, and the regression suite was the gate for every change. More on that in how I build with Claude.

Results

The intake-to-booking flow works end to end against the regression suite: 147 tests across the dashboard and the bot flow, covering the conversation, the slot logic, holidays, translation coverage and the owner notification. The booking engine won’t offer a slot unless a bay and a rostered mechanic both back it up, eliminating phone tag and double-booking risks by verifying real shop capacity before confirming an appointment. It’s live as a public demo garage; there are no paying workshops yet.

What I’d do next

I’d want real usage before tuning anything: the slot-offering logic has only been exercised against seeded demo data, and a shop’s actual booking patterns will tell me faster than I can guess whether the shift-aware scheduling holds up under real load. Before a first paying shop, backups also need to be copied off the host automatically, and the WhatsApp channel needs testing with real traffic.