Skip to content

fix(tools): coerce integral floats inside list[int] tool parameters too - #6972

Open
nileshpatil6 wants to merge 2 commits into
google:mainfrom
nileshpatil6:fix/coerce-list-int-tool-args
Open

fix(tools): coerce integral floats inside list[int] tool parameters too#6972
nileshpatil6 wants to merge 2 commits into
google:mainfrom
nileshpatil6:fix/coerce-list-int-tool-args

Conversation

@nileshpatil6

Copy link
Copy Markdown
Contributor

Link to Issue or Description of Change

2. Or, if no issue exists, describe the change:

Problem:

Some session stores persist call args as a proto Struct, whose only number type is double, so an int comes back as a float on replay. #6885 fixed that for scalar int parameters in FunctionTool._preprocess_args.

The same round trip converts list elements too, and those are still passed through untouched. A tool declared as:

async def get_components(component_ids: list[int]): ...

receives [1396683.0, 7.0] instead of [1396683, 7] after a session replay. Anything downstream that indexes, formats, or sends those ids to a typed API then sees floats, so the failure surfaces far from its cause.

Solution:

Apply the same coercion to list[int] parameters, element by element, right after the scalar int branch it mirrors. Non integral floats are left alone with the same warning the scalar path emits, so no value is silently rounded. Optional[list[int]] is covered because the existing Union handling unwraps the annotation before this point.

Other element types are untouched: only list[int] is coerced, and a list[float] or list[str] parameter passes through unchanged.

Testing Plan

Unit Tests:

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

Five tests added to tests/unittests/tools/test_function_tool.py: coercion for list[int] and Optional[list[int]], plus negative guards asserting list[float], list[str] and non integral values are not altered.

The two coercion tests fail on main and pass with this change.

tests/unittests/tools/test_function_tool.py ... 43 passed
tests/unittests/tools/test_authenticated_function_tool.py,
tests/unittests/tools/test_agent_tool.py,
tests/unittests/tools/test_build_function_declaration.py ... 132 passed

Manual End-to-End (E2E) Tests:

Not required. The defect is entirely in argument preprocessing and is reproduced directly by the unit tests: passing {"component_ids": [1396683.0, 7.0]} to a tool typed list[int] and asserting the callable receives Python ints.

@nileshpatil6
nileshpatil6 force-pushed the fix/coerce-list-int-tool-args branch from 82bd438 to 109f575 Compare September 5, 2026 19:09
@nileshpatil6

Copy link
Copy Markdown
Contributor Author

Rebased onto main after the argument-preprocessing refactor.

FunctionTool._preprocess_args now delegates to _schema_utils.preprocess_args, so I dropped my old inline change and re-applied the fix there instead, directly after the scalar int branch it mirrors. The bug survived the refactor: _schema_utils.py coerces a float back to int for an int parameter but still leaves the elements of a list[int] as floats.

The tests were unchanged and still exercise it through FunctionTool.run_async. On current main they fail:

FAILED test_run_async_coerces_integral_floats_in_list_int_param
FAILED test_run_async_coerces_integral_floats_in_optional_list_int_param
2 failed, 41 passed

and with the change the module is green at 43 passed.

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.

2 participants