Skip to content

Commit c7442b7

Browse files
committed
fix: patch some stuff
1 parent c0ffe24 commit c7442b7

File tree

3 files changed

+30
-20
lines changed

3 files changed

+30
-20
lines changed

letta/agents/letta_agent_v3.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,11 @@ async def _step(
385385
self.response_messages.extend(persisted_messages[new_message_idx:])
386386

387387
if llm_adapter.supports_token_streaming():
388-
if persisted_messages[-1].role != "approval" and tool_call is not None:
388+
# Stream the tool return if a tool was actually executed.
389+
# In the normal streaming path, the tool call is surfaced via the streaming interface
390+
# (llm_adapter.tool_call), so don't rely solely on the local `tool_call` variable.
391+
has_tool_return = any(m.role == "tool" for m in persisted_messages)
392+
if persisted_messages[-1].role != "approval" and has_tool_return:
389393
tool_return = [msg for msg in persisted_messages if msg.role == "tool"][-1].to_letta_messages()[0]
390394
if include_return_message_types is None or tool_return.message_type in include_return_message_types:
391395
yield tool_return

letta/schemas/letta_message_content.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from enum import Enum
22
from typing import Annotated, List, Literal, Optional, Union
33

4+
from openai.types import Reasoning
45
from pydantic import BaseModel, Field
56

67

@@ -274,14 +275,18 @@ class SummarizedReasoningContent(MessageContent):
274275
encrypted_content: str = Field(default=None, description="The encrypted reasoning content.")
275276

276277
# Temporary stop-gap until the SDKs are updated
277-
def to_reasoning_content(self):
278+
def to_reasoning_content(self) -> Optional[ReasoningContent]:
278279
# Merge the summary parts with a '\n' join
279-
combined_summary = "\n\n".join([s.text for s in self.summary])
280-
return ReasoningContent(
281-
is_native=True,
282-
reasoning=combined_summary,
283-
signature=self.encrypted_content,
284-
)
280+
parts = [s.text for s in self.summary if s.text != ""]
281+
if not parts or len(parts) == 0:
282+
return None
283+
else:
284+
combined_summary = "\n\n".join(parts)
285+
return ReasoningContent(
286+
is_native=True,
287+
reasoning=combined_summary,
288+
signature=self.encrypted_content,
289+
)
285290

286291

287292
LettaMessageContentUnion = Annotated[

letta/schemas/message.py

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -389,19 +389,20 @@ def _convert_reasoning_messages(
389389
elif isinstance(content_part, SummarizedReasoningContent):
390390
# TODO remove the cast and just return the native type
391391
casted_content_part = content_part.to_reasoning_content()
392-
messages.append(
393-
ReasoningMessage(
394-
id=self.id,
395-
date=self.created_at,
396-
reasoning=casted_content_part.reasoning,
397-
source="reasoner_model", # TODO do we want to tag like this?
398-
signature=casted_content_part.signature,
399-
name=self.name,
400-
otid=otid,
401-
step_id=self.step_id,
402-
is_err=self.is_err,
392+
if casted_content_part is not None:
393+
messages.append(
394+
ReasoningMessage(
395+
id=self.id,
396+
date=self.created_at,
397+
reasoning=casted_content_part.reasoning,
398+
source="reasoner_model", # TODO do we want to tag like this?
399+
signature=casted_content_part.signature,
400+
name=self.name,
401+
otid=otid,
402+
step_id=self.step_id,
403+
is_err=self.is_err,
404+
)
403405
)
404-
)
405406

406407
elif isinstance(content_part, RedactedReasoningContent):
407408
# "native" redacted/hidden COT

0 commit comments

Comments
 (0)