diff --git a/examples/helper.py b/examples/helper.py
index f19e8ffb13..18b60cc446 100644
--- a/examples/helper.py
+++ b/examples/helper.py
@@ -95,6 +95,8 @@ def nb_print(messages):
def get_formatted_content(msg):
if msg.message_type == "internal_monologue":
return f'
{html.escape(msg.internal_monologue)}
'
+ elif msg.message_type == "reasoning_message":
+ return f'{html.escape(msg.reasoning)}
'
elif msg.message_type == "function_call":
args = format_json(msg.function_call.arguments)
return f'{html.escape(msg.function_call.name)}({args})
'
diff --git a/letta/client/streaming.py b/letta/client/streaming.py
index 9f57352b73..4a258cdc7a 100644
--- a/letta/client/streaming.py
+++ b/letta/client/streaming.py
@@ -10,7 +10,7 @@
from letta.schemas.letta_message import (
ToolCallMessage,
ToolReturnMessage,
- InternalMonologue,
+ ReasoningMessage,
)
from letta.schemas.letta_response import LettaStreamingResponse
from letta.schemas.usage import LettaUsageStatistics
@@ -53,8 +53,8 @@ def _sse_post(url: str, data: dict, headers: dict) -> Generator[LettaStreamingRe
yield MessageStreamStatus(sse.data)
else:
chunk_data = json.loads(sse.data)
- if "internal_monologue" in chunk_data:
- yield InternalMonologue(**chunk_data)
+ if "reasoning" in chunk_data:
+ yield ReasoningMessage(**chunk_data)
elif "tool_call" in chunk_data:
yield ToolCallMessage(**chunk_data)
elif "tool_return" in chunk_data:
diff --git a/letta/schemas/letta_message.py b/letta/schemas/letta_message.py
index 424a003844..45fcf36180 100644
--- a/letta/schemas/letta_message.py
+++ b/letta/schemas/letta_message.py
@@ -60,18 +60,18 @@ class UserMessage(LettaMessage):
message: str
-class InternalMonologue(LettaMessage):
+class ReasoningMessage(LettaMessage):
"""
- Representation of an agent's internal monologue.
+ Representation of an agent's internal reasoning.
Attributes:
- internal_monologue (str): The internal monologue of the agent
+ reasoning (str): The internal reasoning of the agent
id (str): The ID of the message
date (datetime): The date the message was created in ISO format
"""
- message_type: Literal["internal_monologue"] = "internal_monologue"
- internal_monologue: str
+ message_type: Literal["reasoning_message"] = "reasoning_message"
+ reasoning: str
class ToolCall(BaseModel):
@@ -196,10 +196,24 @@ class LegacyFunctionReturn(LettaMessage):
stderr: Optional[List[str]] = None
-LegacyLettaMessage = Union[InternalMonologue, AssistantMessage, LegacyFunctionCallMessage, LegacyFunctionReturn]
+class LegacyInternalMonologue(LettaMessage):
+ """
+ Representation of an agent's internal monologue.
+
+ Attributes:
+ internal_monologue (str): The internal monologue of the agent
+ id (str): The ID of the message
+ date (datetime): The date the message was created in ISO format
+ """
+
+ message_type: Literal["internal_monologue"] = "internal_monologue"
+ internal_monologue: str
+
+
+LegacyLettaMessage = Union[LegacyInternalMonologue, AssistantMessage, LegacyFunctionCallMessage, LegacyFunctionReturn]
LettaMessageUnion = Annotated[
- Union[SystemMessage, UserMessage, InternalMonologue, ToolCallMessage, ToolReturnMessage, AssistantMessage],
+ Union[SystemMessage, UserMessage, ReasoningMessage, ToolCallMessage, ToolReturnMessage, AssistantMessage],
Field(discriminator="message_type"),
]
diff --git a/letta/schemas/letta_response.py b/letta/schemas/letta_response.py
index 990a55cb15..c6a1e8be58 100644
--- a/letta/schemas/letta_response.py
+++ b/letta/schemas/letta_response.py
@@ -40,6 +40,8 @@ def _repr_html_(self):
def get_formatted_content(msg):
if msg.message_type == "internal_monologue":
return f'{html.escape(msg.internal_monologue)}
'
+ if msg.message_type == "reasoning_message":
+ return f'{html.escape(msg.reasoning)}
'
elif msg.message_type == "function_call":
args = format_json(msg.function_call.arguments)
return f'{html.escape(msg.function_call.name)}({args})
'
diff --git a/letta/schemas/message.py b/letta/schemas/message.py
index b548ec256a..74bb813567 100644
--- a/letta/schemas/message.py
+++ b/letta/schemas/message.py
@@ -19,7 +19,7 @@
ToolCall as LettaToolCall,
ToolCallMessage,
ToolReturnMessage,
- InternalMonologue,
+ ReasoningMessage,
LettaMessage,
SystemMessage,
UserMessage,
@@ -145,10 +145,10 @@ def to_letta_message(
if self.text is not None:
# This is type InnerThoughts
messages.append(
- InternalMonologue(
+ ReasoningMessage(
id=self.id,
date=self.created_at,
- internal_monologue=self.text,
+ reasoning=self.text,
)
)
if self.tool_calls is not None:
diff --git a/letta/server/rest_api/interface.py b/letta/server/rest_api/interface.py
index 85248ec3bb..b3d344798b 100644
--- a/letta/server/rest_api/interface.py
+++ b/letta/server/rest_api/interface.py
@@ -16,7 +16,7 @@
ToolCallDelta,
ToolCallMessage,
ToolReturnMessage,
- InternalMonologue,
+ ReasoningMessage,
LegacyFunctionCallMessage,
LegacyLettaMessage,
LettaMessage,
@@ -411,7 +411,7 @@ def clear():
def _process_chunk_to_letta_style(
self, chunk: ChatCompletionChunkResponse, message_id: str, message_date: datetime
- ) -> Optional[Union[InternalMonologue, ToolCallMessage, AssistantMessage]]:
+ ) -> Optional[Union[ReasoningMessage, ToolCallMessage, AssistantMessage]]:
"""
Example data from non-streaming response looks like:
@@ -426,10 +426,10 @@ def _process_chunk_to_letta_style(
# inner thoughts
if message_delta.content is not None:
- processed_chunk = InternalMonologue(
+ processed_chunk = ReasoningMessage(
id=message_id,
date=message_date,
- internal_monologue=message_delta.content,
+ reasoning=message_delta.content,
)
# tool calls
@@ -518,10 +518,10 @@ def _process_chunk_to_letta_style(
# If we have inner thoughts, we should output them as a chunk
if updates_inner_thoughts:
- processed_chunk = InternalMonologue(
+ processed_chunk = ReasoningMessage(
id=message_id,
date=message_date,
- internal_monologue=updates_inner_thoughts,
+ reasoning=updates_inner_thoughts,
)
# Additionally inner thoughts may stream back with a chunk of main JSON
# In that case, since we can only return a chunk at a time, we should buffer it
@@ -680,13 +680,13 @@ def _process_chunk_to_letta_style(
# Once we get a complete key, check if the key matches
# If it does match, start processing the value (stringified-JSON string
- # And with each new chunk, output it as a chunk of type InternalMonologue
+ # And with each new chunk, output it as a chunk of type ReasoningMessage
# If the key doesn't match, then flush the buffer as a single ToolCallMessage chunk
# If we're reading a value
- # If we're reading the inner thoughts value, we output chunks of type InternalMonologue
+ # If we're reading the inner thoughts value, we output chunks of type ReasoningMessage
# Otherwise, do simple chunks of ToolCallMessage
@@ -823,10 +823,10 @@ def internal_monologue(self, msg: str, msg_obj: Optional[Message] = None):
# "id": str(msg_obj.id) if msg_obj is not None else None,
# }
assert msg_obj is not None, "Internal monologue requires msg_obj references for metadata"
- processed_chunk = InternalMonologue(
+ processed_chunk = ReasoningMessage(
id=msg_obj.id,
date=msg_obj.created_at,
- internal_monologue=msg,
+ reasoning=msg,
)
self._push_to_buffer(processed_chunk)
diff --git a/tests/helpers/endpoints_helper.py b/tests/helpers/endpoints_helper.py
index a526f2315b..c267a4bd1f 100644
--- a/tests/helpers/endpoints_helper.py
+++ b/tests/helpers/endpoints_helper.py
@@ -26,7 +26,7 @@
from letta.schemas.embedding_config import EmbeddingConfig
from letta.schemas.letta_message import (
ToolCallMessage,
- InternalMonologue,
+ ReasoningMessage,
LettaMessage,
)
from letta.schemas.letta_response import LettaResponse
@@ -419,7 +419,7 @@ def assert_invoked_function_call(messages: List[LettaMessage], function_name: st
def assert_inner_monologue_is_present_and_valid(messages: List[LettaMessage]) -> None:
for message in messages:
- if isinstance(message, InternalMonologue):
+ if isinstance(message, ReasoningMessage):
# Found it, do nothing
return
diff --git a/tests/test_client_legacy.py b/tests/test_client_legacy.py
index 30b78c911f..37c227c526 100644
--- a/tests/test_client_legacy.py
+++ b/tests/test_client_legacy.py
@@ -20,7 +20,7 @@
AssistantMessage,
ToolCallMessage,
ToolReturnMessage,
- InternalMonologue,
+ ReasoningMessage,
LettaMessage,
SystemMessage,
UserMessage,
@@ -171,7 +171,7 @@ def test_agent_interactions(mock_e2b_api_key_none, client: Union[LocalClient, RE
assert type(letta_message) in [
SystemMessage,
UserMessage,
- InternalMonologue,
+ ReasoningMessage,
ToolCallMessage,
ToolReturnMessage,
AssistantMessage,
@@ -255,7 +255,7 @@ def test_streaming_send_message(mock_e2b_api_key_none, client: RESTClient, agent
assert response, "Sending message failed"
for chunk in response:
assert isinstance(chunk, LettaStreamingResponse)
- if isinstance(chunk, InternalMonologue) and chunk.internal_monologue and chunk.internal_monologue != "":
+ if isinstance(chunk, ReasoningMessage) and chunk.reasoning and chunk.reasoning != "":
inner_thoughts_exist = True
inner_thoughts_count += 1
if isinstance(chunk, ToolCallMessage) and chunk.tool_call and chunk.tool_call.name == "send_message":
diff --git a/tests/test_server.py b/tests/test_server.py
index fc39d527a5..2209c8bcff 100644
--- a/tests/test_server.py
+++ b/tests/test_server.py
@@ -12,7 +12,7 @@
from letta.schemas.letta_message import (
ToolCallMessage,
ToolReturnMessage,
- InternalMonologue,
+ ReasoningMessage,
LettaMessage,
SystemMessage,
UserMessage,
@@ -691,14 +691,14 @@ def _test_get_messages_letta_format(
letta_message = letta_messages[letta_message_index]
if message.text:
- assert isinstance(letta_message, InternalMonologue)
+ assert isinstance(letta_message, ReasoningMessage)
letta_message_index += 1
else:
assert message.tool_calls is not None
else: # Non-reverse handling
if message.text:
- assert isinstance(letta_message, InternalMonologue)
+ assert isinstance(letta_message, ReasoningMessage)
letta_message_index += 1
if letta_message_index >= len(letta_messages):
break