Skip to content

feat(tools): add preserve_property_names option to OpenAPIToolset#4505

Open
yuvrajangadsingh wants to merge 4 commits intogoogle:mainfrom
yuvrajangadsingh:fix/openapi-preserve-property-names
Open

feat(tools): add preserve_property_names option to OpenAPIToolset#4505
yuvrajangadsingh wants to merge 4 commits intogoogle:mainfrom
yuvrajangadsingh:fix/openapi-preserve-property-names

Conversation

@yuvrajangadsingh
Copy link

@yuvrajangadsingh yuvrajangadsingh commented Feb 16, 2026

Link to Issue or Description of Change

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

Description

ADK's OpenAPIToolset automatically converts all parameter names to snake_case via _to_snake_case(). This is a problem when calling APIs that expect camelCase property names — e.g. an OpenAPI spec with sessionInfo gets converted to session_info, causing the target API to reject the request.

While the internal mapping (original_namepy_name) correctly maps back to the original names for the actual HTTP call, the LLM schema shows the snake_cased names, creating a mismatch with the API documentation and confusing developers.

This PR adds a preserve_property_names parameter to OpenAPIToolset that, when set to True, keeps the original property names from the OpenAPI spec instead of converting them to snake_case. The flag is False by default for full backward compatibility.

Usage:

toolset = OpenAPIToolset(
    spec_str=spec_content,
    spec_str_type="yaml",
    preserve_property_names=True,  # Skip snake_case conversion
)

Changes:

  • openapi_toolset.py — New preserve_property_names parameter, passed to the parser
  • openapi_spec_parser.py — Accepts and forwards the flag to OperationParser
  • operation_parser.py — When flag is True, sets py_name directly from original_name (only applying Python keyword renaming), skipping _to_snake_case()

Testing Plan

Unit Tests:

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

Added 3 new tests:

  • test_openapi_toolset_preserve_property_names — verifies camelCase params are preserved when flag is True
  • test_openapi_toolset_default_snake_case_conversion — verifies default behavior still converts to snake_case
  • test_openapi_toolset_preserve_property_names_body_params — verifies request body properties (firstName, lastName, emailAddress) are preserved
$ pytest tests/unittests/tools/openapi_tool/ -v
...
210 passed, 17 warnings in 9.62s

All 210 tests pass (14 in the toolset file, 3 of which are new).

Manual End-to-End (E2E) Tests:

Not applicable — this is a parsing/schema generation change that doesn't affect the web UI or runner. The unit tests cover the full flow from OpenAPI spec parsing through to JSON schema generation, which is the complete surface area of this change.

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.

Additional context

The fix is intentionally minimal — 3 source files modified, 1 test file updated, all backward compatible. The ApiParameter class itself needed no changes since its model_post_init already skips snake_case inference when py_name is pre-set.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @yuvrajangadsingh, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request enhances the OpenAPIToolset by providing a new configuration option, preserve_property_names. This option allows developers to prevent the automatic conversion of OpenAPI property names to snake_case, which is crucial for interacting with APIs that expect different casing conventions like camelCase. This change improves the flexibility and compatibility of the toolset, ensuring that the generated schema accurately reflects the target API's expectations and reduces confusion for developers.

Highlights

  • New Configuration Option: Introduced a preserve_property_names option to the OpenAPIToolset constructor, allowing control over parameter name conversion.
  • Flexible Naming Conventions: Enabled skipping the automatic snake_case conversion for OpenAPI property names when preserve_property_names is set to True, facilitating integration with APIs expecting camelCase or other conventions.
  • Backward Compatibility: Ensured backward compatibility by setting the preserve_property_names flag to False by default, maintaining existing behavior.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • src/google/adk/tools/openapi_tool/openapi_spec_parser/openapi_spec_parser.py
    • Added an __init__ method to accept a preserve_property_names boolean flag.
    • Modified the parse method to pass the _preserve_property_names instance variable to the OperationParser constructor.
  • src/google/adk/tools/openapi_tool/openapi_spec_parser/openapi_toolset.py
    • Added preserve_property_names as a new boolean parameter to the __init__ method, defaulting to False.
    • Stored the preserve_property_names value as an instance variable _preserve_property_names.
    • Modified the _parse method to instantiate OpenApiSpecParser with the new _preserve_property_names flag.
  • src/google/adk/tools/openapi_tool/openapi_spec_parser/operation_parser.py
    • Imported the rename_python_keywords utility function.
    • Added preserve_property_names as a new boolean parameter to the __init__ method.
    • Conditionally set the py_name for ApiParameter objects in _process_operation_parameters and _process_request_body based on the _preserve_property_names flag, applying rename_python_keywords when preserving names.
  • tests/unittests/tools/openapi_tool/openapi_spec_parser/test_openapi_toolset.py
    • Added test_openapi_toolset_preserve_property_names to verify that camelCase names are preserved when the flag is True.
    • Added test_openapi_toolset_default_snake_case_conversion to confirm that the default behavior still converts names to snake_case.
    • Added test_openapi_toolset_preserve_property_names_body_params to test the preservation of request body properties.
