Skip to content

fix(tools): stringify Enum values in legacy schema declarations - #6981

Open
chelsealong wants to merge 1 commit into
google:mainfrom
chelsealong:fix-6978-intenum-string-values
Open

fix(tools): stringify Enum values in legacy schema declarations#6981
chelsealong wants to merge 1 commit into
google:mainfrom
chelsealong:fix-6978-intenum-string-values

Conversation

@chelsealong

Copy link
Copy Markdown
Contributor

Link to Issue or Description of Change

Link to an existing issue:

Problem:

When a tool function has a parameter annotated with an enum.IntEnum (or
any Enum whose member .values are not strings), the legacy
_parse_schema_from_parameter builds a declaration with type: STRING but
copies the raw e.value into schema.enum, e.g. [1, 2]. That is invalid
by types.Schema's own contract — Schema.enum is list[str] — so:

  • Building the same schema through the public constructor
    (types.Schema(type='STRING', enum=[1, 2])) raises a ValidationError.
  • Serializing the ADK-built schema emits
    PydanticSerializationUnexpectedValue warnings, because the assignment
    happens via schema.enum = [...] after construction, bypassing
    validation.

Solution:

Stringify enum values (str(e.value)) when building the STRING schema,
and stringify the default the same way before comparing/assigning it. This
keeps the declaration internally consistent with the STRING type it
already declares. str-valued enums are unaffected, since str(value) == value for them (confirmed by the existing test_enums test, which still
passes unchanged).

The call-path question the issue raised (how a string-vs-name enum value
maps back onto the Python Enum when the model calls the tool) is a
separate, already-preexisting gap — there is no enum re-hydration in
FunctionTool._preprocess_args today for str enums either — and is out
of scope for this fix, which only makes the generated declaration valid.

Testing Plan

Unit Tests:

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

Added TestBuildFunctionDeclarationLegacy.test_int_enum in
tests/unittests/tools/test_build_function_declaration.py, which builds a
declaration for an IntEnum-typed parameter and asserts:

  • schema.type == 'STRING'
  • schema.enum == ['1', '2'] (strings, not ints)
  • schema.default == '1'
  • the resulting (type, enum) pair round-trips through types.Schema(...)
    without raising.

Verified the test fails without the fix:

$ git stash push -- src/google/adk/tools/_function_parameter_parse_util.py
$ python -m pytest tests/unittests/tools/test_build_function_declaration.py -k test_int_enum -q
...
E     assert level_schema.enum == ['1', '2']
E     AssertionError: assert [1, 2] == ['1', '2']
1 failed, 57 deselected in 0.72s
$ git stash pop

And passes with the fix:

$ python -m pytest tests/unittests/tools/test_build_function_declaration.py -k "test_int_enum or test_enums or test_enum_parameter" -q
3 passed, 55 deselected in 1.33s

Full tests/unittests/tools/ directory (2119 tests):

$ python -m pytest tests/unittests/tools/ -q
2119 passed, 1 skipped, 762 warnings in 46.53s

Manual End-to-End (E2E) Tests:

Reproduced the exact repro from the issue (from_function_with_options on
a function with an IntEnum-typed parameter, promoting the pydantic
serializer UserWarning to an error). Before the fix:

UserWarning: Pydantic serializer warnings:
  PydanticSerializationUnexpectedValue(Expected `str` - serialized value may not be as expected [field_name='enum', input_value=1, input_type=int])
  PydanticSerializationUnexpectedValue(Expected `str` - serialized value may not be as expected [field_name='enum', input_value=2, input_type=int])

After the fix, decl.parameters.properties['level'].model_dump(...) returns
{'enum': ['1', '2'], 'type': 'STRING'} with no warnings.

Checklist

  • I have read the CONTRIBUTING.md document.
  • I have performed a self-review of my own code.
  • 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.

Additional context

Reported with AI assistance (this PR was authored by an AI coding agent);
the fix was implemented, tested, and reviewed following the reproduction
steps and root cause in the issue report.

`_parse_schema_from_parameter` declared enum parameters as
`type: STRING` but copied `e.value` verbatim into `schema.enum`, so an
`IntEnum` (or any enum with non-string values) produced an int list
under a STRING schema. That's invalid by `types.Schema`'s own
contract: constructing the same schema through the public constructor
raises `ValidationError`, and serializing the ADK-built one emits
`PydanticSerializationUnexpectedValue` warnings.

Stringify enum values (and the default, if any) so the declaration
matches the STRING type it declares. `str`-valued enums are
unaffected since `str(value) == value` for them.
@chelsealong
chelsealong force-pushed the fix-6978-intenum-string-values branch from 33c3853 to db4f73f Compare September 3, 2026 00:33
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.

IntEnum tool parameters produce an invalid function declaration: integer values in a STRING enum

2 participants