Please read this first
- Have you read the docs? Yes.
- Have you searched for related issues? Yes. I searched issues and PRs for
RealtimeSession close iterator and Realtime close event_queue; I did not find a direct duplicate.
Describe the bug
RealtimeSession.__aiter__() waits on self._event_queue.get() while the session is open. RealtimeSession.close() eventually sets _closed=True, but it does not wake a consumer that is already blocked in Queue.get().
This can leave an async for event in session consumer blocked after another task closes the session.
Related paths and boundaries checked:
- The existing cancellation behavior still exits cleanly when the consumer task is cancelled.
- Closing an already closed session should not enqueue internal wakeup markers when no iterator is waiting.
- Multiple simultaneous event iterators should all be woken when the session closes.
- This is separate from tool-call cleanup and unknown-tool handling, which are covered by separate candidates.
Debug information
- Agents SDK version:
main at 683b6e79 (latest release tag checked locally: v0.17.0)
- Python version: Python 3.12.1
Repro steps
Run this script against current main:
import asyncio
from typing import Any
from agents.realtime.agent import RealtimeAgent
from agents.realtime.model import RealtimeModel, RealtimeModelConfig
from agents.realtime.model_inputs import RealtimeModelSendEvent
from agents.realtime.session import RealtimeSession
class DummyModel(RealtimeModel):
async def connect(self, options: RealtimeModelConfig) -> None:
pass
def add_listener(self, listener: Any) -> None:
pass
def remove_listener(self, listener: Any) -> None:
pass
async def send_event(self, event: RealtimeModelSendEvent) -> None:
pass
async def close(self) -> None:
pass
async def main() -> None:
session = RealtimeSession(DummyModel(), RealtimeAgent(name="agent"), None)
iterator = session.__aiter__()
next_event = asyncio.ensure_future(iterator.__anext__())
await asyncio.sleep(0.01)
await session.close()
done, pending = await asyncio.wait({next_event}, timeout=0.1)
print("done:", bool(done))
print("pending:", bool(pending))
for task in pending:
task.cancel()
await asyncio.gather(*pending, return_exceptions=True)
asyncio.run(main())
Actual output:
done: False
pending: True
Expected behavior
Closing a realtime session should wake iterators that are already waiting for the next event. The pending __anext__() should complete with StopAsyncIteration instead of staying blocked.
Please read this first
RealtimeSession close iteratorandRealtime close event_queue; I did not find a direct duplicate.Describe the bug
RealtimeSession.__aiter__()waits onself._event_queue.get()while the session is open.RealtimeSession.close()eventually sets_closed=True, but it does not wake a consumer that is already blocked inQueue.get().This can leave an
async for event in sessionconsumer blocked after another task closes the session.Related paths and boundaries checked:
Debug information
mainat683b6e79(latest release tag checked locally:v0.17.0)Repro steps
Run this script against current
main:Actual output:
Expected behavior
Closing a realtime session should wake iterators that are already waiting for the next event. The pending
__anext__()should complete withStopAsyncIterationinstead of staying blocked.