Skip to content

fix(core): surface real http_context error from STT streams#5709

Merged
longcw merged 1 commit into
mainfrom
longc/http-context-helper
May 13, 2026
Merged

fix(core): surface real http_context error from STT streams#5709
longcw merged 1 commit into
mainfrom
longc/http-context-helper

Conversation

@longcw
Copy link
Copy Markdown
Contributor

@longcw longcw commented May 12, 2026

Summary

When AgentSession runs outside a job process (tests, scripts, ad-hoc usage), there's no http session bound to the event loop. The intent was for utils.http_context.http_session() to raise a clear RuntimeError, but two bugs combined to hide it:

  1. Init race in inference & cartesia SpeechStream. The base RecognizeStream.__init__ schedules _main_task via asyncio.create_task(...) before the subclass finishes init. The subclass then ran self._session = stt._ensure_session(), which can raise RuntimeError from http_session(). When it did, self._session was never assigned — but the already-scheduled task kept running, eventually hitting self._session.ws_connect(...)AttributeError: 'SpeechStream' object has no attribute '_session'. The original RuntimeError got swallowed and users saw a cryptic AttributeError with Task exception was never retrieved.

  2. No ergonomic way to set up the context outside a worker. Users running plugins in tests had to hand-roll an aiohttp.ClientSession and pass it to every plugin constructor.

Changes

  • livekit-agents/livekit/agents/inference/stt.py and livekit-plugins/livekit-plugins-cartesia/livekit/plugins/cartesia/stt.py: move _ensure_session() out of SpeechStream.__init__ and into _run(). The real RuntimeError now propagates through the task naturally.

  • livekit-agents/livekit/agents/utils/http_context.py: add a public open() async context manager for running plugins outside a job:

    async with utils.http_context.open():
        async with AgentSession() as session:
            await session.start(MyAgent())

    It's a no-op pass-through when an http context is already set up (e.g. inside a worker, or nested calls).

  • Update the http_session() RuntimeError message to point users at the new helper.

Notes

Supersedes #5608's approach of having AgentSession own the http context.

Move `_ensure_session()` out of `SpeechStream.__init__` for inference and
cartesia STT. Previously, the base `RecognizeStream.__init__` scheduled
`_main_task` before the subclass finished init, so when `_ensure_session()`
raised `RuntimeError` (no http context), the orphan task ran and surfaced
`AttributeError: '_session'` — masking the real error.

Add `utils.http_context.open()` async context manager for running plugins
outside a job (tests, scripts):

    async with utils.http_context.open():
        async with AgentSession() as session:
            await session.start(MyAgent())

Update the `http_session()` RuntimeError message to point users to the helper.
@chenghao-mou chenghao-mou requested a review from a team May 12, 2026 05:28
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 4 additional findings.

Open in Devin Review

@longcw longcw merged commit b01a645 into main May 13, 2026
37 of 38 checks passed
@longcw longcw deleted the longc/http-context-helper branch May 13, 2026 01:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants