Skip to content

fix: make native tool calls async in async execution path to avoid bl…#5227

Open
royzhz wants to merge 3 commits intocrewAIInc:mainfrom
royzhz:fix/async-native-tool-calls-blocking-event-loop
Open

fix: make native tool calls async in async execution path to avoid bl…#5227
royzhz wants to merge 3 commits intocrewAIInc:mainfrom
royzhz:fix/async-native-tool-calls-blocking-event-loop

Conversation

@royzhz
Copy link
Copy Markdown

@royzhz royzhz commented Apr 2, 2026

Problem

_handle_native_tool_calls is synchronous and uses ThreadPoolExecutor for parallel tool execution. When called from the async path (_ainvoke_loop_native_tools), it blocks the event loop, causing the entire program to hang during tool execution.

Solution

Added async counterparts for the two key methods:

  • _ahandle_native_tool_calls — replaces ThreadPoolExecutor + as_completed with asyncio.gather for parallel tool execution.
  • _aexecute_single_native_tool_call — tries original_tool.arun() first for true async execution; falls back to asyncio.to_thread(tool.run) if the tool hasn't implemented _arun, so the event loop is never blocked.

Updated _ainvoke_loop_native_tools to call await self._ahandle_native_tool_calls(). The sync path (_invoke_loop_native_tools) is unchanged.

Backward Compatibility

  • Tools that don't implement _arun automatically fall back to thread-based execution via asyncio.to_thread — no changes required from tool authors.
  • Tools that implement _arun get true async execution with no thread overhead.
  • The sync execution path is completely untouched.

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.

1 participant