Adding a voice assistant to an existing app is now a days-long job rather than a quarter-long one. The model is an API call. Speech recognition ships with the platform. The demo works almost immediately.
The distance between that demo and something you let parents use is where the actual work is, and almost none of it is model work.
What was easy
Wiring it up. Capturing audio, transcribing it, sending the text to a model with a system prompt, speaking the answer back — that is a few days of work with well-trodden APIs. Any competent mobile developer can get there.
On-device handwriting recognition was similarly straightforward, because it uses a platform library rather than a hosted model — and how easily you can reach one is part of the Flutter-or-native decision. It runs offline, costs nothing per use, and does not raise a single privacy question.
If you have been told an AI feature is a large project because the AI part is hard, that is usually not true any more.
What was not easy
Deciding what it is allowed to say. A school app serves parents asking about attendance, fees, exam dates and homework. A general model will answer all of those confidently, including when it has no idea. It will invent a fee amount. It will guess at a holiday date.
The fix is not a better prompt. It is restricting the assistant to answering from data the app already holds, and having it say plainly that it does not know when the question falls outside that. Every question about money, dates or a specific child has to resolve against a record or be handed off.
Deciding when to stop listening. Voice interfaces have no submit button. Silence detection that is too eager cuts people off mid-sentence; too patient and it sits there while a parent thinks. Tuning that took longer than the model integration.
Handling the network honestly. A voice assistant that requires connectivity fails in exactly the places phones fail — corridors, car parks, basements. The interface has to say “I can’t reach the assistant” rather than appearing to hang, and the rest of the app must keep working.
Cost at real volume. A demo costs nothing. A few thousand parents asking a few questions each is a real monthly number. That has to be estimated before launch, and the model chosen accordingly — smaller models are frequently good enough for a scoped assistant, and dramatically cheaper.
The rule that matters most
An assistant answering questions about a specific child, a specific fee, or a specific date must never generate the answer. It must retrieve it.
Generation is for phrasing, not facts. The moment a model is allowed to produce a number, someone eventually acts on a number nobody stored. In a school context that means a parent who turns up on the wrong day or pays the wrong amount, and it is entirely avoidable.
What we would tell anyone adding this
Scope it to one thing first. “Answer questions about the timetable” is buildable, testable and honest. “An assistant for the app” is not a specification — it is a promise you cannot keep, because you have not defined what it must refuse.
Then decide, before writing anything, what happens when it does not know. That answer shapes the entire build, and teams that leave it until later end up with a system that guesses because guessing was the default.
We build AI features that ship — scoped, grounded in your own data, and designed for the cases where the model should say no. Tell us what you have in mind.