Inspiration
For a lot of autistic and socially anxious young people, the hardest conversations aren't the big ones. They're the tiny everyday ones: ordering food, asking a teacher for an extension, joining a lunch table mid-conversation. They're unpredictable, they run at someone else's pace, and there's a social cost if they go wrong. There's nowhere to practice them. Roleplaying with a parent feels fake, and text chatbots skip the hardest part: the real-time pressure of speaking and listening.
Rehearse started from one question: what would a practice space look like if the user controlled the pace of the conversation, always?
What it does
Rehearse is a voice agent that plays the other person in an everyday scenario, out loud, in the browser. You pick a scenario (ordering at a restaurant, asking a teacher for an extension, joining classmates at lunch), choose how the other person acts (friendly or everyday), and talk.
The design promises, all enforced rather than suggested:
- You speak first. The agent never opens with a surprise. If you want them to start, you tap "Let them start". Predictability is an accessibility feature.
- The pace bar never moves. Pause, Slower please, Start over, End and get feedback: same four buttons, same order, same place, on screen the entire session.
- A distress tripwire lives in code, not in the prompt. Say "stop", "too much", or "I can't do this" and a pattern matcher catches it before the language model ever sees the turn. The scenario halts instantly, the agent drops out of character into calm de-escalation, and the UI shifts with it. The model is never given the chance to stay in character past a distress signal.
- Feedback, never a grade. Two specific things that went well, one gentle "next time you could try", nothing else. Transcript available, collapsed by default.
How neurodivergent users shaped it
Yicheng Cui, a volunteer tester from the hackathon community, ran full sessions across all three scenarios and sent detailed written feedback. All of it changed the build the same day.
He told us the scenarios "were not as comprehensive as I anticipated": the restaurant agent "only continues the conversation if users respond with the select few dishes within its narrow, assigned range", and the teacher had no real assignment context. The restaurant is now Maple Street Diner with a full priced menu and suggests the closest dish instead of refusing off-menu orders; the teacher scenario now has a named teacher, a real essay assignment and a deadline to negotiate around.
His sharpest catch: he Googled the show our classmates scenario referenced and told us "I can't find it on Google... I think it may be fake." He was right, it was invented, and it broke his trust in the scenario. That taught us something real about designing for literal-minded users: invented details that neurotypical users gloss over read as errors. Our first instinct was to invent a more convincing show; the correct fix was the opposite. The classmates now ask what you've been watching, so the conversation runs on the user's real world, and the agent is forbidden from inventing plot details for titles it doesn't know.
He also reported the Slower button made no perceivable difference, which was true. It now enforces one short sentence per reply with real pauses, and native speech-rate control is on the roadmap as an engine change.
What he validated mattered as much: "when I say 'stop'... the safety mode works fabulously" and "I would use it in half of my daily scenarios."
How we built it
Real-time voice: LiveKit Agents with Deepgram Flux for speech-to-text (Flux's native end-of-turn detection drives turn taking) and Deepgram Aura for the voice. The LLM is gemma4:31b on Ollama cloud wrapped in LiveKit's FallbackAdapter with Groq behind it, so if the primary provider degrades mid-conversation the session fails over automatically instead of stalling.
The backend is FastAPI. Scenario personas, moods, tripwire phrase lists and the persona ceiling (no mockery, no rushing, one question at a time, plain language, no idioms) are all config as data, so adding a scenario is an edit, not a refactor. Everything is instrumented: JSON-lines logging with per-turn latency spans across STT finalisation, LLM handoff and TTS.
The frontend is React with Tailwind. Body text is Atkinson Hyperlegible, a typeface designed for legibility. Muted palette, near-zero animation, reduced motion respected, and the safe mode state has its own calm visual treatment.
Challenges we ran into
The voice pipeline was adapted from a production out-of-hours call agent for service trades, and the interesting challenge was inverting its values. A booking agent is optimised to drive a conversation forward efficiently; Rehearse had to be optimised to never drive at all. The user leads, the agent follows, silence is fine. That inversion touched everything: turn taking, prompt design, even which participant speaks first.
The second challenge was making safety real rather than rhetorical. A system prompt that says "stop if the user is distressed" is a suggestion to a model. A pattern matcher that halts the scenario before the model sees the turn is a guarantee. We chose the guarantee.
What we learned
The biggest lesson came from our tester: authenticity is an accessibility feature. An invented detail that most users would gloss over broke trust for a literal-minded user, and the right fix wasn't better fiction, it was grounding the conversation in the user's real world. We also learned that "felt pace" is more about utterance length and silence than speech speed, and that the accessibility choices we were most nervous about (the always-visible pace bar, user-speaks-first) were the ones our tester didn't even comment on, because they simply worked.
What's next for Rehearse
A third difficulty setting (a bit impatient) gated on tester validation. A structured pre-scenario questionnaire so conversations carry the user's real context, an idea from our tester's feedback. A custom scenario builder for rehearsing the specific conversation you're dreading. Native speech-rate control at the engine level. More voices and accents, including West African English.
Built With
- celery
- deepgram
- fastapi
- groq
- livekit
- ollama
- python
- react
- tailwind
- typescript
Log in or sign up for Devpost to join the conversation.