fix(interop/langchain): use arun for async langchain tools#2806
Open
obchain wants to merge 2 commits into
Open
fix(interop/langchain): use arun for async langchain tools#2806obchain wants to merge 2 commits into
obchain wants to merge 2 commits into
Conversation
LangChainInteroperability.convert_tool always wrapped the langchain tool with the sync run() dispatcher, even when the tool defined a native async implementation. Inside an asyncio event loop (e.g. a_initiate_chat), this blocks on the synchronous path and degrades concurrency. Detect tools that provide a native coroutine — StructuredTool with `coroutine=...` or BaseTool subclasses that override `_arun` — and wrap those with an async function that awaits `langchain_tool.arun(...)`. Sync tools keep the existing sync wrapper for backward compatibility, and the behavior for tools whose async impl is just a thread-pool fallback of `_run` is left unchanged. Add regression tests covering both StructuredTool(coroutine=...) and class-based BaseTool subclasses with overridden _arun. Fixes ag2ai#1402
Replace the if/else `def func` shadowing pattern with two distinct helpers (`async_func`, `sync_func`) assigned to a single `func` variable of type `Callable[..., Any]`. Drops the 'All conditional function variants must have identical signatures' mypy [misc] error and removes the no-any-unimported error by widening `_has_async_run`'s parameter annotation to `Any` (it already guards on isinstance internally).
Codecov Report❌ Patch coverage is
... and 38 files with indirect coverage changes 🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why are these changes needed?
LangChainInteroperability.convert_toolalways wrapped the langchain tool with the synchronousrun()dispatcher, even when the tool defined a native async implementation. Calling such a converted tool inside an asyncio event loop (e.g.a_initiate_chat) blocks on the sync path and defeats the point of using an async langchain tool — exactly the behaviour reported in #1402.Fix
Detect tools that provide a native coroutine and switch to an async wrapper that awaits
langchain_tool.arun(...):StructuredTool(created via@langchain_core.tools.toolon anasync def) — detected viacoroutine is not None.BaseToolsubclasses that override_arun— detected by comparingtype(t)._arunagainstBaseTool._arun.Tools without a native async implementation keep the existing synchronous wrapper — converting them to async would only wrap
_runin a thread executor, which would be a behaviour change with no benefit for existing sync-only callers.Tests
TestLangChainInteroperabilityAsync—StructuredTool(coroutine=...)path: wrapper is a coroutine function and runs througharun.TestLangChainInteroperabilityClassBasedAsync—BaseToolsubclass with overridden_arun: same checks. The class's_runraisesNotImplementedErrorso any accidental fallback to the sync dispatcher would surface as a test failure.TestLangChainInteroperability,TestLangChainInteroperabilityWithoutPydanticInput) continue to pass — the sync wrapper is preserved when no native coroutine is detected.uv run pytest test/interop/langchain/test_langchain.py -vv→ 8 passed, 2 skipped (OpenAI-credential gated).Related issue number
Fixes #1402
Checks
AI assistance