🔴 Required Information
Describe the Bug:
Across several critical subsystems in the framework, there is a hardcoded assumption that the function_response always resides at index 0 of the event parts array (event.content.parts[0]). When an agent handles parallel tool calls, the model returns multiple function responses within a single turn, making the index dynamic. This hardcoded parts[0] assumption causes the framework to silently ignore, drop, or mismatch tool responses when they appear at indices other than 0.
This systemic flaw breaks telemetry tracing (spans are dropped or mismatched), causes load_artifacts to infinite loop (as seen in #5967), breaks MCP resource loading, and crashes CLI conformance tests.
Steps to Reproduce:
- Configure an agent with multiple tools (e.g., a custom tool and
load_artifacts_tool).
- Prompt the agent in a way that triggers multiple tools to execute simultaneously in parallel.
- Observe that telemetry is only recorded for the first tool, and/or
load_artifacts fails to execute because its response is located at parts[1].
Expected Behavior:
The framework should correctly iterate through event.content.parts to locate the function_response that matches the executing tool's name, allowing parallel tools to resolve correctly regardless of their position in the array.
Observed Behavior:
The framework blindly targets parts[0]. This causes subsequent tools in the parallel execution array (like load_artifacts at parts[1]) to be ignored or treated as text, leading to infinite retry loops, dropped telemetry traces, and ValueError crashes in the CLI testing framework.
Environment Details:
- ADK Library Version: N/A (Source code level bug in
main)
- Desktop OS: N/A (Framework level)
- Python Version: N/A
Model Information:
- Are you using LiteLLM: Yes/No
- Which model is being used: Any model supporting parallel function calling (e.g., gemini-1.5-pro, gemini-2.5-pro)
🟡 Optional Information
Regression:
N/A. This appears to be an architectural assumption present since parallel tools were supported.
Logs:
N/A
Screenshots / Video:
N/A
Additional Context:
To ensure this was a genuine framework bug and not an anomaly, we performed multiple rounds of rigorous verification:
- Mocking Failure: We initially tried to test this using
ToolContext mocks, which hit JSON serialization TypeErrors, forcing us to look deeper into the actual object payloads.
- Custom Test Script: We built a dedicated script that programmatically constructed
types.Content objects containing parallel types.Part elements. We fed this into the load_artifacts_tool logic and conclusively proved that the tool drops any function response that does not sit exactly at index 0.
- Full Test Suite Run: After fixing the source code locally, we ran the full
pytest suite and immediately caught existing tests in test_spans.py failing. These tests were actually written around the bug (assuming index 0 was correct) and broke once the framework began properly mapping responses by name!
Minimal Reproduction Code:
This is the core issue present in tracing.py, load_artifacts_tool.py, load_mcp_resource_tool.py, and others:
# BROKEN LOGIC:
function_response = function_response_event.content.parts[0].function_response
# CORRECT LOGIC:
function_response = None
for part in function_response_event.content.parts:
if part.function_response and part.function_response.name == tool.name:
function_response = part.function_response
break
(Note: I have a branch prepared with a comprehensive fix across all of the affected files, including updated unit tests in test_spans.py, and I will be opening a Pull Request to address this shortly).
How often has this issue occurred?:
- Always (100%) when parallel tools are invoked and the target tool is not at index 0.
🔴 Required Information
Describe the Bug:
Across several critical subsystems in the framework, there is a hardcoded assumption that the
function_responsealways resides at index0of the event parts array (event.content.parts[0]). When an agent handles parallel tool calls, the model returns multiple function responses within a single turn, making the index dynamic. This hardcodedparts[0]assumption causes the framework to silently ignore, drop, or mismatch tool responses when they appear at indices other than0.This systemic flaw breaks telemetry tracing (spans are dropped or mismatched), causes
load_artifactsto infinite loop (as seen in #5967), breaks MCP resource loading, and crashes CLI conformance tests.Steps to Reproduce:
load_artifacts_tool).load_artifactsfails to execute because its response is located atparts[1].Expected Behavior:
The framework should correctly iterate through
event.content.partsto locate thefunction_responsethat matches the executing tool's name, allowing parallel tools to resolve correctly regardless of their position in the array.Observed Behavior:
The framework blindly targets
parts[0]. This causes subsequent tools in the parallel execution array (likeload_artifactsatparts[1]) to be ignored or treated as text, leading to infinite retry loops, dropped telemetry traces, andValueErrorcrashes in the CLI testing framework.Environment Details:
main)Model Information:
🟡 Optional Information
Regression:
N/A. This appears to be an architectural assumption present since parallel tools were supported.
Logs:
N/A
Screenshots / Video:
N/A
Additional Context:
To ensure this was a genuine framework bug and not an anomaly, we performed multiple rounds of rigorous verification:
ToolContextmocks, which hit JSON serializationTypeErrors, forcing us to look deeper into the actual object payloads.types.Contentobjects containing paralleltypes.Partelements. We fed this into theload_artifacts_toollogic and conclusively proved that the tool drops any function response that does not sit exactly at index0.pytestsuite and immediately caught existing tests intest_spans.pyfailing. These tests were actually written around the bug (assuming index 0 was correct) and broke once the framework began properly mapping responses by name!Minimal Reproduction Code:
This is the core issue present in
tracing.py,load_artifacts_tool.py,load_mcp_resource_tool.py, and others:(Note: I have a branch prepared with a comprehensive fix across all of the affected files, including updated unit tests in
test_spans.py, and I will be opening a Pull Request to address this shortly).How often has this issue occurred?: