done
Separate session and turn behavior. A WebSocket session is the ongoing conversation. A turn starts with one user message and finishes after ChatAgent has produced the visible reply, including any EventAgent handoff and final ChatAgent response.
The UI currently closes and recreates the WebSocket for every submit. The backend runtime also treats done as the end of the whole run after one user message. round_index is a ChatAgent call counter, so the post-event ChatAgent call appears as a second round with events_enabled=[], which is expected for a one-event-loop turn but confusing without turn boundaries.
turn_started and turn_completed events.runtime.run() behavior for tests and smoke helpers.user_message on an open socket and handles turn_completed.uv run pytest tests/test_debug_runtime.py tests/test_websocket_api.py -q passes: 45 tests.uv run pytest passes: 56 tests.