Activity
  • Linked to issue OpenAPIToolset automatically converts camelCase to snake_case with no option to disable #4166, addressing the problem of snake_case conversion for API parameter names.
  • Added three new unit tests to thoroughly cover the new preserve_property_names functionality, including default behavior and request body parameters.
  • Verified that all 210 unit tests pass locally after the changes.
  • Confirmed that manual end-to-end tests are not applicable, as the changes are focused on parsing and schema generation.
  • Completed the contribution checklist, including self-review, commenting code, and ensuring all necessary steps for a quality pull request were followed.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@adk-bot adk-bot added the tools [Component] This issue is related to tools label Feb 16, 2026
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a preserve_property_names option to the OpenAPIToolset, allowing developers to prevent the automatic conversion of API parameter names to snake_case. This is a valuable feature for interacting with APIs that expect camelCase or other naming conventions. The implementation is clean, backward-compatible, and well-tested. I have one suggestion to refactor a small piece of duplicated logic to improve long-term maintainability, but overall this is a great addition.

Address review feedback by extracting the duplicated py_name
determination logic into a single _get_py_name() method.
@yuvrajangadsingh
Copy link
Author

@gemini-code-assist review

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a preserve_property_names option to the OpenAPIToolset, allowing developers to prevent the automatic conversion of API parameter names to snake_case. This is a valuable feature for interacting with APIs that expect camelCase or other naming conventions. The implementation is clean, passing the new flag down through the parser classes and conditionally applying the name transformation. The changes are well-tested with new unit tests covering various scenarios. I have one suggestion to improve the signature of the OperationParser's __init__ method for better clarity and consistency.

@yuvrajangadsingh
Copy link
Author

All review feedback has been addressed:

  • Extracted duplicated py_name logic into _get_py_name() helper (039c4a3)
  • Added type hint to should_parse, made preserve_property_names keyword-only with * (3d0712e)

@gemini-code-assist review

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a preserve_property_names option to OpenAPIToolset, which is a valuable feature for interacting with APIs that don't use snake_case for property names. The implementation is clean and minimally invasive, cleverly reusing existing logic in ApiParameter to handle the conditional snake-casing. The changes are well-tested, covering both the new functionality and ensuring backward compatibility.

I have one suggestion regarding the propagation of the preserve_property_names flag to improve long-term robustness, but overall this is a solid contribution.

@yuvrajangadsingh
Copy link
Author

All three review suggestions have been addressed:

  1. Extracted duplicated py_name logic into _get_py_name() helper (039c4a3)
  2. Added type hint to should_parse, made preserve_property_names keyword-only (3d0712e)
  3. Propagated preserve_property_names through full chain: OperationParser.load() -> RestApiTool.from_parsed_operation() -> OpenAPIToolset._parse() (e952af5)

All 210 tests pass. Ready for review.

@gemini-code-assist review

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This is a great addition that provides more flexibility when working with APIs that don't use snake_case for property names. The implementation is clean and backward-compatible, and the new tests provide good coverage. I have one suggestion in operation_parser.py to improve code clarity by centralizing the logic for parameter name generation. Overall, this is a well-executed feature.

@yuvrajangadsingh
Copy link
Author

@gemini-code-assist review

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a valuable preserve_property_names option to the OpenAPIToolset, allowing for better integration with APIs that use naming conventions other than snake_case. The implementation is clean, and the new functionality is well-covered by unit tests. I've identified a minor area for simplification where the new flag is passed down further than necessary, leading to some redundant code. My suggestions aim to remove this redundancy and improve maintainability. Overall, this is a solid contribution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

tools [Component] This issue is related to tools

Projects

None yet

Development

Successfully merging this pull request may close these issues.

OpenAPIToolset automatically converts camelCase to snake_case with no option to disable

2 participants