diff --git a/letta/agents/letta_agent.py b/letta/agents/letta_agent.py index 348ed669..59acf654 100644 --- a/letta/agents/letta_agent.py +++ b/letta/agents/letta_agent.py @@ -821,6 +821,9 @@ class LettaAgent(BaseAgent): """ tool_call_name = tool_call.function.name tool_call_args_str = tool_call.function.arguments + # Temp hack to gracefully handle parallel tool calling attempt, only take first one + if "}{" in tool_call_args_str: + tool_call_args_str = tool_call_args_str.split("}{", 1)[0] + "}" try: tool_args = json.loads(tool_call_args_str) diff --git a/letta/interfaces/anthropic_streaming_interface.py b/letta/interfaces/anthropic_streaming_interface.py index 4e643afb..16622093 100644 --- a/letta/interfaces/anthropic_streaming_interface.py +++ b/letta/interfaces/anthropic_streaming_interface.py @@ -379,7 +379,7 @@ class AnthropicStreamingInterface: group: List[Union[ReasoningMessage, HiddenReasoningMessage]], group_type: str ) -> Union[TextContent, ReasoningContent, RedactedReasoningContent]: if group_type == "reasoning": - reasoning_text = "".join(chunk.reasoning for chunk in group) + reasoning_text = "".join(chunk.reasoning for chunk in group).strip() is_native = any(chunk.source == "reasoner_model" for chunk in group) signature = next((chunk.signature for chunk in group if chunk.signature is not None), None) if is_native: diff --git a/letta/interfaces/openai_streaming_interface.py b/letta/interfaces/openai_streaming_interface.py index b392a294..33ac6051 100644 --- a/letta/interfaces/openai_streaming_interface.py +++ b/letta/interfaces/openai_streaming_interface.py @@ -32,6 +32,7 @@ class OpenAIStreamingInterface: self.function_args_buffer = None self.function_id_buffer = None self.last_flushed_function_name = None + self.last_flushed_function_id = None # Buffer to hold function arguments until inner thoughts are complete self.current_function_arguments = "" @@ -53,14 +54,14 @@ class OpenAIStreamingInterface: self.reasoning_messages = [] def get_reasoning_content(self) -> List[TextContent]: - content = "".join(self.reasoning_messages) + content = "".join(self.reasoning_messages).strip() return [TextContent(text=content)] def get_tool_call_object(self) -> ToolCall: """Useful for agent loop""" function_name = self.last_flushed_function_name if self.last_flushed_function_name else self.function_name_buffer return ToolCall( - id=self.letta_message_id, + id=self.last_flushed_function_id, function=FunctionCall(arguments=self.current_function_arguments, name=function_name), ) @@ -184,6 +185,8 @@ class OpenAIStreamingInterface: # Record what the last function name we flushed was self.last_flushed_function_name = self.function_name_buffer + if self.last_flushed_function_id is None: + self.last_flushed_function_id = self.function_id_buffer # Clear the buffer self.function_name_buffer = None self.function_id_buffer = None