Description
Gemini’s ~64-char function name limit is handled by a hard slice to 60 characters with no uniqueness suffix:
google/adk/tools/openapi_tool/openapi_spec_parser/operation_parser.py — get_function_name ([:60])
google/adk/tools/openapi_tool/openapi_spec_parser/rest_api_tool.py — RestApiTool.__init__ (name[:60])
Codegen-style OpenAPI specs routinely produce long operationIds that share a long snake_case prefix. Distinct operations collapse to one tool name. LlmRequest.append_tools still sends two FunctionDeclarations with that name to the model, but tools_dict keeps only the last registration (warning logged; calls always hit the survivor).
Environment
google-adk==2.9.2
- Offline unit repro
Repro
Minimal OpenAPI with two long operationIds that share a 60-char snake_case prefix after conversion, e.g.:
listAllCompanyOrganizationDepartmentUsersByFilterCriteriaV1 → /users/v1
listAllCompanyOrganizationDepartmentUsersByFilterCriteriaV2 → /users/v2
Build OpenAPIToolset / register tools into an LlmRequest and inspect names + tools_dict.
Observed (google-adk==2.9.2)
- Both tools named
list_all_company_organization_department_users_by_filter_cri (len 60)
- Warning: duplicate tool name … previously registered tool is shadowed
tools_dict has 1 key; survivor path = /users/v2; first endpoint unreachable
- Declarations list still contains two entries with the same name
Expected
After truncation, colliding names should get a short stable disambiguator so each operationId maps to a unique callable tool, and tools_dict / declarations stay 1:1.
Suggested fix
After [:60], if the name collides with an already-emitted tool in the toolset, append a short stable disambiguator (e.g. _2, hash of full operationId, or path+method suffix).
Notes
#60 is an unrelated tools_dict miss for agent-as-tool naming. Happy to open a PR.
Description
Gemini’s ~64-char function name limit is handled by a hard slice to 60 characters with no uniqueness suffix:
google/adk/tools/openapi_tool/openapi_spec_parser/operation_parser.py—get_function_name([:60])google/adk/tools/openapi_tool/openapi_spec_parser/rest_api_tool.py—RestApiTool.__init__(name[:60])Codegen-style OpenAPI specs routinely produce long
operationIds that share a long snake_case prefix. Distinct operations collapse to one tool name.LlmRequest.append_toolsstill sends twoFunctionDeclarations with that name to the model, buttools_dictkeeps only the last registration (warning logged; calls always hit the survivor).Environment
google-adk==2.9.2Repro
Minimal OpenAPI with two long
operationIds that share a 60-char snake_case prefix after conversion, e.g.:listAllCompanyOrganizationDepartmentUsersByFilterCriteriaV1→/users/v1listAllCompanyOrganizationDepartmentUsersByFilterCriteriaV2→/users/v2Build
OpenAPIToolset/ register tools into anLlmRequestand inspect names +tools_dict.Observed (
google-adk==2.9.2)list_all_company_organization_department_users_by_filter_cri(len 60)tools_dicthas 1 key; survivor path =/users/v2; first endpoint unreachableExpected
After truncation, colliding names should get a short stable disambiguator so each
operationIdmaps to a unique callable tool, andtools_dict/ declarations stay 1:1.Suggested fix
After
[:60], if the name collides with an already-emitted tool in the toolset, append a short stable disambiguator (e.g._2, hash of fulloperationId, or path+method suffix).Notes
#60 is an unrelated
tools_dictmiss for agent-as-tool naming. Happy to open a PR.