From 4126fdadeafe9d4f24bada7b8814374ac6da8703 Mon Sep 17 00:00:00 2001 From: Kian Jones <11655409+kianjones9@users.noreply.github.com> Date: Thu, 12 Feb 2026 12:13:23 -0800 Subject: [PATCH] fix(core): preserve thought_signature on TextContent in Gemini streaming path (#9461) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit get_content() was only setting signature on ReasoningContent items. When Gemini returns a function call with thought_signature but no ReasoningContent (e.g. include_thoughts=False), the signature was stored on self.thinking_signature but never attached to TextContent. This caused "missing thought_signature in functionCall parts" errors when the message was echoed back to Gemini on the next turn. 🐾 Generated with [Letta Code](https://letta.com) Co-authored-by: Letta --- letta/interfaces/gemini_streaming_interface.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/letta/interfaces/gemini_streaming_interface.py b/letta/interfaces/gemini_streaming_interface.py index 9656977c..e7f45040 100644 --- a/letta/interfaces/gemini_streaming_interface.py +++ b/letta/interfaces/gemini_streaming_interface.py @@ -97,9 +97,11 @@ class SimpleGeminiStreamingInterface: def get_content(self) -> List[ReasoningContent | TextContent | ToolCallContent]: """This is (unusually) in chunked format, instead of merged""" + has_reasoning = any(isinstance(c, ReasoningContent) for c in self.content_parts) for content in self.content_parts: if isinstance(content, ReasoningContent): - # This assumes there is only one signature per turn + content.signature = self.thinking_signature + elif isinstance(content, TextContent) and not has_reasoning and self.thinking_signature: content.signature = self.thinking_signature return self.content_parts