Skip to content

fix(tools): await coroutine returned by sync wrapper in CrewStructuredTool.ainvoke - #7475

Open
parthiban-sivakumar wants to merge 1 commit into
crewAIInc:mainfrom
parthiban-sivakumar:parthiban/fix/structured-tool-ainvoke-await
Open

parthiban-sivakumar wants to merge 1 commit into
crewAIInc:mainfrom
parthiban-sivakumar:parthiban/fix/structured-tool-ainvoke-await

Conversation

@parthiban-sivakumar

@parthiban-sivakumar parthiban-sivakumar commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

Related issue

Fixes #7474

Summary

For an async @tool, to_structured_tool() stores func=self._run, and Tool._run is a sync method that returns self.func(...). So in CrewStructuredTool.ainvoke(), inspect.iscoroutinefunction(self.func) is False, the call goes through run_in_executor, and the coroutine it returns was handed straight back. The tool body never ran, and on the async agent path the LLM saw <coroutine object ...> as the observation.

ainvoke() now awaits the result when it is awaitable, the same way invoke(), BaseTool.run, Tool.run and Tool._arun already handle a returned coroutine. The get_event_loop() call is left as is, since #5969 and #4832 cover that line.

Verification

  • Tests added or updated for the changed behavior
  • Relevant tests and quality checks pass locally

Added test_ainvoke_awaits_coroutine_from_sync_wrapper: an async @tool converted with to_structured_tool() returns its value from ainvoke(), runs its body once, and counts one usage. It fails on main with assert <coroutine object ...> == 'data:x' and passes with the fix.

Full lib/crewai/tests/: 5472 passed, 43 skipped. ruff and mypy clean on the changed files.

…dTool.ainvoke

An async @tool reaches ainvoke through Tool._run, a sync wrapper, so the executor returned the un-awaited coroutine and the tool body never ran. Await the result when it is awaitable, as invoke() already does.
@coderabbitai

coderabbitai Bot commented Sep 15, 2026

Copy link
Copy Markdown

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: 78f12a2d-4249-4af7-b67e-1899026fb99d

📥 Commits

Reviewing files that changed from the base of the PR and between 66ef97c and bc71130.

📒 Files selected for processing (2)
  • lib/crewai/src/crewai/tools/structured_tool.py
  • lib/crewai/tests/tools/test_structured_tool.py

Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.


📝 Walkthrough

Walkthrough

CrewStructuredTool.ainvoke now awaits coroutine results returned by synchronous wrappers. A test covers the decorated async tool path and verifies the result, recorded call, and usage count.

Changes

Awaitable result handling

Layer / File(s) Summary
Await awaitable invocation results
lib/crewai/src/crewai/tools/structured_tool.py, lib/crewai/tests/tools/test_structured_tool.py
ainvoke awaits executor results when they are awaitable. The new test verifies the returned data, recorded query, and current_usage_count value.

Suggested reviewers: joaomdmoura

Priority: ⬇️ Low

Merge Risk: ⚪ Minimal · up to bc711

The async tool execution issue is addressed and covered by a focused test; no concrete merge-blocking risk remains.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 5 functions across 2 files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly and concisely identifies the main change: awaiting a coroutine returned by the synchronous wrapper in CrewStructuredTool.ainvoke.
Description check ✅ Passed The description includes the related issue, explains the problem and solution, and documents verification results. The optional Additional context section is missing, but the required information is o…
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant