Visitar URL original
fix: stop plain langchain Tools from asking the model for config by omnomkar · Pull Request #8117 · google/adk-python · GitHub
Skip to content

fix: stop plain langchain Tools from asking the model for config - #8117

Open
omnomkar wants to merge 1 commit into
google:mainfrom
omnomkar:fix/langchain-plain-tool-func
Open

omnomkar wants to merge 1 commit into
google:mainfrom
omnomkar:fix/langchain-plain-tool-func

Conversation

@omnomkar

Copy link
Copy Markdown

Link to Issue or Description of Change

1. Link to an existing issue (if applicable):

Problem:
LangchainTool.__init__ only takes tool.func / tool.coroutine for a StructuredTool. Tool and StructuredTool are siblings (both subclass BaseTool), so a plain langchain_core.tools.Tool skips that branch and falls back to Tool._run(self, *args, config: RunnableConfig, run_manager=None, **kwargs). FunctionTool builds the declaration from that signature: run_manager is ignored and *args / **kwargs are dropped, leaving config as the only required parameter. The model is asked for config, never for the wrapped function's real arguments, and every call fails the mandatory-argument check.

Solution:
Give a plain Tool the same resolution the StructuredTool branch already uses:

  1. use tool.func;
  2. otherwise use tool.coroutine (async-only tools);
  3. otherwise, if the subclass overrides _run, keep using _run (unchanged behavior);
  4. otherwise raise ValueError, as StructuredTool already does.

The change is the isinstance check plus the "_run not overridden" check, which now compares against both StructuredTool._run and Tool._run.

One intentional behavior change: Tool(func=None) with no coroutine and no _run override used to construct but could never run (it declared config and every call failed). It now raises at construction, matching StructuredTool.

Testing Plan

Unit Tests:

  • I have added or updated unit tests for my change.
  • All unit tests pass locally.

New tests in tests/unittests/integrations/langchain/test_langchain_tool.py. Following the review on #8036, they assert the declared parameters the model sees, not only the run_async result:

Test Checks
test_plain_tool_declares_func_params_not_config declares ["text"], required ["text"], no config
test_plain_tool_run_async_calls_func run_async returns the function's result
test_plain_tool_with_only_coroutine_works async-only Tool declares ["text"] and runs
test_tool_subclass_overriding_run_uses_run regression guard: _run override still used
test_plain_tool_without_func_or_coroutine_raises ValueError matching must have a func

Without the fix (src change stashed), the new tests fail as expected and the guard passes:

FAILED test_plain_tool_declares_func_params_not_config - assert ['config'] == ['text']
FAILED test_plain_tool_run_async_calls_func - mandatory input parameters are not present: config
FAILED test_plain_tool_with_only_coroutine_works - assert ['config'] == ['text']
FAILED test_plain_tool_without_func_or_coroutine_raises - DID NOT RAISE ValueError
4 failed, 11 passed

With the fix:

$ pytest tests/unittests/integrations/langchain -q
15 passed

$ pytest tests/unittests/integrations tests/unittests/tools -q
5485 passed, 40 subtests passed

pre-commit run on both files passes (ruff, isort, pyink, addlicense, codespell, ADK compliance checks).

Manual End-to-End (E2E) Tests:

The issue's repro script (no model or API key needed), Python 3.11.18, langchain-core 1.8.0:

Before:

Tool func: Tool._run
Tool declares: ['config'] required: ['config']
Tool run_async: {'error': 'Invoking `shout()` failed as the following mandatory input parameters are not present:\nconfig ...'}
StructuredTool declares: ['text'] required: ['text']
StructuredTool run_async: HI

After:

Tool func: shout
Tool declares: ['text'] required: ['text']
Tool run_async: HI
StructuredTool declares: ['text'] required: ['text']
StructuredTool run_async: HI

Checklist

  • I have read the CONTRIBUTING.md document.
  • I have performed a self-review of my own code.
  • I have commented my code, particularly in hard-to-understand areas.
  • I have added tests that prove my fix is effective or that my feature works.
  • New and existing unit tests pass locally with my changes.
  • I have manually tested my changes end-to-end.
  • Any dependent changes have been merged and published in downstream modules.

LangchainTool only took tool.func or tool.coroutine for a StructuredTool. A
plain langchain Tool fell through to Tool._run, whose keyword-only config
parameter became the tool's only required argument, so the model was asked
for config and every call failed. Treat a plain Tool the same way: use func,
then coroutine, fall back to an overridden _run, and reject a Tool that has
none of them.

Fixes google#8035
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.

LangchainTool asks the model for config when it wraps a plain langchain Tool

2 participants