A Stateful Chatbot API Built for Children's Handheld Devices
A conversational API with per-turn safety flags, strict token caps, and monotonic turn indexing, designed to run behind children's handheld toys.
BMO Chatbot is a conversational API with an unusual target: handheld children's devices. That audience changes almost every design decision. The interesting engineering here is not the chat itself, it is the guardrails around it, the strict contract the device has to follow, and keeping all of that fast on a stack built from Bun, Hono, Redis, and OpenRouter.
A contract strict enough for a toy
The main endpoint keeps stateful conversations with memory across turns, but it demands a disciplined request shape to do it. Every call carries a conversation_id, a turn_index, the user_message, and a required max_tokens. The turn index is the load-bearing field: it is a monotonically increasing counter starting at zero, and if it does not match the expected sequence the server rejects the call with a TURN_INDEX_MISMATCH.
That strictness is deliberate. A toy is a flaky client. It loses connectivity, retries, and resends. Making turn ordering explicit means the server can detect a duplicate or out-of-order request instead of quietly corrupting the conversation history in Redis. The client can reset the whole thing with a reset_context flag when it wants a clean slate, which the response confirms by reporting context_state as either active or reset.
Token limits are not optional either. max_tokens is a hard cap between 10 and 500 on the reply, and the response reports reply_tokens_used back. On a small device with a small screen and a young user, an unbounded reply is a bug, not a feature. Forcing the caller to declare the ceiling on every turn keeps replies short and costs predictable.
Safety as a first-class response field
Because the users are children, safety cannot be an afterthought bolted on later. Every success response carries a safety_flags object with a content_filtered boolean and a reason code. When the system applies a safety redirect, it says so, with a machine-readable reason like redirect_weapons.
Surfacing that in the response, rather than silently swapping the text, matters. The device, and anyone auditing it, can see that a redirect happened and why. Safety becomes observable instead of a black box, which is exactly what you want when the product is aimed at kids and the people responsible for it need to trust what it did.
The takeaway
Building for a constrained, low-trust client like a children's toy pushes all the important logic to the edges of the request and response. Explicit turn sequencing catches the flaky-network failures, mandatory token caps keep replies appropriate and cheap, and exposing safety flags on every turn makes the guardrails auditable. The chat model is the easy part. The contract around it is where a product like this is actually won or lost.
Have something that needs building, or stabilizing?
These notes are the work log. The paid work runs through Moonshine Labs, my product and engineering studio. Tell us what you're building, or grab a call.
Work with us →