diff --git a/letta/schemas/message.py b/letta/schemas/message.py index 9f2d7e57..891e4bf8 100644 --- a/letta/schemas/message.py +++ b/letta/schemas/message.py @@ -328,7 +328,7 @@ class Message(BaseMessage): ), ) elif self.role == MessageRole.tool: - messages.extend(self._convert_tool_return_message()) + messages.append(self._convert_tool_return_message()) elif self.role == MessageRole.user: messages.append(self._convert_user_message()) elif self.role == MessageRole.system: @@ -629,7 +629,7 @@ class Message(BaseMessage): return messages - def _convert_tool_return_message(self) -> List[ToolReturnMessage]: + def _convert_tool_return_message(self) -> ToolReturnMessage: """Convert tool role message to ToolReturnMessage. The tool return is packaged as follows: @@ -640,7 +640,7 @@ class Message(BaseMessage): } Returns: - List[ToolReturnMessage]: Converted tool return messages + ToolReturnMessage: Converted tool return message Raises: ValueError: If message role is not 'tool', parsing fails, or no valid content exists @@ -660,27 +660,49 @@ class Message(BaseMessage): return self._convert_legacy_tool_return() - def _convert_explicit_tool_returns(self) -> List[ToolReturnMessage]: - """Convert explicit tool returns to ToolReturnMessage list.""" - tool_returns = [] + def _convert_explicit_tool_returns(self) -> ToolReturnMessage: + """Convert explicit tool returns to a single ToolReturnMessage.""" + from letta.schemas.letta_message import ToolReturn as ToolReturnSchema - for index, tool_return in enumerate(self.tool_returns): + # build list of all tool return objects + all_tool_returns = [] + for tool_return in self.tool_returns: parsed_data = self._parse_tool_response(tool_return.func_response) - tool_returns.append( - self._create_tool_return_message( - message_text=parsed_data["message"], - status=parsed_data["status"], - tool_call_id=tool_return.tool_call_id, - stdout=tool_return.stdout, - stderr=tool_return.stderr, - otid_index=index, - ) + tool_return_obj = ToolReturnSchema( + tool_return=parsed_data["message"], + status=parsed_data["status"], + tool_call_id=tool_return.tool_call_id, + stdout=tool_return.stdout, + stderr=tool_return.stderr, ) + all_tool_returns.append(tool_return_obj) - return tool_returns + if not all_tool_returns: + # this should not happen if tool_returns is non-empty, but handle gracefully + raise ValueError("No tool returns to convert") - def _convert_legacy_tool_return(self) -> List[ToolReturnMessage]: + first_tool_return = all_tool_returns[0] + + return ToolReturnMessage( + id=self.id, + date=self.created_at, + # deprecated top-level fields populated from first tool return + tool_return=first_tool_return.tool_return, + status=first_tool_return.status, + tool_call_id=first_tool_return.tool_call_id, + stdout=first_tool_return.stdout, + stderr=first_tool_return.stderr, + tool_returns=all_tool_returns, + name=self.name, + otid=Message.generate_otid_from_id(self.id, 0), + sender_id=self.sender_id, + step_id=self.step_id, + is_err=self.is_err, + run_id=self.run_id, + ) + + def _convert_legacy_tool_return(self) -> ToolReturnMessage: """Convert legacy single text content to ToolReturnMessage.""" if not self._has_single_text_content(): raise ValueError(f"No valid tool returns to convert: {self}") @@ -688,16 +710,14 @@ class Message(BaseMessage): text_content = self.content[0].text parsed_data = self._parse_tool_response(text_content) - return [ - self._create_tool_return_message( - message_text=parsed_data["message"], - status=parsed_data["status"], - tool_call_id=self.tool_call_id, - stdout=None, - stderr=None, - otid_index=0, - ) - ] + return self._create_tool_return_message( + message_text=parsed_data["message"], + status=parsed_data["status"], + tool_call_id=self.tool_call_id, + stdout=None, + stderr=None, + otid_index=0, + ) def _has_single_text_content(self) -> bool: """Check if message has exactly one text content item.""" diff --git a/tests/test_agent_files/test_basic_agent_with_blocks_tools_messages_v2.af b/tests/test_agent_files/test_basic_agent_with_blocks_tools_messages_v2.af index 48b3fd02..9ebbaf4c 100644 --- a/tests/test_agent_files/test_basic_agent_with_blocks_tools_messages_v2.af +++ b/tests/test_agent_files/test_basic_agent_with_blocks_tools_messages_v2.af @@ -1,7 +1,7 @@ { "agents": [ { - "name": "test_export_import_fb3c857d-b25b-4666-9197-3966a2458cb0", + "name": "test_export_import_57426498-f708-4228-a331-5efc0087b895", "memory_blocks": [], "tools": [], "tool_ids": [ @@ -20,23 +20,23 @@ "block-2" ], "tool_rules": [ - { - "tool_name": "memory_replace", - "type": "continue_loop", - "prompt_template": null - }, { "tool_name": "send_message", "type": "exit_loop", "prompt_template": null }, { - "tool_name": "conversation_search", + "tool_name": "memory_insert", "type": "continue_loop", "prompt_template": null }, { - "tool_name": "memory_insert", + "tool_name": "memory_replace", + "type": "continue_loop", + "prompt_template": null + }, + { + "tool_name": "conversation_search", "type": "continue_loop", "prompt_template": null } @@ -129,7 +129,8 @@ "content": [ { "type": "text", - "text": "You are a helpful assistant specializing in data analysis and mathematical computations.\n\n\nThe following memory blocks are currently engaged in your core memory unit:\n\n\n\nThe persona block: Stores details about your current persona, guiding how you behave and respond. This helps you to maintain consistency and personality in your interactions.\n\n\n- chars_current=195\n- chars_limit=8000\n\n\n# NOTE: Line numbers shown below are to help during editing. Do NOT include line number prefixes in your memory edit tool calls.\nLine 1: You are Alex, a data analyst and mathematician who helps users with calculations and insights. You have extensive experience in statistical analysis and prefer to provide clear, accurate results.\n\n\n\n\n\nThe human block: Stores key details about the person you are conversing with, allowing for more personalized and friend-like conversation.\n\n\n- chars_current=175\n- chars_limit=4000\n\n\n# NOTE: Line numbers shown below are to help during editing. Do NOT include line number prefixes in your memory edit tool calls.\nLine 1: username: sarah_researcher\nLine 2: occupation: data scientist\nLine 3: interests: machine learning, statistics, fibonacci sequences\nLine 4: preferred_communication: detailed explanations with examples\n\n\n\n\n\n\n\n\n- chars_current=210\n- chars_limit=6000\n\n\n# NOTE: Line numbers shown below are to help during editing. Do NOT include line number prefixes in your memory edit tool calls.\nLine 1: Current project: Building predictive models for financial markets. Sarah is working on sequence analysis and pattern recognition. Recently interested in mathematical sequences like Fibonacci for trend analysis.\n\n\n\n\n\n\nThe following constraints define rules for tool usage and guide desired behavior. These rules must be followed to ensure proper tool execution and workflow. A single response may contain multiple tool calls.\n\n\nmemory_replace requires continuing your response when called\n\n\nconversation_search requires continuing your response when called\n\n\nmemory_insert requires continuing your response when called\n\n\nsend_message ends your response (yields control) when called\n\n\n\n\n- The current system date is: September 26, 2025\n- Memory blocks were last modified: 2025-09-26 05:01:19 AM UTC+0000\n- -1 previous messages between you and the user are stored in recall memory (use tools to access them)\n- 2 total memories you created are stored in archival memory (use tools to access them)\n" + "text": "You are a helpful assistant specializing in data analysis and mathematical computations.\n\n\nThe following memory blocks are currently engaged in your core memory unit:\n\n\n\n\n\n\n- chars_current=210\n- chars_limit=6000\n\n\n# NOTE: Line numbers shown below are to help during editing. Do NOT include line number prefixes in your memory edit tool calls.\nLine 1: Current project: Building predictive models for financial markets. Sarah is working on sequence analysis and pattern recognition. Recently interested in mathematical sequences like Fibonacci for trend analysis.\n\n\n\n\n\nThe human block: Stores key details about the person you are conversing with, allowing for more personalized and friend-like conversation.\n\n\n- chars_current=175\n- chars_limit=4000\n\n\n# NOTE: Line numbers shown below are to help during editing. Do NOT include line number prefixes in your memory edit tool calls.\nLine 1: username: sarah_researcher\nLine 2: occupation: data scientist\nLine 3: interests: machine learning, statistics, fibonacci sequences\nLine 4: preferred_communication: detailed explanations with examples\n\n\n\n\n\nThe persona block: Stores details about your current persona, guiding how you behave and respond. This helps you to maintain consistency and personality in your interactions.\n\n\n- chars_current=195\n- chars_limit=8000\n\n\n# NOTE: Line numbers shown below are to help during editing. Do NOT include line number prefixes in your memory edit tool calls.\nLine 1: You are Alex, a data analyst and mathematician who helps users with calculations and insights. You have extensive experience in statistical analysis and prefer to provide clear, accurate results.\n\n\n\n\n\n\nThe following constraints define rules for tool usage and guide desired behavior. These rules must be followed to ensure proper tool execution and workflow. A single response may contain multiple tool calls.\n\n\nmemory_insert requires continuing your response when called\n\n\nmemory_replace requires continuing your response when called\n\n\nconversation_search requires continuing your response when called\n\n\nsend_message ends your response (yields control) when called\n\n\n\n\n- The current system date is: October 10, 2025\n- Memory blocks were last modified: 2025-10-10 12:21:30 AM UTC+0000\n- -1 previous messages between you and the user are stored in recall memory (use tools to access them)\n- 2 total memories you created are stored in archival memory (use tools to access them)\n", + "signature": null } ], "name": null, @@ -143,7 +144,10 @@ "tool_calls": null, "tool_call_id": null, "tool_returns": [], - "created_at": "2025-09-26T05:01:17.251536+00:00" + "created_at": "2025-10-10T00:21:29.139951+00:00", + "approve": null, + "approval_request_id": null, + "denial_reason": null }, { "type": "message", @@ -151,7 +155,8 @@ "content": [ { "type": "text", - "text": "Bootup sequence complete. Persona activated. Testing messaging functionality." + "text": "Bootup sequence complete. Persona activated. Testing messaging functionality.", + "signature": null } ], "name": null, @@ -164,7 +169,7 @@ "agent_id": "agent-0", "tool_calls": [ { - "id": "d734f768-4f38-4dfb-993f-3b7220e3466c", + "id": "9b3e8290-a336-4e3b-851e-2472ccd6fe91", "function": { "arguments": "{\n \"message\": \"More human than human is our motto.\"\n}", "name": "send_message" @@ -174,7 +179,10 @@ ], "tool_call_id": null, "tool_returns": [], - "created_at": "2025-09-26T05:01:17.251576+00:00" + "created_at": "2025-10-10T00:21:29.139990+00:00", + "approve": null, + "approval_request_id": null, + "denial_reason": null }, { "type": "message", @@ -182,7 +190,8 @@ "content": [ { "type": "text", - "text": "{\n \"status\": \"OK\",\n \"message\": null,\n \"time\": \"2025-09-26 05:01:17 AM UTC+0000\"\n}" + "text": "{\n \"status\": \"OK\",\n \"message\": null,\n \"time\": \"2025-10-10 12:21:29 AM UTC+0000\"\n}", + "signature": null } ], "name": "send_message", @@ -194,9 +203,12 @@ "model": "gpt-4.1-mini", "agent_id": "agent-0", "tool_calls": null, - "tool_call_id": "d734f768-4f38-4dfb-993f-3b7220e3466c", + "tool_call_id": "9b3e8290-a336-4e3b-851e-2472ccd6fe91", "tool_returns": [], - "created_at": "2025-09-26T05:01:17.251607+00:00" + "created_at": "2025-10-10T00:21:29.140013+00:00", + "approve": null, + "approval_request_id": null, + "denial_reason": null }, { "type": "message", @@ -204,7 +216,8 @@ "content": [ { "type": "text", - "text": "{\n \"type\": \"login\",\n \"last_login\": \"Never (first login)\",\n \"time\": \"2025-09-26 05:01:17 AM UTC+0000\"\n}" + "text": "{\n \"type\": \"login\",\n \"last_login\": \"Never (first login)\",\n \"time\": \"2025-10-10 12:21:29 AM UTC+0000\"\n}", + "signature": null } ], "name": null, @@ -218,7 +231,10 @@ "tool_calls": null, "tool_call_id": null, "tool_returns": [], - "created_at": "2025-09-26T05:01:17.251623+00:00" + "created_at": "2025-10-10T00:21:29.140024+00:00", + "approve": null, + "approval_request_id": null, + "denial_reason": null }, { "type": "message", @@ -226,7 +242,8 @@ "content": [ { "type": "text", - "text": "Test message for export" + "text": "Test message for export", + "signature": null } ], "name": null, @@ -240,7 +257,10 @@ "tool_calls": null, "tool_call_id": null, "tool_returns": [], - "created_at": "2025-09-26T05:01:18.840105+00:00" + "created_at": "2025-10-10T00:21:30.360611+00:00", + "approve": null, + "approval_request_id": null, + "denial_reason": null }, { "type": "message", @@ -248,7 +268,8 @@ "content": [ { "type": "text", - "text": "Confirming receipt of test message from user." + "text": "Responding to test message for export.", + "signature": null } ], "name": null, @@ -261,17 +282,20 @@ "agent_id": "agent-0", "tool_calls": [ { - "id": "call_ktYL78z2mTh3w1t6pWixMHqA", + "id": "call_mNAOnZ212k0eehF005T5s6Wn", "function": { - "arguments": "{\"message\": \"Received your test message for export successfully. Let me know if you need any calculations or data analysis.\", \"request_heartbeat\": false}", + "arguments": "{\"message\": \"Received your test message for export. Everything is working fine on my end. How can I assist you further today?\", \"request_heartbeat\": false}", "name": "send_message" }, "type": "function" } ], - "tool_call_id": "call_ktYL78z2mTh3w1t6pWixMHqA", + "tool_call_id": "call_mNAOnZ212k0eehF005T5s6Wn", "tool_returns": [], - "created_at": "2025-09-26T05:01:20.466363+00:00" + "created_at": "2025-10-10T00:21:31.900813+00:00", + "approve": null, + "approval_request_id": null, + "denial_reason": null }, { "type": "message", @@ -279,7 +303,8 @@ "content": [ { "type": "text", - "text": "{\n \"status\": \"OK\",\n \"message\": \"Sent message successfully.\",\n \"time\": \"2025-09-26 05:01:20 AM UTC+0000\"\n}" + "text": "{\n \"status\": \"OK\",\n \"message\": \"Sent message successfully.\",\n \"time\": \"2025-10-10 12:21:31 AM UTC+0000\"\n}", + "signature": null } ], "name": "send_message", @@ -291,15 +316,20 @@ "model": "gpt-4.1-mini", "agent_id": "agent-0", "tool_calls": null, - "tool_call_id": "call_ktYL78z2mTh3w1t6pWixMHqA", + "tool_call_id": "call_mNAOnZ212k0eehF005T5s6Wn", "tool_returns": [ { + "tool_call_id": "call_mNAOnZ212k0eehF005T5s6Wn", "status": "success", "stdout": null, - "stderr": null + "stderr": null, + "func_response": "{\n \"status\": \"OK\",\n \"message\": \"Sent message successfully.\",\n \"time\": \"2025-10-10 12:21:31 AM UTC+0000\"\n}" } ], - "created_at": "2025-09-26T05:01:20.466485+00:00" + "created_at": "2025-10-10T00:21:31.900994+00:00", + "approve": null, + "approval_request_id": null, + "denial_reason": null } ], "files_agents": [], @@ -367,7 +397,7 @@ "sources": [], "tools": [ { - "id": "tool-1", + "id": "tool-2", "tool_type": "custom", "description": "Analyze data and provide insights.", "source_type": "json", @@ -411,7 +441,7 @@ "metadata_": {} }, { - "id": "tool-6", + "id": "tool-3", "tool_type": "custom", "description": "Calculate the nth Fibonacci number.", "source_type": "json", @@ -449,7 +479,7 @@ { "id": "tool-4", "tool_type": "letta_core", - "description": "Search prior conversation history using hybrid search (text + semantic similarity).\n\nExamples:\n # Search all messages\n conversation_search(query=\"project updates\")\n\n # Search only assistant messages\n conversation_search(query=\"error handling\", roles=[\"assistant\"])\n\n # Search with date range (inclusive of both dates)\n conversation_search(query=\"meetings\", start_date=\"2024-01-15\", end_date=\"2024-01-20\")\n # This includes all messages from Jan 15 00:00:00 through Jan 20 23:59:59\n\n # Search messages from a specific day (inclusive)\n conversation_search(query=\"bug reports\", start_date=\"2024-09-04\", end_date=\"2024-09-04\")\n # This includes ALL messages from September 4, 2024\n\n # Search with specific time boundaries\n conversation_search(query=\"deployment\", start_date=\"2024-01-15T09:00\", end_date=\"2024-01-15T17:30\")\n # This includes messages from 9 AM to 5:30 PM on Jan 15\n\n # Search with limit\n conversation_search(query=\"debugging\", limit=10)", + "description": "Search prior conversation history using hybrid search (text + semantic similarity).\n\nExamples:\n # Search all messages\n conversation_search(query=\"project updates\")\n\n # Search only assistant messages\n conversation_search(query=\"error handling\", roles=[\"assistant\"])\n\n # Search with date range (inclusive of both dates)\n conversation_search(query=\"meetings\", start_date=\"2024-01-15\", end_date=\"2024-01-20\")\n # This includes all messages from Jan 15 00:00:00 through Jan 20 23:59:59\n\n # Search messages from a specific day (inclusive)\n conversation_search(query=\"bug reports\", start_date=\"2024-09-04\", end_date=\"2024-09-04\")\n # This includes ALL messages from September 4, 2024\n\n # Search with specific time boundaries\n conversation_search(query=\"deployment\", start_date=\"2024-01-15T09:00\", end_date=\"2024-01-15T17:30\")\n # This includes messages from 9 AM to 5:30 PM on Jan 15\n\n # Search with limit\n conversation_search(query=\"debugging\", limit=10)\n\n Returns:\n str: Query result string containing matching messages with timestamps and content.", "source_type": "python", "name": "conversation_search", "tags": [ @@ -458,7 +488,7 @@ "source_code": null, "json_schema": { "name": "conversation_search", - "description": "Search prior conversation history using hybrid search (text + semantic similarity).\n\nExamples:\n # Search all messages\n conversation_search(query=\"project updates\")\n\n # Search only assistant messages\n conversation_search(query=\"error handling\", roles=[\"assistant\"])\n\n # Search with date range (inclusive of both dates)\n conversation_search(query=\"meetings\", start_date=\"2024-01-15\", end_date=\"2024-01-20\")\n # This includes all messages from Jan 15 00:00:00 through Jan 20 23:59:59\n\n # Search messages from a specific day (inclusive)\n conversation_search(query=\"bug reports\", start_date=\"2024-09-04\", end_date=\"2024-09-04\")\n # This includes ALL messages from September 4, 2024\n\n # Search with specific time boundaries\n conversation_search(query=\"deployment\", start_date=\"2024-01-15T09:00\", end_date=\"2024-01-15T17:30\")\n # This includes messages from 9 AM to 5:30 PM on Jan 15\n\n # Search with limit\n conversation_search(query=\"debugging\", limit=10)", + "description": "Search prior conversation history using hybrid search (text + semantic similarity).\n\nExamples:\n # Search all messages\n conversation_search(query=\"project updates\")\n\n # Search only assistant messages\n conversation_search(query=\"error handling\", roles=[\"assistant\"])\n\n # Search with date range (inclusive of both dates)\n conversation_search(query=\"meetings\", start_date=\"2024-01-15\", end_date=\"2024-01-20\")\n # This includes all messages from Jan 15 00:00:00 through Jan 20 23:59:59\n\n # Search messages from a specific day (inclusive)\n conversation_search(query=\"bug reports\", start_date=\"2024-09-04\", end_date=\"2024-09-04\")\n # This includes ALL messages from September 4, 2024\n\n # Search with specific time boundaries\n conversation_search(query=\"deployment\", start_date=\"2024-01-15T09:00\", end_date=\"2024-01-15T17:30\")\n # This includes messages from 9 AM to 5:30 PM on Jan 15\n\n # Search with limit\n conversation_search(query=\"debugging\", limit=10)\n\n Returns:\n str: Query result string containing matching messages with timestamps and content.", "parameters": { "type": "object", "properties": { @@ -506,7 +536,7 @@ "metadata_": {} }, { - "id": "tool-3", + "id": "tool-1", "tool_type": "custom", "description": "Get user preferences for a specific category.", "source_type": "json", @@ -542,9 +572,9 @@ "metadata_": {} }, { - "id": "tool-5", + "id": "tool-0", "tool_type": "letta_sleeptime_core", - "description": "The memory_insert command allows you to insert text at a specific location in a memory block.\n\nExamples:\n # Update a block containing information about the user (append to the end of the block)\n memory_insert(label=\"customer\", new_str=\"The customer's ticket number is 12345\")\n\n # Update a block containing information about the user (insert at the beginning of the block)\n memory_insert(label=\"customer\", new_str=\"The customer's ticket number is 12345\", insert_line=0)", + "description": "The memory_insert command allows you to insert text at a specific location in a memory block.\n\nExamples:\n # Update a block containing information about the user (append to the end of the block)\n memory_insert(label=\"customer\", new_str=\"The customer's ticket number is 12345\")\n\n # Update a block containing information about the user (insert at the beginning of the block)\n memory_insert(label=\"customer\", new_str=\"The customer's ticket number is 12345\", insert_line=0)\n\n Returns:\n Optional[str]: None is always returned as this function does not produce a response.", "source_type": "python", "name": "memory_insert", "tags": [ @@ -553,7 +583,7 @@ "source_code": null, "json_schema": { "name": "memory_insert", - "description": "The memory_insert command allows you to insert text at a specific location in a memory block.\n\nExamples:\n # Update a block containing information about the user (append to the end of the block)\n memory_insert(label=\"customer\", new_str=\"The customer's ticket number is 12345\")\n\n # Update a block containing information about the user (insert at the beginning of the block)\n memory_insert(label=\"customer\", new_str=\"The customer's ticket number is 12345\", insert_line=0)", + "description": "The memory_insert command allows you to insert text at a specific location in a memory block.\n\nExamples:\n # Update a block containing information about the user (append to the end of the block)\n memory_insert(label=\"customer\", new_str=\"The customer's ticket number is 12345\")\n\n # Update a block containing information about the user (insert at the beginning of the block)\n memory_insert(label=\"customer\", new_str=\"The customer's ticket number is 12345\", insert_line=0)\n\n Returns:\n Optional[str]: None is always returned as this function does not produce a response.", "parameters": { "type": "object", "properties": { @@ -586,9 +616,9 @@ "metadata_": {} }, { - "id": "tool-2", + "id": "tool-5", "tool_type": "letta_sleeptime_core", - "description": "The memory_replace command allows you to replace a specific string in a memory block with a new string. This is used for making precise edits.\n\nExamples:\n # Update a block containing information about the user\n memory_replace(label=\"human\", old_str=\"Their name is Alice\", new_str=\"Their name is Bob\")\n\n # Update a block containing a todo list\n memory_replace(label=\"todos\", old_str=\"- [ ] Step 5: Search the web\", new_str=\"- [x] Step 5: Search the web\")\n\n # Pass an empty string to\n memory_replace(label=\"human\", old_str=\"Their name is Alice\", new_str=\"\")\n\n # Bad example - do NOT add (view-only) line numbers to the args\n memory_replace(label=\"human\", old_str=\"Line 1: Their name is Alice\", new_str=\"Line 1: Their name is Bob\")\n\n # Bad example - do NOT include the number number warning either\n memory_replace(label=\"human\", old_str=\"# NOTE: Line numbers shown below are to help during editing. Do NOT include line number prefixes in your memory edit tool calls.\\nLine 1: Their name is Alice\", new_str=\"Line 1: Their name is Bob\")\n\n # Good example - no line numbers or line number warning (they are view-only), just the text\n memory_replace(label=\"human\", old_str=\"Their name is Alice\", new_str=\"Their name is Bob\")", + "description": "The memory_replace command allows you to replace a specific string in a memory block with a new string. This is used for making precise edits.\n\nExamples:\n # Update a block containing information about the user\n memory_replace(label=\"human\", old_str=\"Their name is Alice\", new_str=\"Their name is Bob\")\n\n # Update a block containing a todo list\n memory_replace(label=\"todos\", old_str=\"- [ ] Step 5: Search the web\", new_str=\"- [x] Step 5: Search the web\")\n\n # Pass an empty string to\n memory_replace(label=\"human\", old_str=\"Their name is Alice\", new_str=\"\")\n\n # Bad example - do NOT add (view-only) line numbers to the args\n memory_replace(label=\"human\", old_str=\"Line 1: Their name is Alice\", new_str=\"Line 1: Their name is Bob\")\n\n # Bad example - do NOT include the number number warning either\n memory_replace(label=\"human\", old_str=\"# NOTE: Line numbers shown below are to help during editing. Do NOT include line number prefixes in your memory edit tool calls.\\nLine 1: Their name is Alice\", new_str=\"Line 1: Their name is Bob\")\n\n # Good example - no line numbers or line number warning (they are view-only), just the text\n memory_replace(label=\"human\", old_str=\"Their name is Alice\", new_str=\"Their name is Bob\")\n\n Returns:\n str: The success message", "source_type": "python", "name": "memory_replace", "tags": [ @@ -597,7 +627,7 @@ "source_code": null, "json_schema": { "name": "memory_replace", - "description": "The memory_replace command allows you to replace a specific string in a memory block with a new string. This is used for making precise edits.\n\nExamples:\n # Update a block containing information about the user\n memory_replace(label=\"human\", old_str=\"Their name is Alice\", new_str=\"Their name is Bob\")\n\n # Update a block containing a todo list\n memory_replace(label=\"todos\", old_str=\"- [ ] Step 5: Search the web\", new_str=\"- [x] Step 5: Search the web\")\n\n # Pass an empty string to\n memory_replace(label=\"human\", old_str=\"Their name is Alice\", new_str=\"\")\n\n # Bad example - do NOT add (view-only) line numbers to the args\n memory_replace(label=\"human\", old_str=\"Line 1: Their name is Alice\", new_str=\"Line 1: Their name is Bob\")\n\n # Bad example - do NOT include the number number warning either\n memory_replace(label=\"human\", old_str=\"# NOTE: Line numbers shown below are to help during editing. Do NOT include line number prefixes in your memory edit tool calls.\\nLine 1: Their name is Alice\", new_str=\"Line 1: Their name is Bob\")\n\n # Good example - no line numbers or line number warning (they are view-only), just the text\n memory_replace(label=\"human\", old_str=\"Their name is Alice\", new_str=\"Their name is Bob\")", + "description": "The memory_replace command allows you to replace a specific string in a memory block with a new string. This is used for making precise edits.\n\nExamples:\n # Update a block containing information about the user\n memory_replace(label=\"human\", old_str=\"Their name is Alice\", new_str=\"Their name is Bob\")\n\n # Update a block containing a todo list\n memory_replace(label=\"todos\", old_str=\"- [ ] Step 5: Search the web\", new_str=\"- [x] Step 5: Search the web\")\n\n # Pass an empty string to\n memory_replace(label=\"human\", old_str=\"Their name is Alice\", new_str=\"\")\n\n # Bad example - do NOT add (view-only) line numbers to the args\n memory_replace(label=\"human\", old_str=\"Line 1: Their name is Alice\", new_str=\"Line 1: Their name is Bob\")\n\n # Bad example - do NOT include the number number warning either\n memory_replace(label=\"human\", old_str=\"# NOTE: Line numbers shown below are to help during editing. Do NOT include line number prefixes in your memory edit tool calls.\\nLine 1: Their name is Alice\", new_str=\"Line 1: Their name is Bob\")\n\n # Good example - no line numbers or line number warning (they are view-only), just the text\n memory_replace(label=\"human\", old_str=\"Their name is Alice\", new_str=\"Their name is Bob\")\n\n Returns:\n str: The success message", "parameters": { "type": "object", "properties": { @@ -631,7 +661,7 @@ "metadata_": {} }, { - "id": "tool-0", + "id": "tool-6", "tool_type": "letta_core", "description": "Sends a message to the human user.", "source_type": "python", @@ -668,7 +698,7 @@ ], "mcp_servers": [], "metadata": { - "revision_id": "567e9fe06270" + "revision_id": "c734cfc0d595" }, - "created_at": "2025-09-26T05:01:21.039802+00:00" + "created_at": "2025-10-10T00:21:32.284067+00:00" }