Humanizing iMessage assistants. Flow, timing, and voice
Aug 22, 2025 · 2 min read · guide, design, nlp, imessage · 209 reads
Simple rules that make an assistant feel quick and respectful. Merge bursts. Speak like a person. Reply once per turn.
Humanizing iMessage assistants. Flow, timing, and voice
Write like a person. Respond at the right tempo. Never spam. These rules sound obvious. They also separate a tool that people keep using from one they mute.
Message flow and timing
- Merge quick back to back messages from the same person for about two seconds, then answer once. This prevents double replies and reads like a single turn.
- When you merge, keep any attachments and combine the text in order. Then treat it as one turn.
- Process once per merged turn. Store. Think. Act. Reply. Do not send two messages for one burst.
How we wire it in code
- We keep a short buffer per sender. Every new message resets a two second timer. When the window closes we merge and process one message.
- Files:
rabbit_worker.pykeeps per sender buffers and the timer._process_user_messages()merges and calls the agent._combine_messages()joins content and keeps unique attachments. - Note:
_combine_messages()uses a set to dedupe content. If you need strict order, switch to an order preserving method.
When not to reply
- Give the model an escape hatch. If it outputs a sentinel such as
NO_RESPONSE, send nothing and mark the turn as handled. - Good uses: one word acknowledgments that add no value. Waiting on a tool. A stray ping with no question.
How we wire it in code
- The policy tells the model that it may return
NO_RESPONSE. We check the string before sending and drop the turn. - Files:
services/prompt_builder.py:get_policy_snippet()mentionsNO_RESPONSE. - Where to gate: right after the agent response in
rabbit_worker.py:_process_combined_message()or insideunified_sender.py:send()before dispatch.
How the assistant speaks
- iMessage style: be concise. Skip markdown. Be personable and brief. Avoid emoji spam.
- Email style: write a clear subject. Use clean HTML or structured text. Reply in the existing thread when it makes sense.
- Do not leak your thinking steps. Think and act. Then send a single message that reads like a human message.