Skip to content

fix(tools): compare a parameter default with the empty sentinel by identity - #7985

Open
DZH166 wants to merge 2 commits into
google:mainfrom
DZH166:fix/mandatory-args-identity-check
Open

DZH166 wants to merge 2 commits into
google:mainfrom
DZH166:fix/mandatory-args-identity-check

Conversation

@DZH166

@DZH166 DZH166 commented Nov 4, 2026

Copy link
Copy Markdown

Problem

FunctionTool._get_mandatory_args() decides whether a parameter has a default with ==:

if param.default == inspect.Parameter.empty:
    mandatory.append(param.name)

== runs the default's own __eq__. A default with elementwise equality - a numpy.ndarray, a pandas.Series, the natural default of a numeric tool parameter - returns a non-boolean:

  • a truthy result marks the optional parameter as mandatory, so run_async() answers every call that omits it with "mandatory input parameters are not present" and the default is never used;
  • an ambiguous result (an array with more than one element) makes _get_mandatory_args() raise ValueError: The truth value of an array with more than one element is ambiguous on every call.

_get_mandatory_args() runs on every FunctionTool.run_async() path. The comment directly above the code already states the test in identity form.

BEFORE  mandatory parameters reported: ValueError: The truth value of an array with more than one element is ambiguous.
        (scalar-eq shape: ['text', 'weights'] -> run_async fails with "mandatory input parameters are not present: weights")
AFTER   mandatory parameters reported: ['text']
        run_async result: {'text': 'hello', 'weights_is_default': True}

Fix

if param.default is inspect.Parameter.empty:

Tests

tests/unittests/tools/test_function_tool.py::test_optional_param_with_elementwise_equality_default_is_optional uses a dependency-free stand-in whose __eq__ returns an object with ambiguous truthiness.

pytest tests/unittests/tools/test_function_tool.py -q   # 121 passed (1 failed with the test only, on the unpatched code)

Related suites (test_function_tool*.py, test_authenticated_function_tool.py, utils/test_callable_utils.py): 232 passed, 1 skipped.

Note: the look-alike param.default != inspect.Parameter.empty in tools/_automatic_function_calling_util.py is intentionally not touched here - that path is the legacy function-declaration builder, while _get_mandatory_args() runs on every tool call.

@google-cla

google-cla Bot commented Nov 4, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@DZH166
DZH166 force-pushed the fix/mandatory-args-identity-check branch from 5bc5bf7 to 2e357f4 Compare November 4, 2026 05:53

@mangeshraut712 mangeshraut712 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The identity check in _get_mandatory_args is the right fix for elementwise-equality defaults.

Same hazard remains in src/google/adk/tools/_automatic_function_calling_util.py (~line 84) when building the pydantic field default: param.default != inspect.Parameter.empty still calls the default's __eq__/__ne__. For an elementwise numpy/pandas-style default that returns a non-bool, that ternary can raise the same ambiguous-truth error during schema generation. Please switch it to is / is not, matching this change and the other identity checks in _function_parameter_parse_util.py.

# when tested for truth or marks an optional parameter as mandatory.
if (
param.default == inspect.Parameter.empty
param.default is inspect.Parameter.empty

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using is here is correct: with a stand-in default whose __eq__ returns a non-bool (as in the new test), == inspect.Parameter.empty raises on truth-testing, while is keeps the parameter optional.

Please apply the same identity check in _automatic_function_calling_util.py where param.default != inspect.Parameter.empty is still used for the pydantic Field default.

…entity

param.default == inspect.Parameter.empty runs the default's __eq__, so a numpy/pandas default made an optional parameter mandatory or raised on ambiguous truth values. Use 'is'.
@DZH166
DZH166 force-pushed the fix/mandatory-args-identity-check branch from 2e357f4 to b454400 Compare November 6, 2026 06:25
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.

3 participants