voice.auto_tts (flipped globally by Desktop "Read replies aloud") made
the runner synthesize a spoken reply for every A2A text task. The A2A
adapter has no native send_voice, so delivery fell back to the media
notice — the peer received "Couldn't deliver the audio attachment."
instead of the text the agent had already produced (#90103). Inbound A2A
is MessageType.TEXT; the base adapter's own auto-TTS gate keys on
MessageType.VOICE, but the runner's fallback branch
(voice_mode is None and adapter_auto_tts) had no platform gate at all.
Two aligned gates, both field-tested by the reporter:
- _should_send_voice_reply returns False for platform 'a2a' before any
mode/config consultation — the text reply lands normally.
- _sync_voice_mode_state_to_adapter never pushes the global speak
default onto the A2A adapter, so the adapter-side path cannot regress
it either.
/voice on|tts|off scoped behavior is untouched (persisted per
platform:chat_id, still honored for human platforms). Tests pin the
pair the issue asked for: A2A + global auto-TTS skips, Telegram with
the same default still voices, and the sync-side skip.
Re-implemented from PR #90121 on the GatewayVoiceMixin split (author
credited). The Desktop-scoped read-aloud preference is a separate
design change, not folded in.
Fixes#90103