Choose what to speak
Summary, closing, brief, and full select different slices of the same agent turn. Junk turns stay silent.
The sanitizer turns Markdown into an utterance queue, then the mode keeps a slice of that queue. Toggle a mode on the same sample turn:
First prose paragraph. Default. Often the “I’ll look at that” line.
Agent turn
Fix the Stop hook timeout
I'll check the Cursor adapter and the shared runner. Then I'll raise the timeout and add a test.
The stop hook currently times out at 10 seconds, which is enough to notify the daemon but not to wait on playback. I raised it in hosts/cursor/hooks.json and documented why.
Keep the hook fail-open. A TTS failure must never block the turn.
see codeblock below
The tests are green. Bind skip to a hotkey next.
What you hear
- prose
“I'll check the Cursor adapter and the shared runner. Then I'll raise the timeout and add a test.”
Why summary is often the wrong paragraph
Agents usually open with a plan ("I'll check the adapter") and close with the result ("The tests are green"). Summary speaks the first prose paragraph, so you hear the plan. Closing speaks the last prose paragraph, so you hear the result.
tts closingMode is global for the data directory (~/.agent-tts/config.json). Every session sharing that directory uses the same mode.
What each mode keeps
Given this turn:
# Fix the Stop hook timeout
I'll check the Cursor adapter and the shared runner. Then I'll raise the timeout and add a test.
The stop hook currently times out at 10 seconds…
> Keep the hook fail-open.
{ "timeout": 90 }
The tests are green. Bind skip to a hotkey next.| Mode | Spoken | Skipped |
|---|---|---|
| summary | Lead paragraph ("I'll check…") | Heading, body, quote, code pointer, closing |
| closing | Last paragraph ("The tests are green…") | Everything above it |
| brief | First sentence of the lead paragraph | The rest of that paragraph, and every other block |
| full | Heading, every paragraph, quote, see codeblock below | Raw code and table cells (replaced by pointers) |
Replay can override the configured mode for one playback:
tts replay closing
tts replay fullVoices
Prose and headings can use different system voices:
tts voice prose Samantha
tts voice header DanielIf header_voice is unset, headings use the prose_voice and the distinction is off. Cloud backends use the provider voice id from tts cloud voice unless a per-utterance voice is set.
Turns that stay silent
After sanitizing, the queue is dropped when:
- it is empty
- every utterance is a pointer (
see codeblock below/see table below) - the whole queue is shorter than three words (
Done.,OK.)
A one-line "Done." in full mode is silent on purpose. If you need to hear short acks, that threshold is _MIN_SPEAK_WORDS in sanitize.py.