Skip to content

fix(interop/langchain): use arun for async langchain tools#2806

Open
obchain wants to merge 2 commits into
ag2ai:mainfrom
obchain:fix/issue-1402
Open

fix(interop/langchain): use arun for async langchain tools#2806
obchain wants to merge 2 commits into
ag2ai:mainfrom
obchain:fix/issue-1402

Conversation

@obchain
Copy link
Copy Markdown
Contributor

@obchain obchain commented May 12, 2026

Why are these changes needed?

LangChainInteroperability.convert_tool always wrapped the langchain tool with the synchronous run() 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.tool on an async def) — detected via coroutine is not None.
  • Class-based BaseTool subclasses that override _arun — detected by comparing type(t)._arun against BaseTool._arun.

Tools without a native async implementation keep the existing synchronous wrapper — converting them to async would only wrap _run in a thread executor, which would be a behaviour change with no benefit for existing sync-only callers.

Tests

  • TestLangChainInteroperabilityAsyncStructuredTool(coroutine=...) path: wrapper is a coroutine function and runs through arun.
  • TestLangChainInteroperabilityClassBasedAsyncBaseTool subclass with overridden _arun: same checks. The class's _run raises NotImplementedError so any accidental fallback to the sync dispatcher would surface as a test failure.
  • Existing sync tests (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

  • I've included any doc changes needed (none required — internal wrapper behaviour, no public-API signature change).
  • I've added tests corresponding to the changes introduced in this PR.
  • I've made sure all auto checks have passed.

AI assistance

  • I understand the changes in this PR and can explain them in my own words.
  • I have verified that the PR description accurately reflects the actual diff.
  • If AI assistance was used, I reviewed, tested, and validated the generated code/text before submitting.

obchain added 2 commits May 12, 2026 11:53
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
Copy link
Copy Markdown

codecov Bot commented May 12, 2026

Codecov Report

❌ Patch coverage is 30.00000% with 7 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
autogen/interop/langchain/langchain_tool.py 30.00% 7 Missing ⚠️
Files with missing lines Coverage Δ
autogen/interop/langchain/langchain_tool.py 56.41% <30.00%> (-6.93%) ⬇️

... and 38 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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]: Synchronous Call of Asynchronous Langchain Tool in Autogen Interoperability System

1 participant