Skip to content

Replace deprecated asyncio.get_event_loop() with asyncio.get_running_loop() in coroutine contexts - #8914

Open
LVsarff wants to merge 1 commit into
crewAIInc:mainfrom
LVsarff:fix/get-running-loop
Open

LVsarff wants to merge 1 commit into
crewAIInc:mainfrom
LVsarff:fix/get-running-loop

Conversation

@LVsarff

@LVsarff LVsarff commented Nov 1, 2026 •

Copy link
Copy Markdown

Summary

asyncio.get_event_loop() is deprecated since Python 3.12 (and raises RuntimeError in Python 3.14 when no current loop exists). In coroutine contexts the recommended replacement is asyncio.get_running_loop(), which returns exactly the same loop with no deprecation.

This PR replaces the three usages in lib/crewai that are always executed inside a running event loop:

  • src/crewai/tools/structured_tool.py — inside async def _arun, so a loop is always running
  • src/crewai/rag/chromadb/client.py — inside async def _alocked, so a loop is always running
  • src/crewai/utilities/streaming.py — the use_async=True branch of create_streaming_state, which is only reached from async kickoff paths (Crew.kickoff_async / streaming kickoff), so a loop is always running

Changes

One-line, behavior-identical replacement of asyncio.get_event_loop() with asyncio.get_running_loop() in each of the three files above.

Verification

  • py_compile passes for all three files
  • ruff check --no-fix reports no new findings on the changed lines (existing findings in these files are pre-existing and untouched)
  • Call-path analysis confirms each site executes only inside a coroutine, so get_running_loop() returns the same loop get_event_loop() would

Fixes #8912

Note: this PR supersedes #8910, which was submitted without an issue reference and auto-closed by the first-time-contributor gate as a result (reopen is not permitted for external contributors).

LLM disclosure

This change was prepared with the assistance of an AI coding agent and reviewed before submission. Per the repository's contribution guidelines, please add the llm-generated label to this PR if appropriate (I don't have permission to add labels myself).


Note

Low Risk
Mechanical asyncio API update with no intended behavior change; each site is already inside a running coroutine.

Overview
Replaces deprecated asyncio.get_event_loop() with asyncio.get_running_loop() in three lib/crewai call sites that always run inside an active event loop, avoiding Python 3.12+ deprecation warnings and Python 3.14 failures when no default loop exists.

The swap is one line each in ChromaDB async locking (_alocked), sync tool execution from ainvoke via run_in_executor, and async streaming setup when create_streaming_state(use_async=True) (and the same pattern already used in frame streaming). Runtime behavior should be unchanged: the running loop is the same object the old API would return in these paths.

Reviewed by Cursor Bugbot for commit 20d369f. Bugbot is set up for automated code reviews on this repo. Configure here.

@strix-security

strix-security Bot commented Nov 1, 2026 •

Copy link
Copy Markdown

Strix Security Review

✅ No open security findings.

PR summary: Replaces three deprecated asyncio.get_event_loop() calls in lib/crewai with asyncio.get_running_loop() at sites that always execute inside a coroutine.

Review summary

This PR makes three one-line, behavior-equivalent replacements of asyncio.get_event_loop() with asyncio.get_running_loop() to fix a Python 3.12+ deprecation. I verified each changed site is reached only with a running event loop, so the new call cannot introduce a RuntimeError path: _alocked and CrewStructuredTool.ainvoke are coroutine bodies, and the use_async=True branch of create_streaming_state is only reached from StreamingContext(use_async=True)/ForEachStreamingContext, both instantiated inside kickoff_async/akickoff/run_for_each_async. The change touches no input handling, authentication, secret material, serialization, or query construction, so it neither weakens an existing control nor creates a new attack surface. No security issues found in the changed code.

Ruled out (1)
  • Can asyncio.get_running_loop() raise RuntimeError at any of the three sites where get_event_loop() previously succeeded?
    Every caller of the use_async branch of create_streaming_state is an async def (kickoff_async, akickoff, run_for_each_async), and the other two sites are inside coroutines, so a running loop always exists.

Review 1 on this PR · 20d369f · requested Nov 1 13:21 UTC when the PR was opened


Reviewed by Strix
Re-run review · Configure security review settings

This branch has not been deployed

No deployments
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.

[BUG] Deprecated asyncio.get_event_loop() calls in lib/crewai and lib/crewai-tools

1 participant