feat: Return nested tool returns (#5305)

* Adapt to support multiple tool returns

* remove unused create_tool_return_message

* Add explanation to otid index

* Simplify explicit tool returns

* Simplify function return to only return single object
This commit is contained in:
Matthew Zhou
2025-10-09 23:38:59 -07:00
committed by Caren Thomas
parent 207ef28fd9
commit b06619c290
2 changed files with 121 additions and 71 deletions

View File

@@ -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."""

View File

@@ -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<memory_blocks>\nThe following memory blocks are currently engaged in your core memory unit:\n\n<persona>\n<description>\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</description>\n<metadata>\n- chars_current=195\n- chars_limit=8000\n</metadata>\n<value>\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</value>\n</persona>\n\n<human>\n<description>\nThe human block: Stores key details about the person you are conversing with, allowing for more personalized and friend-like conversation.\n</description>\n<metadata>\n- chars_current=175\n- chars_limit=4000\n</metadata>\n<value>\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</value>\n</human>\n\n<project_context>\n<description>\n\n</description>\n<metadata>\n- chars_current=210\n- chars_limit=6000\n</metadata>\n<value>\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</value>\n</project_context>\n\n</memory_blocks>\n\n<tool_usage_rules>\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<tool_rule>\nmemory_replace requires continuing your response when called\n</tool_rule>\n<tool_rule>\nconversation_search requires continuing your response when called\n</tool_rule>\n<tool_rule>\nmemory_insert requires continuing your response when called\n</tool_rule>\n<tool_rule>\nsend_message ends your response (yields control) when called\n</tool_rule>\n</tool_usage_rules>\n\n<memory_metadata>\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</memory_metadata>"
"text": "You are a helpful assistant specializing in data analysis and mathematical computations.\n\n<memory_blocks>\nThe following memory blocks are currently engaged in your core memory unit:\n\n<project_context>\n<description>\n\n</description>\n<metadata>\n- chars_current=210\n- chars_limit=6000\n</metadata>\n<value>\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</value>\n</project_context>\n\n<human>\n<description>\nThe human block: Stores key details about the person you are conversing with, allowing for more personalized and friend-like conversation.\n</description>\n<metadata>\n- chars_current=175\n- chars_limit=4000\n</metadata>\n<value>\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</value>\n</human>\n\n<persona>\n<description>\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</description>\n<metadata>\n- chars_current=195\n- chars_limit=8000\n</metadata>\n<value>\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</value>\n</persona>\n\n</memory_blocks>\n\n<tool_usage_rules>\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<tool_rule>\nmemory_insert requires continuing your response when called\n</tool_rule>\n<tool_rule>\nmemory_replace requires continuing your response when called\n</tool_rule>\n<tool_rule>\nconversation_search requires continuing your response when called\n</tool_rule>\n<tool_rule>\nsend_message ends your response (yields control) when called\n</tool_rule>\n</tool_usage_rules>\n\n<memory_metadata>\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</memory_metadata>",
"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"
}