Description
When a user sends a new message while a tool call is still pending (or the tool errors without ADK emitting a function_response), the persisted session contains a tool_use event with no matching tool_result. Claude's API requires every tool_use to have a corresponding tool_result — without one, every subsequent turn returns a 400 error and the session is permanently broken.
Difference from existing fixes
This is distinct from the fixes in #3504 and #4027, which address orphaned function_response blocks during context truncation. This issue is about orphaned function_call blocks caused by user interruption — a different problem that ADK does not currently handle.
Current workaround
We use a before_model_callback that scans llm_request.contents and injects synthetic function_response stubs for any unmatched function_call blocks, preserving the rest of the conversation context.
Expected behavior
ADK should handle orphaned function_call blocks (from interruption or tool errors) gracefully, either by injecting synthetic responses or by stripping the orphaned calls before sending to the model API.
Description
When a user sends a new message while a tool call is still pending (or the tool errors without ADK emitting a
function_response), the persisted session contains atool_useevent with no matchingtool_result. Claude's API requires everytool_useto have a correspondingtool_result— without one, every subsequent turn returns a 400 error and the session is permanently broken.Difference from existing fixes
This is distinct from the fixes in #3504 and #4027, which address orphaned
function_responseblocks during context truncation. This issue is about orphanedfunction_callblocks caused by user interruption — a different problem that ADK does not currently handle.Current workaround
We use a
before_model_callbackthat scansllm_request.contentsand injects syntheticfunction_responsestubs for any unmatchedfunction_callblocks, preserving the rest of the conversation context.Expected behavior
ADK should handle orphaned
function_callblocks (from interruption or tool errors) gracefully, either by injecting synthetic responses or by stripping the orphaned calls before sending to the model API.