Two Agents Talk Over Each Other
Symptom
Two voices speak at the same time, or spoken updates interleave mid-sentence, when more than one agent is active against the same Autonomy session.
Why
Autonomy serializes spoken output through one speech queue per attached
session — a single lock that each voiceover_transport_announce call
acquires before speaking and holds for the real audio lifetime, not just an
estimated duration. Overlap happens for one of two reasons:
- An agent bypassed the queue. Only
voiceover_transport_announceacquires the session’s speech slot.speak_text, rawsay, orosascriptcalls speak immediately, on top of whatever Autonomy is already saying. - Agents aren’t identified. Without a registered
agentIdandspokenName, announcements fall back to a generic “Autonomy agent” prefix, so even correctly serialized speech is hard to attribute to the right agent — and it’s easy to assume two overlapping calls are a queue bug when they’re actually just unlabeled.
This was a real, fixed defect (tracked as autonomy-r0r23): the speech slot
now spans the actual audio playback, and is released even if the requesting
client disconnects mid-call, so a dropped connection can’t leave the lane
stuck or let the next message speak over an unfinished one.
Keep agent-to-agent development coordination (build status, handoffs between coding agents) out of the user’s spoken accessibility lane entirely. That’s a separate channel’s job — the spoken lane is for the user, not for agents talking to each other.
Fix
Register each agent’s identity once per session, before it speaks
a7y-cli tools call voiceover_transport_session_policy \
--args '{"agentId":"claude","spokenName":"Claude"}'a7y-cli tools call voiceover_transport_session_policy \
--args '{"agentId":"codex","spokenName":"Codex"}'Announce through the same tool from every agent
Pass each agent’s own agentId so the response is attributed and
serialized correctly:
a7y-cli tools call voiceover_transport_announce \
--args '{"message":"Tests passed.","agentId":"claude"}'Leave queue at its default (true) — don’t disable it to “speed things
up.” Disabling the queue is what reintroduces overlap.
Verify
Check the response’s action.speaker.spokenName and spokenPrefix —
each agent’s messages should carry its own name (rendered as
"<Name> says: …"), not the generic default. Fire two announcements back to
back from different agents and confirm the second one’s
speechQueue.mode reads serialized_session_queue and that it doesn’t
start speaking until the first finishes, rather than interleaving.
If a single agent’s own updates are the ones going unheard rather than overlapping, see Spoken updates are not heard. If calls are being dropped outright rather than overlapping, see The daemon closes a request.