diff --git a/src/google/adk/models/lite_llm.py b/src/google/adk/models/lite_llm.py index 3a6c36624d8..88488bbd0d5 100644 --- a/src/google/adk/models/lite_llm.py +++ b/src/google/adk/models/lite_llm.py @@ -1716,7 +1716,13 @@ def _message_to_generate_content_response( name=tool_call.function.name, args=json.loads(tool_call.function.arguments or "{}"), ) - part.function_call.id = tool_call.id + # The signature is carried on the part, so strip it back out of the id. + # Leaving it there leaks base64 into anything keyed by function_call_id — + # artifact filenames, logs, UI — and `_content_to_message_param` re-attaches + # it to the outgoing tool call from `thought_signature` anyway. + part.function_call.id = tool_call.id.split( + _THOUGHT_SIGNATURE_SEPARATOR, 1 + )[0] if thought_signature: part.thought_signature = thought_signature parts.append(part) diff --git a/tests/unittests/models/test_litellm.py b/tests/unittests/models/test_litellm.py index 9007bcf2015..6260969020e 100644 --- a/tests/unittests/models/test_litellm.py +++ b/tests/unittests/models/test_litellm.py @@ -2560,6 +2560,30 @@ def test_message_to_generate_content_response_preserves_thought_signature(): assert fc_part.thought_signature == b"round_trip_sig" +def test_message_to_generate_content_response_strips_signature_from_id(): + """An id carrying an embedded signature is split before it reaches the part.""" + sig_b64 = base64.b64encode(b"embedded_sig").decode("utf-8") + message = ChatCompletionAssistantMessage( + role="assistant", + content=None, + tool_calls=[ + ChatCompletionMessageToolCall( + type="function", + id=f"call_ts_2{_THOUGHT_SIGNATURE_SEPARATOR}{sig_b64}", + function=Function( + name="load_skill", + arguments='{"skill": "my_skill"}', + ), + ) + ], + ) + + response = _message_to_generate_content_response(message) + fc_part = response.content.parts[0] + assert fc_part.function_call.id == "call_ts_2" + assert fc_part.thought_signature == b"embedded_sig" + + def test_message_to_generate_content_response_no_thought_signature(): """Parts without thought_signature have thought_signature=None.""" message = ChatCompletionAssistantMessage(