Skip to content

MALFORMED_FUNCTION_CALL when using OpenAPIToolSet #1192

Open
@quad2524

Description

@quad2524

I have an LLMAgent using the openAPIToolset to interface with a Rundeck server via its API.

When asking to run functions, most of the time it just prints [user] prompt again in CLI, or in adk web it doesn't return anything at all after showing the "thinking" dots that then disappear. It logs a MALFORMED_FUNCTION_CALL finish_reason.

Sometimes (5% of the time I would say) it will actually work, but mostly it is failing, and providing no output at all other than the trace logs.

Example of error from logs below - Note I have pruned down the Rundeck OpenAPI spec file to only provide limited function set to try and troubleshoot this, otherwise the function list would be big and not relevant. I have tried many different functions and simple tasks and it can happen on any of them:

{"parts":[{"text":"get status of execution id 1234"}],"role":"user"}
-----------------------------------------------------------
Functions:
api_execution: {'id': {'description': 'Execution ID', 'type': <Type.STRING: 'STRING'>}} -> None
api_jobs_listv2: {'project': {'description': 'Project Name', 'type': <Type.STRING: 'STRING'>}, ... (trunc) 

-----------------------------------------------------------

2025-06-05 16:39:09,252 - INFO - models.py:7447 - AFC is enabled with max remote calls: 10.
2025-06-05 16:39:13,076 - INFO - _client.py:1740 - HTTP Request: POST https://us-central1-aiplatform.googleapis.com/v1beta1/projects/XXXXXXX/locations/us-central1/publishers/google/models/gemini-2.5-pro-preview-05-06:generateContent "HTTP/1.1 200 OK"
2025-06-05 16:39:13,077 - INFO - google_llm.py:151 - 
LLM Response:
-----------------------------------------------------------
Text:
None
-----------------------------------------------------------
Function calls:

-----------------------------------------------------------
Raw response:
{"candidates":[{"content":{},"finish_message":"Malformed function call: print(default_api.api_jobs_listv2(_auth_prefix_vaf_X-Rundeck-Auth-Token = \"XXXXXXXXX\", project=\"My_Project\"))\nprint(default_api.api_execution(_auth_prefix_vaf_X-Rundeck-Auth-Token = \"XXXXXXXX\", id=\"1234\"))","finish_reason":"MALFORMED_FUNCTION_CALL"}],"create_time":"2025-06-05T16:39:09.903350Z","response_id":"ZZZZZZ","model_version":"gemini-2.5-pro-preview-05-06","usage_metadata":{"prompt_token_count":1737,"prompt_tokens_details":[{"modality":"TEXT","token_count":1737}],"total_token_count":1737,"traffic_type":"ON_DEMAND"},"automatic_function_calling_history":[]}
-----------------------------------------------------------

2025-06-05 16:39:13,077 - INFO - fast_api.py:705 - Generated event in agent run streaming: {"errorCode":"MALFORMED_FUNCTION_CALL","errorMessage":"Malformed function call: print(default_api.api_jobs_listv2(_auth_prefix_vaf_X-Rundeck-Auth-Token = \"XXXXXXXX\", project=\"My_Project\"))\nprint(default_api.api_execution(_auth_prefix_vaf_X-Rundeck-Auth-Token = \"XXXXXXXX\", id=\"1234\"))","usageMetadata":{"promptTokenCount":1737,"promptTokensDetails":[{"modality":"TEXT","tokenCount":1737}],"totalTokenCount":1737,"trafficType":"ON_DEMAND"},"invocationId":"YYYY","author":"rundeck_agent","actions":{"stateDelta":{},"artifactDelta":{},"requestedAuthConfigs":{}},"id":"ZZZZZ","timestamp":1749141549.24444}

Expected behavior:
When it actually works in the log I do see the function call with all the args. When it fails it does not
{"parts":[{"text":"get status of job 1234"}],"role":"user"}
{"parts":[{"function_call":{"args":{ ...
{"parts":[{"function_response":{"name": ...

The agent.py code:

# Read from API_FILE location
openapi_spec_string = open(f"{API_FILE}", "r").read()
auth_scheme, auth_credential = token_to_scheme_credential(
    "apikey", "header", "X-Rundeck-Auth-Token", f"{RUNDECK_API_TOKEN}"
)

# --- Create OpenAPIToolset ---
rundeck_toolset = OpenAPIToolset(
    spec_str=openapi_spec_string,
    spec_str_type='yaml',
    auth_scheme=auth_scheme,
    auth_credential=auth_credential    
)

# --- Agent Definition ---
root_agent = LlmAgent(
    name=AGENT_NAME_OPENAPI,
    model=GEMINI_MODEL,
    tools=[rundeck_toolset], 
    instruction="""
    You are an assistant that can execute and retrieve information about jobs from Rundeck.
    Only use the tools provided to interact with Rundeck. 
""",
    description="Manage Rundeck Jobs using tools generated from an OpenAPI spec.",
)

To reproduce you would need a rundeck server...

  • OS: [e.g. iOS] RHEL8
  • Python version(python -V): 3.12.8
  • ADK version(pip show google-adk): 1.1.1

Additional context
I have tried this on Flash 2.0, Flash 2.5, and Pro 2.5 with same result.
I added a before_tool_callback to log args to see if that would help, but when this occurrs, it doesn't reach that part before the MALFORMED_FUNCTION_CALL and no response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions