Uh oh!
There was an error while loading. Please reload this page.
fix(agents): fresh google client for run_agent_sync agent routes (part of #354) - #357
Conversation
Same root cause as the streaming fix (#349): the shared module-level GoogleProvider is unsafe across event loops. run_agent_sync drives agents on throwaway per-request loops (asyncio.run) in reused threadpool threads, so the shared client's pooled connection outlives its loop and trips "Event loop is closed" on the next call -> flaky 500s (repro: concept-description returns 500/200/500 on repeat). - concept_describe + course_summary now run on fresh_model_for(...) clients. - run_agent_sync hardened: from a running loop it closes the coroutine (no "never awaited" warning) and raises clearly instead of degrading. - Adds test_run_agent_sync_loop.py. Remaining sites (study_guide, social, documents, quiz_context, flashcard_import, health-probe) still need the same treatment -- see #354. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Deploying with |
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs | frontend-staging | 6f37e57 | Commit Preview URL Branch Preview URL | Jul 18 2026, 04:54 AM |
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Free Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Note 🎁 Summarized by CodeRabbit FreeYour organization is on the Free plan. CodeRabbit will generate a high-level summary and a walkthrough for each pull request. For a comprehensive line-by-line review, please upgrade your subscription to CodeRabbit Pro by visiting https://app.coderabbit.ai/login. Comment |
AndresL230
commented
Jul 18, 2026
Folding into #349 — same root cause (shared google client unsafe across event loops) and same helper. The commit now lives on |
Part of #354. Stacked on #349 (
feat/streaming-tutor) — merge that first.Root cause
Same one as #349's streaming crash: the module-level shared
google.genaiclient (agents/_providers.py::_provider) is unsafe across event loops. Its httpx pool caches connections bound to the loop that opened them; reusing/closing one on a different (or already-closed) loop tripsRuntimeError: Event loop is closed.run_agent_sync()drives agents on throwaway per-request loops (asyncio.run) inside FastAPI's reused sync-handler threadpool threads — so the 2nd call in a thread trips over the 1st call's stale connection.Reproduced on
main:POST /api/graph/{user_id}/concept-descriptionreturns a flaky500 / 200 / 500on repeat calls (surfaced as React errors in the Learn knowledge-map).What this does
concept_describe(routes/graph.py) andcourse_summary(services/course_context_service.py) now run on a fresh client viamodel=fresh_model_for(...).run_agent_synchardened: when misused from a running event loop it now closes the coroutine (kills the "coroutine was never awaited" warning) and raises a clear error the caller degrades on — instead of blocking the loop or leaking.tests/test_run_agent_sync_loop.py.The
fresh_google_model/fresh_model_for/model_name_forhelpers land in #349.Verification
POST /api/graph/{u}/concept-description× 5 in a row → 200 every time (was 500/200/500 onmain); 0Event loop is closedin logs.donewith graph deltas; non-streaming/chatunaffected.161 passedacross the affected suites (learn, graph, quiz, social, study_guide, course_context, streaming, run_agent_sync).Not in this PR (remaining #354 scope)
The same one-line fresh-client fix still needs applying to the other sync-handler agent routes:
study_guide.py:104,social.py:142,documents.py:245,quiz.py:459,flashcard_import_service.py:249,main.py:222. Tracked in #354.🤖 Generated with Claude Code