aloof-scooter-47164
12/22/2025, 2:06 AM19:58:43.616 DEBUG livekit.…ns.openai <<< {'type': 'error', 'event_id': 'event_CS', 'error': {'type': 'invalid_request_error',
'code': 'conversation_already_has_active_response', 'message': 'Conversation already has an active response in
progress: resp_. Wait until the response is finished before creating a new one.', 'param':
None, 'event_id': None}}
ERROR livekit.…ns.openai OpenAI Realtime API returned an error
{"error": "RealtimeError(message='Conversation already has an active response in progress:
resp_CmSrSgYHYc4spjMtDTWnf. Wait until the response is finished before creating a new one.', type='invalid_request_error',
code='conversation_already_has_active_response', event_id=None, param=None)",
19:58:43.617 DEBUG events Recoverable error: OpenAI Realtime API returned an error (body=RealtimeError(message='Conversation already has
an active response in progress: resp_. Wait until the response is finished before creating
a new one.', type='invalid_request_error', code='conversation_already_has_active_response', event_id=None,
param=None), retryable=True)tall-airline-16756
12/22/2025, 2:06 AMtall-airline-16756
12/22/2025, 2:06 AMconversation_already_has_active_response that’s preventing new replies.
Why this happens (brief)
• The model is already producing a response (audio/text). The Realtime API prevents starting another response until the active one finishes.
What you can do (practical steps)
1. Wait for the current response to finish before calling generate_reply() again.
◦ Use the SpeechHandle returned by generate_reply() / say() and await it so you only start the next reply after it completes.
1. Guard calls so you don’t start concurrent replies.
◦ Check agent state before generating:
if session.agent_state != voice.AgentState.IDLE:
return # or queue the request
await session.generate_reply(...)
• Or serialize with a mutex/lock:
from asyncio import Lock
speech_lock = Lock()
async def safe_generate(instructions):
async with speech_lock:
handle = session.generate_reply(instructions=instructions)
await handle
1. Avoid duplicate triggers / race conditions
◦ Deduplicate events that call generate_reply() (RPC handlers, message events, UI clicks).
◦ Add short debounce or rate-limit so repeated events don’t create multiple calls.
1. Handle interruptions and state events
◦ If a user interrupts, wait until interruption finishes then start new response.
◦ Listen for agent_speech_finished or agent_state_changed and only generate when state is IDLE.
1. Logging & debugging
◦ Log each generate_reply() call with timestamps and unique IDs to find where duplicates originate.
If you want, share:
• the snippet where you call generate_reply() (or your @session.on("error") handler),
• whether you use events like agent_state_changed or agent_speech_finished,
and I’ll point out exact places to add checks/locks or suggest a safe wrapper.
Sources: Agents (Node.js) | livekit/livekit_composite | DeepWiki | OpenAI Realtime API plugin guide | LiveKit docs | Agent speech and audio | LiveKit docsaloof-scooter-47164
12/22/2025, 2:10 AMtall-airline-16756
12/22/2025, 2:10 AMgenerate_reply() / say() is called, or your @session.on(...) handlers).
• Any customizations to the agent (middleware, RPC handlers, auto-responses, or queued prompts).
• Logs around when the first response starts and when the error occurs (timestamps for both).
In the meantime, quick checks you can do now:
• Verify the agent listens for agent_state_changed or agent_speech_finished and only issues new replies when state is IDLE.
• Search the agent code for any places that call `generate_reply()`/`say()` automatically and add a guard like a lock or a check for session.agent_state == voice.AgentState.IDLE before calling.
• Add logging around every internal generate call (unique IDs + timestamps) to see overlapping calls.
Send the code/log snippets and agent version and I’ll point out exactly where to add guards or fixes.