Agentic AI · Production · Sealed at v1.0.0
Nistula Assistance
A WhatsApp host that quotes real prices, gets the job onto the right phone, and structurally cannot promise something nobody is going to do.
Built
2026 · built solo during a three-month internship
Stack
- TypeScript
- Fastify
- Postgres
- pg-boss
- Claude Sonnet 4.5
- WhatsApp Cloud API
- eZee PMS
No live demo — the deployment was retired when the project was sealed.
01 — The problem
A guest asks the price. The model must not answer.
Guests message one number, at any hour, about anything — availability, rates, extra towels, a late checkout. An assistant that answers well is easy to build. An assistant that never invents a price is a different problem.
A language model that has seen a thousand rate cards will happily produce a plausible one. In hospitality that is not a glitch; it is a quote the property then has to honour, or refuse and lose the guest. The same applies to actions: an assistant that says “housekeeping is on the way” when no job was created has done real damage.
So the design puts the model where it is good — reading intent, writing naturally in the guest’s register — and takes the decisions away from it. Prices come only from a tool call against the live property management system. Actions exist only if a row was written. Then, after the model has written its reply and before anything is sent, a pipeline of deterministic checks reads what it produced and decides whether it may leave the building.
- Tools
- 7
- quote, availability, booking link, booking lookup, staff task, memory, escalation
- Tests
- 1,813
- across 106 files, green on Node 22 and 24
- Live backlog
- 62 items
- drained in three polls with 0 errors and 0 ops alerts
- Blockers caught
- 17
- by review, behind an already-green test suite
The checks run after the model, not in the prompt.
Asking a model nicely not to invent prices is a preference. Reading its output afterwards and refusing to send it is a rule. Everything interesting about this project follows from choosing the second one.
The guardrail pipeline sits between the model and the WhatsApp send. It re-reads the draft against what the tools actually returned this turn: a number that no tool produced fails price integrity; a commitment with no matching job row fails promise integrity; a reply that negotiates on rate fails the negotiation lock. A failing draft is rewritten or escalated to a human — it is never sent and softened.
The specification numbers the pipeline at seven checks — price integrity, promise integrity, negotiation lock, window check, identity honesty, length and format, leak scan. Two more, stay integrity and unit integrity, were added later and run in the same pass, so the telemetry enum lists nine rules against the plan’s seven. The count in the code is the honest one.
A real property, a real backlog.
It was verified against a Meta test line and the property’s live eZee PMS rather than against fixtures. The clearest evidence is the first poll of the production queue: the poller drained the property’s entire un-acknowledged backlog in three passes — 62 real items mirrored and acknowledged, 0 errors, 0 operator alerts, covering 22 confirmed stays across Airbnb, Booking.com, MakeMyTrip and walk-ins, plus 40 cancellation tombstones.
The other piece of evidence is less flattering and more useful. Before merge, every chunk went through a multi-agent adversarial review whose only job was to find what the tests had not. On this project that gate caught seventeen blocker-class defects sitting behind a suite of 1,813 passing tests. A green suite proves the code does what its tests say; it does not prove the tests asked the right questions.
What it deliberately does not do
-
It does not negotiate. Rate is not a conversation. A guest pushing for a discount is handed to a human rather than met halfway by a model with no authority to discount.
-
It does not pretend to be a person. Identity honesty is one of the checks. If a guest asks whether they are talking to a human, the answer is no.
-
It has no live demo. The deployment was retired when the work was sealed at v1.0.0, so the repository, its tests and its review record are the whole of the public evidence.
What it gets wrong
The dependency audit in CI is set to continue-on-error, deliberately, at seal — a HIGH advisory in a transitive dependency was failing the pipeline without a fix available upstream. That is a known, dated compromise recorded in the repo rather than a silently disabled check.