Describe the bug
OpenAPIToolset and APIHubToolset only allow each tool to have a single security schema.
For example:
If your endpoint(tool) required multiple security, then OpenAPIToolset and APIHubToolset will only choose the first one become its auth_scheme [1]
[1] https://github.com/google/adk-python/blob/main/src/google/adk/tools/openapi_tool/openapi_spec_parser/openapi_spec_parser.py#L129-L136
To Reproduce
Steps to reproduce the behavior:
- Create python environment
uv venv --python 3.12.0
source .venv/bin/activate
uv pip install google-adk==1.8.0
- Use this openapi.json
{
"openapi": "3.1.0",
"info": {
"title": "FastAPI",
"version": "0.1.0"
},
"servers": [
{
"url": "http://localhost:8080"
}
],
"paths": {
"/helloworld": {
"get": {
"summary": "Helloworld",
"operationId": "helloworld_helloworld_get",
"responses": {
"200": {
"description": "Successful Response",
"content": {
"application/json": {
"schema": {
}
}
}
}
},
"security": [
{
"api1": []
},
{
"api2": []
}
]
}
}
},
"components": {
"securitySchemes": {
"api1": {
"type": "apiKey",
"in": "header",
"name": "x-api-key-1"
},
"api2": {
"type": "apiKey",
"in": "header",
"name": "x-api-key-2"
}
}
}
}- use test_tool.py to testing.
importosimportjsonfromgoogle.authimportdefaultfromgoogle.auth.transport.requestsimportRequestfromgoogle.cloudimportsecretmanagerfromgoogle.adk.tools.apihub_tool.apihub_toolsetimportAPIHubToolsetfromgoogle.adk.agents.llm_agentimportLlmAgentfromgoogle.adk.auth.auth_credentialimportAuthCredential, AuthCredentialTypes, HttpAuth, HttpCredentialsfromgoogle.adk.tools.openapi_tool.auth.auth_helpersimporttoken_to_scheme_credentialfromgoogle.adk.tools.openapi_tool.openapi_spec_parser.openapi_toolsetimportOpenAPIToolsetimportasyncioOPENAPI_SPEC_FILENAME="hello_world_openapi.json"TOKEN="secret-key-1"withopen(os.path.join(os.path.dirname(__file__), OPENAPI_SPEC_FILENAME), 'r') asf:
spec_content=f.read()
auth_scheme, auth_credential=token_to_scheme_credential(
"apikey", "header", "x-api-key-1", TOKEN
)
smorch_toolset=OpenAPIToolset(
spec_str=spec_content,
spec_str_type='json',
auth_scheme=auth_scheme,
auth_credential=auth_credential
)
asyncdefmain():
tools=awaitsmorch_toolset.get_tools()
fortoolintools:
print(tool.auth_scheme)
asyncio.run(main())
- tool only have one auth_scheme (x-api-key-1), x-api-key-2 is missing....
(adk_with_different_auth) user@abehsu-us-vscode:~/abehsu/fastapi_with_multiple_security$ python /home/user/abehsu/adk_with_different_auth/api_key/openapi/test_tool.py
type_=<SecuritySchemeType.apiKey: 'apiKey'> description=None in_=<APIKeyIn.header: 'header'> name='x-api-key-1'
- The other way you can test it is using this agent.py
importosfromgoogle.adk.agents.llm_agentimportLlmAgentfromgoogle.adk.tools.openapi_tool.auth.auth_helpersimporttoken_to_scheme_credentialfromgoogle.adk.tools.openapi_tool.openapi_spec_parser.openapi_toolsetimportOpenAPIToolsetOPENAPI_SPEC_FILENAME="hello_world_openapi.json"TOKEN="secret-key-1"withopen(os.path.join(os.path.dirname(__file__), OPENAPI_SPEC_FILENAME), 'r') asf:
spec_content=f.read()
auth_scheme, auth_credential=token_to_scheme_credential(
"apikey", "header", "x-api-key-1", TOKEN
)
hello_world_toolset=OpenAPIToolset(
spec_str=spec_content,
spec_str_type='json',
auth_scheme=auth_scheme,
auth_credential=auth_credential
)
# --- Agent Configuration ---# Configure and create the main LLM Agent.root_agent=LlmAgent(
model='gemini-2.0-flash',
name='hello_world_agent',
instruction='when user say hi you will use hello world tool to response them',
tools=[hello_world_toolset],
)
Backend server example code:
fromfastapiimportFastAPI, Depends, HTTPException, statusfromfastapi.securityimportAPIKeyHeaderapi_key_header_1=APIKeyHeader(name="x-api-key-1", auto_error=False, scheme_name="api1")
api_key_header_2=APIKeyHeader(name="x-api-key-2", auto_error=False, scheme_name="api2")
SECRET_KEY_1="secret-key-1"SECRET_KEY_2="secret-key-2"asyncdefget_api_keys_1(
key1: str=Depends(api_key_header_1),
key2: str=Depends(api_key_header_2),
):
ifnotkey1orkey1!=SECRET_KEY_1:
raiseHTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid or missing API Key 1",
)
ifnotkey2orkey2!=SECRET_KEY_2:
raiseHTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid or missing API Key 2",
)
returnkey1, key2app=FastAPI()
@app.get("/helloworld", dependencies=[Depends(get_api_keys_1)])asyncdefhelloworld():
return {"message": "Hello World"}Screenshots

Desktop (please complete the following information):
- OS: Linux
- Python version(python -V): Python 3.12.10
- ADK version(pip show google-adk): 1.18.0
Describe the bug
OpenAPIToolset and APIHubToolset only allow each tool to have a single security schema.
For example:
If your endpoint(tool) required multiple security, then OpenAPIToolset and APIHubToolset will only choose the first one become its auth_scheme [1]
[1] https://github.com/google/adk-python/blob/main/src/google/adk/tools/openapi_tool/openapi_spec_parser/openapi_spec_parser.py#L129-L136
To Reproduce
Steps to reproduce the behavior:
uv venv --python 3.12.0 source .venv/bin/activate uv pip install google-adk==1.8.0{ "openapi": "3.1.0", "info": { "title": "FastAPI", "version": "0.1.0" }, "servers": [ { "url": "http://localhost:8080" } ], "paths": { "/helloworld": { "get": { "summary": "Helloworld", "operationId": "helloworld_helloworld_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { } } } } }, "security": [ { "api1": [] }, { "api2": [] } ] } } }, "components": { "securitySchemes": { "api1": { "type": "apiKey", "in": "header", "name": "x-api-key-1" }, "api2": { "type": "apiKey", "in": "header", "name": "x-api-key-2" } } } }Backend server example code:
Screenshots
Desktop (please complete the following information):