Spoken Updates Are Not Heard
Symptom
An agent reports it spoke a status update, but the user — often working screen-off, by voice — did not hear anything.
Why
Autonomy owns one serialized speech lane per session so that spoken updates
are audible, ordered, and don’t collide. The only reliable path into that
lane is the voiceover_transport_announce tool. Raw say, osascript, or
other host-specific TTS calls bypass it entirely — including Autonomy’s own
speak_text tool, which runs its own speech job outside the session’s
serialized queue. If an agent used any of those instead of
voiceover_transport_announce, “the agent spoke” and “the user heard
something coherent” are not the same claim.
Even when voiceover_transport_announce is used correctly, delivery is
reported as evidence, not a guarantee of perception. The response’s
deliveryEvidence array tells you what actually happened:
voiceover_direct_requested— direct VoiceOver output was attempted.tts_fallback_used— Autonomy fell back to its TTS lane (direct VoiceOver output wasn’t available or didn’t succeed).speech_queue_entered— the message entered the serialized per-session queue and will be spoken in order.user_heard_unverified— the runtime requested delivery, but the user has not confirmed hearing it.
user_heard_unverified appears on essentially every successful delivery —
it is not, by itself, a failure signal. Only a failed tag (or the absence
of any _requested/_succeeded pair) means delivery actually broke. Never
label NSAccessibility.announcementRequested — or any delivery evidence
short of explicit user confirmation — as “heard.”
Fix
Confirm the transport used
Check that the update was actually sent through Autonomy’s transport, not a
raw OS call. If code or an agent instruction is calling say, osascript,
or speak_text for user-facing status, switch it to
voiceover_transport_announce.
Check Accessibility and Screen Recording permissions
The screen-reader delivery channel depends on the same live-probed grants covered in Permissions missing:
a7y-cli doctorRe-send the announcement and read the response
Don’t assume success from a lack of an error:
a7y-cli tools call voiceover_transport_announce \
--args '{"message":"Build finished.","agentId":"claude","spokenName":"Claude"}'Check for a TTS fallback
If deliveryEvidence contains tts_fallback_used, direct VoiceOver output
wasn’t available — that’s expected on some setups, not necessarily an
error, but worth knowing if the user reports a different voice or cadence
than expected.
Verify
Look for a failed tag in deliveryEvidence, and check
speechOutputBoundary in the response — it reads
delivery_requested_user_heard_unverified on the normal path, or
delivery_failed_user_heard_unverified if every delivery method failed.
Only the latter is an actual problem to chase.
For a session-wide view (current speech policy, queue state), call:
a7y-cli tools call voiceover_transport_statusIf updates are landing but overlapping with another agent’s speech, see Two agents talk over each other. For the underlying permission grants this depends on, see Grant permissions.