In production · July 2026
Giving a production hotel system its own mind
Tabarak is a hotel & restaurant management platform (Next.js 15, Prisma, SQLite, WhatsApp via Baileys) running a real property in Pakistan: bookings and check-ins, room-service POS with kitchen tokens, housekeeping board, folios and expenses, compliance dispatch. This is the story of integrating Bela into it — from zero to a production agent handling Roman-Urdu staff commands — in roughly one working day.
What was integrated
Bela lives inside the app as three small pieces, none of which touched existing code:
| Piece | File | What it is |
|---|---|---|
| The contract | web/bela/agent.tools.ts | 25 tools + 5 entities wired to the app's real server actions and queries |
| The doorway | web/app/api/bela/route.ts | One POST route: session in, outcome out |
| The face | web/app/bela/page.tsx | A chat page with confirm buttons |
Plus the self-training loop: bela/train.mjs (retrain from config + corrections + memory), bela/bela-memory.md (the hotel's own editable memory), and bela/golden.mjs (replay real staff phrases before every deploy).
The 25 tools
Everything a signed-in user can do through the app's own permission system, Bela can do — that is the integration rule, enforced by deriving Bela's role gates from the app's can(role, action) table so they can never drift.
- Front desk: book (new-guest free-text name + phone), check out (confirmed), occupancy, who-is-in, expected checkouts, room status, availability, checkout reminders over WhatsApp.
- Restaurant: room-service orders, menu, prices with quantity math ("2 cup tea price kia hay" → Rs 200), order queue, advance/cancel by token.
- Housekeeping: assign (fires the app's own WhatsApp task alert), request, board, complete.
- Accounts: today's revenue, outstanding dues, expenses (confirmed).
- Plus staff list, WhatsApp health, and an optional self-hosted web search.
What the safety model did in practice
- Destructive actions (checkout, cancel order, expenses, bookings) ask yes/no first —
haanworks. - Ambiguity never guesses: "order karahi" listed the menu's eleven karahi variants as a numbered pick.
- The app's own auth stayed the last word: even Bela's internal test endpoint could not write to the database without a real staff session. Two independent layers.
- Every action lands in the app's own ActivityLog via Bela's audit hook.
What the learning loop measurably did
- Distillation: a locally-hosted Qwen3-4B (llama.cpp, CPU) generated 224 realistic staff phrasings across the tools in 69.5 seconds — one time. They became permanent training data. No cloud, no API keys, no runtime LLM.
- Memory:
bela-memory.md— a plain markdown file the hotel owns — taught phrases ("wich rooms are occupied and by whome") and vocabulary: an## Aliasessection maps "chai"/"tea" to the POS's actual "Doodh Patti (per cup)" row, feeding the entity resolver directly. - Result: a 16-phrase human test set (Roman-Urdu, typos, phrasings no template covers) went 9/16 → 15/16. Retraining takes ~6 seconds on one CPU core; the model artifact is ~8 MB.
Deployment notes (the honest part)
- Bela ships into the app as packed npm tarballs (
vendor/*.tgz,mainpointing at builtdist/) — file-linked TS sources break the Next build, and npm will not refresh a same-version tarball without purging it from the lockfile first. tsx-run scripts need a localserver-onlystub (Next aliases it internally; plain Node does not) — re-created after everynpm install.- The app's
redirect()-terminated server actions throwNEXT_REDIRECTon success — wrappers treat that digest as the success it is. - Training needs a seeded database: entity vocabulary comes from real rows.
- After every
pm2 restart, the Baileys WhatsApp session must be re-established (auth persists on disk; the connection does not).
What it proved
A production business app gained a natural-language operator — bilingual, safe, auditable, self-improving — for the cost of one config file, on hardware it already had. Latency is milliseconds because nothing leaves the box; vocabulary keeps growing because corrections are one file-edit away; and if every network beyond the VPS died, Bela would not notice.
Numbers in this document are from the integration test bed and live deployment, July 2026. See the whitepaper for the engine itself.