While evaluating open-source restaurant platforms for AI-agent (voice bot / WhatsApp assistant / chatbot) use cases, I ran KitchenAsty through a maturity analysis against production-grade systems like SevenRooms, Zenchef, and TheFork.
KitchenAsty is already in a strong position — the DevOps posture, the TypeScript monorepo, the existing reservations layer, and the Automation Rules engine are all well-suited to this use case. The gaps I found are targeted and additive: none require a rewrite, and none break existing consumers.
I am sharing the full findings here in case the team or any contributor finds them useful.
Summary of Findings
The table below rates the current state of the reservation system against the requirements of a multi-channel AI-agent deployment.
| Dimension |
Current Level |
Key Gap |
| API Coverage (reservations) |
🟡 Partial |
No cancel-with-reason endpoint, no no-show endpoint, no server-side state machine |
| Agent-Readiness |
🔴 Critical gap |
No hold/blockage mechanism — race conditions guaranteed under concurrent load |
| Idempotency |
🔴 Critical gap |
No Idempotency-Key support — agent retries create silent duplicate reservations |
| Webhooks |
🟡 Partial |
Only reservation.created covered — no modified, cancelled, no-show, reminders |
| Auth (external channels) |
🟡 Partial |
JWT only — no per-channel API Keys with scopes for autonomous agents |
| CRM |
🟡 Partial |
No staff notes, VIP tags, or GDPR erasure |
| Payments / Deposits |
🟡 Partial |
No reservation deposits or no-show penalties |
| Ops / DevOps |
🟢 Mature |
Docker Compose, stateless design, Prisma migrations ✅ |
The Two Most Critical Issues
If the community were to prioritise anything from this analysis, these two items have the highest production risk:
1. Missing Hold/Blockage — Race Condition Under Concurrent Load
The problem: Between GET /availability and POST /reservations, there is no atomic slot reservation. If two agents (or two browser tabs) query simultaneously, both see the same slot as available, and both successfully create overlapping reservations. There is no error — just silent overbooking.
The pattern to solve it: A two-step commit with a TTL-bounded hold:
GET /api/reservations/availability → see available slots
POST /api/reservations/hold → atomically lock a slot (TTL: 5 min)
POST /api/reservations/confirm → convert hold → confirmed reservation
Requires a new ReservationHold Prisma model and a cron job to expire stale holds. Availability queries must subtract active holds from visible capacity.
model ReservationHold {
id String @id @default(cuid())
locationId String
date String
time String
partySize Int
channel String
idempotencyKey String @unique
expiresAt DateTime
createdAt DateTime @default(now())
location Location @relation(fields: [locationId], references: [id])
}
2. Missing Idempotency Keys — Silent Duplicate Reservations on Retry
The problem: AI agents operate over unreliable networks. If a POST /reservations request times out before the agent receives a response, the agent will retry. Without idempotency, the retry creates a duplicate reservation — the customer receives two confirmation messages for the same booking.
The pattern to solve it: Support Idempotency-Key: <uuid-v4> on all write endpoints. Cache {status, responseBody} in Redis with a 24h TTL. On a repeated request with the same key, return the cached response without re-executing.
// Middleware sketch — packages/api/src/middleware/idempotency.ts
const idempotencyMiddleware = async (req, res, next) => {
const key = req.headers['idempotency-key'];
if (!key) return next();
const cached = await redis.get(`idempotency:${key}`);
if (cached) {
const { status, body } = JSON.parse(cached);
return res.status(status).json(body);
}
const originalJson = res.json.bind(res);
res.json = (body) => {
redis.setex(`idempotency:${key}`, 86400, JSON.stringify({ status: res.statusCode, body }));
return originalJson(body);
};
next();
};
This is also the simplest item to ship — no schema change, no new endpoints, and it immediately protects the existing POST /reservations as well.
Full Analysis (Additional Items)
Beyond the two critical gaps above, the full analysis also covers:
- RFC-03: Complete reservation lifecycle endpoints —
DELETE /:id with reason codes, POST /:id/no-show, and a server-side state machine that prevents invalid transitions (e.g. COMPLETED → CONFIRMED)
- RFC-04: Extending Automation Rules to cover all reservation lifecycle events (
reservation.modified, reservation.cancelled, reservation.no_show, reservation.reminder_24h, reservation.reminder_2h) with HMAC-SHA256 signing and retry logic on failed deliveries
- RFC-05: A per-channel API Key system with scopes (e.g.
availability:read, reservations:write) so that a WhatsApp agent, a voice agent, and a web widget each have independent, auditable, revocable credentials
For each of these, the full technical specification — Prisma models, API contracts, error codes, and acceptance criteria — was documented during the analysis. I am happy to paste any of it here on request.
Thanks for building KitchenAsty. 🙏
While evaluating open-source restaurant platforms for AI-agent (voice bot / WhatsApp assistant / chatbot) use cases, I ran KitchenAsty through a maturity analysis against production-grade systems like SevenRooms, Zenchef, and TheFork.
KitchenAsty is already in a strong position — the DevOps posture, the TypeScript monorepo, the existing reservations layer, and the Automation Rules engine are all well-suited to this use case. The gaps I found are targeted and additive: none require a rewrite, and none break existing consumers.
I am sharing the full findings here in case the team or any contributor finds them useful.
Summary of Findings
The table below rates the current state of the reservation system against the requirements of a multi-channel AI-agent deployment.
Idempotency-Keysupport — agent retries create silent duplicate reservationsreservation.createdcovered — no modified, cancelled, no-show, remindersThe Two Most Critical Issues
If the community were to prioritise anything from this analysis, these two items have the highest production risk:
1. Missing Hold/Blockage — Race Condition Under Concurrent Load
The problem: Between
GET /availabilityandPOST /reservations, there is no atomic slot reservation. If two agents (or two browser tabs) query simultaneously, both see the same slot as available, and both successfully create overlapping reservations. There is no error — just silent overbooking.The pattern to solve it: A two-step commit with a TTL-bounded hold:
Requires a new
ReservationHoldPrisma model and a cron job to expire stale holds. Availability queries must subtract active holds from visible capacity.2. Missing Idempotency Keys — Silent Duplicate Reservations on Retry
The problem: AI agents operate over unreliable networks. If a
POST /reservationsrequest times out before the agent receives a response, the agent will retry. Without idempotency, the retry creates a duplicate reservation — the customer receives two confirmation messages for the same booking.The pattern to solve it: Support
Idempotency-Key: <uuid-v4>on all write endpoints. Cache{status, responseBody}in Redis with a 24h TTL. On a repeated request with the same key, return the cached response without re-executing.This is also the simplest item to ship — no schema change, no new endpoints, and it immediately protects the existing
POST /reservationsas well.Full Analysis (Additional Items)
Beyond the two critical gaps above, the full analysis also covers:
DELETE /:idwith reason codes,POST /:id/no-show, and a server-side state machine that prevents invalid transitions (e.g.COMPLETED → CONFIRMED)reservation.modified,reservation.cancelled,reservation.no_show,reservation.reminder_24h,reservation.reminder_2h) with HMAC-SHA256 signing and retry logic on failed deliveriesavailability:read,reservations:write) so that a WhatsApp agent, a voice agent, and a web widget each have independent, auditable, revocable credentialsFor each of these, the full technical specification — Prisma models, API contracts, error codes, and acceptance criteria — was documented during the analysis. I am happy to paste any of it here on request.
Thanks for building KitchenAsty. 🙏