Skip to content

fix: strip embedded thought signature from LiteLLM tool call ids - #6599

Open
benclarkeio wants to merge 1 commit into
google:mainfrom
benclarkeio:fix/strip-thought-signature-from-tool-call-id
Open

fix: strip embedded thought signature from LiteLLM tool call ids#6599
benclarkeio wants to merge 1 commit into
google:mainfrom
benclarkeio:fix/strip-thought-signature-from-tool-call-id

Conversation

@benclarkeio

Copy link
Copy Markdown
Contributor

Problem

LiteLLM embeds a Gemini thought_signature inside the tool call id, separated by __thought__ (see _THOUGHT_SIGNATURE_SEPARATOR). _message_to_generate_content_response already extracts that signature onto part.thought_signature, but then assigns the raw id to part.function_call.id:

thought_signature = _extract_thought_signature_from_tool_call(tool_call)
part = types.Part.from_function_call(...)
part.function_call.id = tool_call.id      # still "call_abc__thought__AY89a18..."
if thought_signature:
    part.thought_signature = thought_signature

So every consumer of function_call_id gets several hundred characters of base64 glued onto the real id. In practice this leaks into artifact filenames, logs, and any UI that displays a tool call id — for example a saved artifact named:

my_tool_code_mode-fkmp52ci__thought__AY89a18qpllj6mkpxPjhFEcbBbtEsqy4Ia4Eam2lD_NsoZ...-1.json

Fix

Split the separator off before assigning the id. The signature is already preserved on the part, so nothing is lost.

Why the round trip still works

  • _content_to_message_param re-attaches the signature to the outgoing tool call from part.thought_signature, via both provider_specific_fields and extra_content.google.thought_signature.
  • _extract_thought_signature_from_tool_call checks those two locations before falling back to the id-embedded form, which exists only for providers that drop the other channels.
  • Both sides of the call/response pairing (the assistant tool_calls entry and the tool message's tool_call_id) are generated from ADK's own stored parts, so stripping consistently keeps them matched.

Testing

Added test_message_to_generate_content_response_strips_signature_from_id, asserting the id is split and the signature still lands on the part. Full tests/unittests/models/test_litellm.py passes (257 passed).

LiteLLM embeds a Gemini `thought_signature` in the tool call id, separated
by `__thought__`. `_message_to_generate_content_response` already lifts that
signature onto `part.thought_signature`, but then assigned the raw id to
`part.function_call.id`, so every consumer of `function_call_id` saw a few
hundred characters of base64 appended to the real id.

- Split the separator off the id before assigning it to the function call
- Leave `thought_signature` extraction unchanged, so nothing is lost

The round trip is unaffected: `_content_to_message_param` re-attaches the
signature to the outgoing tool call from `part.thought_signature` via
`provider_specific_fields` and `extra_content.google.thought_signature`, and
`_extract_thought_signature_from_tool_call` reads both of those before it
falls back to the id-embedded form. Both sides of the call/response pairing
are generated from ADK's own stored parts, so ids stay matched.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@google-cla

google-cla Bot commented Aug 5, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@adk-bot adk-bot added the models [Component] This issue is related to model support label Aug 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

models [Component] This issue is related to model support

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants