Skip to content

fix: create AsyncOpenAI lazily in trajectory_compressor to avoid closed event loop - #3696

Closed
binhnt92 wants to merge 1 commit into
NousResearch:mainfrom
binhnt92:fix/trajectory-compressor-async-client-reuse
Closed

fix: create AsyncOpenAI lazily in trajectory_compressor to avoid closed event loop#3696
binhnt92 wants to merge 1 commit into
NousResearch:mainfrom
binhnt92:fix/trajectory-compressor-async-client-reuse

Conversation

@binhnt92

Copy link
Copy Markdown
Contributor

The AsyncOpenAI client in trajectory_compressor.py is created once at __init__ time and stored as self.async_client. When process_directory() calls asyncio.run(), it creates a fresh event loop, runs async work, then closes the loop. On a second call to process_directory(), the cached client's internal httpx transport is still bound to the now-closed loop, raising RuntimeError: Event loop is closed.

This is the same pattern fixed by PR #3398 for the main agent loop's AsyncOpenAI client.

Changes Made

  • Removed eager AsyncOpenAI(...) construction from _init_summarizer()
  • Added _get_async_client() method that creates a fresh client on each call, binding it to the current running event loop
  • Updated the single call site in _generate_summary_async() to use _get_async_client()

How to Test

python3 -m pytest tests/test_trajectory_compressor_async.py -v

5 tests covering: client is None after init, lazy creation works, fresh instance per call, source verification (no eager creation, method exists).

Checklist

  • Tests added (5 tests)
  • Full test suite run — no regressions
  • Tested on Linux (Ubuntu 22.04)

…ed event loop

The AsyncOpenAI client was created once at __init__ and stored as an
instance attribute. process_directory() calls asyncio.run() which creates
and closes a fresh event loop. On a second call, the client's httpx
transport is still bound to the closed loop, raising RuntimeError:
"Event loop is closed" — the same pattern fixed by PR NousResearch#3398 for the
main agent loop.

Create the client lazily in _get_async_client() so each asyncio.run()
gets a client bound to the current loop.
@teknium1

Copy link
Copy Markdown
Contributor

Merged via #4013. Bug confirmed E2E — eager AsyncOpenAI creation caused stale loop binding on repeated process_directory() calls. Authorship preserved, all 5 tests pass. Thanks @binhnt92!

@teknium1 teknium1 closed this Mar 30, 2026
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