- Role
- Founder. Sole engineer.
- Started
- August 2025. Public launch September 2026.
- What it does
- Answers a restaurant's phone, takes the order, prices it, and submits it
- Telephony
- Telnyx call control, Pipecat media pipeline
- Models
- AssemblyAI speech recognition, neural TTS, Vertex Gemini with bounded Groq and Together fallbacks
- Data
- PostgreSQL via Supabase
The problem
I ran my family's restaurant for four years. The phone is the bottleneck: calls arrive exactly when the kitchen is busiest, every missed one is lost revenue, and the person answering is the person who should be expediting.
The obvious build is speech to text, a language model, text to speech, and a database write. I tried that first and it failed inside a morning. It took orders for things the kitchen does not make and quoted prices that do not exist, because a language model is producing the most plausible next thing to say, and the plausible answer to almost any customer request is yes.
Architecture
The system is split in two, with a hard boundary between them. This is the whole design.
| The model owns | Deterministic code owns |
|---|---|
| Understanding what the caller said | What exists on the menu |
| Handling corrections mid-sentence | What it costs |
| Interruptions and turn-taking | Which combinations are legal |
| Proposing what should change | Whether a change is applied |
| Phrasing the response | Whether an order was accepted |
The model proposes typed edits against opaque references. It cannot name a menu item by writing its name, invent an identity, or assert a price. Application code resolves those references against the real catalog, validates the operation, prices it, and persists it.
A rule the model is told to follow is a suggestion. A rule it cannot express is a guarantee.
Design decisions
- Unsupported configuration fails closed rather than being guessed. The agent will refuse things a human would have allowed, and that is the correct trade: a refusal is recoverable, a silently wrong order is not.
- Unpriced preparation notes such as "no mayo" stay attached to the line and route the order to manager review, instead of being silently dropped or charged as a modifier.
- Any material change to an order invalidates prior confirmation, so nobody confirms one total and receives another.
- Partial speech can trigger a lookup but can never authorise a write. Reads are free to be wrong; writes are not.
- An interruption stops the agent speaking but does not by itself cancel a business action. Treating those as one event loses orders.
- Catalog data defines configuration, including defaults, presets, amounts, half-and-half scopes and nested options. A new restaurant is a data-entry job, not a code change.
- Card data is never collected, logged, or transmitted. Card processing stays disabled until a PCI-contained payment leg is proven; cash and pickup work end to end.
- Recording and transcript persistence require an explicit yes or no before anything is stored.
Telephony, which is most of the real work
- Full call lifecycle on Telnyx: initiation, ring, answer, media, playback, hangup, timeout, and provider failure
- Webhook signature verification and idempotent handling of duplicate event delivery
- Teardown that runs on success, failure, cancellation, provider error and shutdown alike, with leaked-session detection after every call
- Both inbound and outbound, sharing one deterministic core and one state model
Status
Proven on real inbound and outbound calls rather than tests alone, including a half-and-half order priced and read back correctly through live telephony with no food-specific code path. Deployment was held uncertified until real calls passed audio, transcript, deterministic-state and teardown checks, because tests do not certify voice.
This one is entirely mine. No NDA, no restrictions. I can walk through any part of the codebase, including the parts I got wrong first.
