Skip to Content
TroubleshootingSpoken updates not heard

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 doctor

Re-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_status

If 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.

Last updated on