Inspiration

Six months into managing a team, you know exactly what needs to be said. You rehearsed it in your head on the commute. Then the 1:1 starts, your teammate says "I thought I delivered everything on time," and the sentence you practiced silently does not come out.

That gap — between knowing what to say and being able to say it out loud — is what SayBetter AI exists to close. Generative AI is very good at writing the message for you. It is not good at making you say it. Reading a perfect script does not build the reflex you need when someone pushes back in real time.

I also had a selfish reason. I work in overseas sales, so I regularly have to explain a delayed shipment, defend a price increase, or say no to an unreasonable deadline — sometimes in English, which doubles the difficulty. I wanted the rehearsal I always ended up doing badly, alone, in my head.

What it does

SayBetter AI is a voice-first rehearsal room for the workplace conversations people avoid.

1. Pick a situation. 20 built-in scenarios across five categories that map to what new managers actually struggle with: giving critical feedback, saying no and setting boundaries, disagreeing with your boss, delivering delays and bad news, and negotiating. Each ships with a specific counterpart, a background situation, and a goal. You can also describe your own situation in a sentence or two.

2. Take 30 seconds to prepare. A prep card gives you three concrete objectives, the phrases to avoid, and one suggested opening line — what a good coach would tell you in the hallway before you walk in.

3. Talk. Out loud. You speak; the AI plays the other person. It pushes back, gets defensive, asks questions, and applies time pressure according to the difficulty you chose. It never coaches mid-conversation and never breaks character, because the point is to make the room feel real. If you cannot use a microphone, you can type instead — the practice still works.

4. Get feedback grounded in what you actually said. After you end the session you get scores on five axes — clarity, empathy, logic, assertiveness, resolution — plus strengths and improvements that quote your own sentences verbatim and offer a concrete better phrasing. "You said 'I think that might be difficult' — try naming the range you can commit to instead."

5. Try again, differently. Run the same scenario softer, firmer, or in the other language, and watch the score move. Practice becomes a loop, not a one-off.

Everything is fully bilingual: every scenario exists in Korean and English, and the conversation language is independent of the app language — so a Korean user can rehearse the same difficult conversation in English before a call with an overseas client.

How I built it

Flutter for one codebase across iOS and Android. The conversation is a small state machine — idle → listening → thinking → speaking — that keeps the mic, the model, and the TTS voice from stepping on each other.

Speech in, speech out. The platform speech recognizer captures the user's turn; the counterpart's reply is spoken back through platform TTS with an audio session configured to coexist with recording. Latency is budgeted end to end (target: 2.5 seconds from "you stop talking" to "they start talking"), which shaped several decisions — short system prompts, replies capped at 1-3 sentences, sentence-level TTS playback.

Two separate model calls, on purpose. One prompt makes the counterpart only a counterpart: stay in character, react to the last thing said, never give advice. A second call, made after the conversation ends, is the coach: it scores the five axes and is required to quote verbatim substrings of the user's own lines as evidence. Splitting them is what keeps the roleplay from collapsing into a chatbot that helpfully explains what you should have said while you are still talking.

A Cloudflare Worker proxy holds the OpenAI key so it never ships in the app binary, gates requests with an app token, enforces a model allowlist so a leaked token cannot run up a bill on an expensive model, and routes through Cloudflare AI Gateway (OpenAI region-blocks some egress IPs, including from where I build).

Graceful degradation is a feature, not a fallback. With no key, no network, or no microphone permission, the app still completes a full practice loop: a scripted offline counterpart per scenario, an on-device baseline evaluator that scores using linguistic markers and still quotes real sentences, and a typing input path. The UI says honestly which mode you are in rather than pretending.

RevenueCat for monetization on both stores, with a single pro entitlement that every paid product attaches to, so the app never has to know which store a subscriber came from.

Challenges I ran into

Making the AI a person, not an assistant. The first version kept helping. Ask it to play a defensive employee and it would answer defensively and then add a tip about how to phrase things better. The fix was hard separation — a system prompt that forbids advice and stage directions, one reaction per turn, plus difficulty rules that govern how many times the character pushes back before converging.

Feedback specific enough to act on. Generic scores are useless. The evaluation prompt requires verbatim quotes of the user's own sentences; the on-device fallback does the same without a model, detecting hedges, vague timing, acknowledgment markers, and concrete dates in the transcript.

A paywall that tells the truth. When RevenueCat offerings fail to load, the easy thing is to show hardcoded prices. Instead the app says products are unavailable and offers retry. This surfaced a real bug during Android testing — and the honest message is what made the cause obvious in seconds.

Getting the store timeline right. Google Play requires new apps from individual accounts to run a 12-tester / 14-day closed test before production access. I checked my own history — a previous app took 11 days for approval alone — and concluded a public Play launch inside the hackathon window was not realistic. So I restructured around the App Store and Galaxy Store for the launch requirement, started the Play closed test immediately, and kept the timeline honest instead of optimistic.

Accomplishments that I'm proud of

  • The core loop genuinely works: I have had conversations where the AI counterpart pushed back in a way that made me stop and rethink my sentence — which is the entire product thesis.
  • Feedback that quotes you. Seeing your own hedge sentence on screen next to a better version is a different experience from reading generic advice.
  • The app degrades honestly at every layer instead of faking it.
  • Bilingual all the way down: 20 scenarios x 2 languages, with conversation language decoupled from UI language.

What I learned

That the hard part of an AI product is usually restraint. Almost every quality problem I hit was solved by making the model do less: shorter replies, one reaction per turn, no advice during roleplay, evidence-constrained evaluation. Also that shipping infrastructure — store timelines, signing keys, verification deadlines, billing availability on emulators — deserves as much planning as the code.

What's next for SayBetter AI

  • Live coaching captions during a conversation, for users who want a safety net.
  • Role packs: sales, customer support, interviews, performance reviews.
  • Speech-quality signals — pace, filler words, silence — layered onto the five axes.
  • Team dashboards, so a manager can assign practice instead of just recommending it.

Built With

Share this project:

Updates

Submission history