From 2504cb6a1bbc463f62fd30817f004ba629359968 Mon Sep 17 00:00:00 2001 From: Charles Packer Date: Thu, 17 Apr 2025 17:50:49 -0700 Subject: [PATCH] fix: add a check to prevent agents from writing the line number warning into memory (#1770) --- letta/constants.py | 5 +++++ letta/functions/function_sets/base.py | 13 +++++++++++++ letta/schemas/agent.py | 4 ++-- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/letta/constants.py b/letta/constants.py index 0c903e0a..57e85b1f 100644 --- a/letta/constants.py +++ b/letta/constants.py @@ -103,6 +103,11 @@ ERROR_MESSAGE_PREFIX = "Error" NON_USER_MSG_PREFIX = "[This is an automated system message hidden from the user] " +CORE_MEMORY_LINE_NUMBER_WARNING = ( + "# NOTE: Line numbers shown below are to help during editing. Do NOT include line number prefixes in your memory edit tool calls." +) + + # Constants to do with summarization / conversation length window # The max amount of tokens supported by the underlying model (eg 8k for gpt-4 and Mistral 7B) LLM_MAX_TOKENS = { diff --git a/letta/functions/function_sets/base.py b/letta/functions/function_sets/base.py index 0705a388..654675c9 100644 --- a/letta/functions/function_sets/base.py +++ b/letta/functions/function_sets/base.py @@ -1,6 +1,7 @@ from typing import Optional from letta.agent import Agent +from letta.constants import CORE_MEMORY_LINE_NUMBER_WARNING def send_message(self: "Agent", message: str) -> Optional[str]: @@ -219,6 +220,10 @@ def memory_replace(agent_state: "AgentState", label: str, old_str: str, new_str: raise ValueError( "old_str contains a line number prefix, which is not allowed. Do not include line numbers when calling memory tools (line numbers are for display purposes only)." ) + if CORE_MEMORY_LINE_NUMBER_WARNING in old_str: + raise ValueError( + "old_str contains a line number warning, which is not allowed. Do not include line number information when calling memory tools (line numbers are for display purposes only)." + ) if bool(re.search(r"\nLine \d+: ", new_str)): raise ValueError( "new_str contains a line number prefix, which is not allowed. Do not include line numbers when calling memory tools (line numbers are for display purposes only)." @@ -282,6 +287,10 @@ def memory_insert(agent_state: "AgentState", label: str, new_str: str, insert_li raise ValueError( "new_str contains a line number prefix, which is not allowed. Do not include line numbers when calling memory tools (line numbers are for display purposes only)." ) + if CORE_MEMORY_LINE_NUMBER_WARNING in new_str: + raise ValueError( + "new_str contains a line number warning, which is not allowed. Do not include line number information when calling memory tools (line numbers are for display purposes only)." + ) current_value = str(agent_state.memory.get_block(label).value).expandtabs() new_str = str(new_str).expandtabs() @@ -340,6 +349,10 @@ def memory_rethink(agent_state: "AgentState", label: str, new_memory: str) -> No raise ValueError( "new_memory contains a line number prefix, which is not allowed. Do not include line numbers when calling memory tools (line numbers are for display purposes only)." ) + if CORE_MEMORY_LINE_NUMBER_WARNING in new_memory: + raise ValueError( + "new_memory contains a line number warning, which is not allowed. Do not include line number information when calling memory tools (line numbers are for display purposes only)." + ) if agent_state.memory.get_block(label) is None: agent_state.memory.create_block(label=label, value=new_memory) diff --git a/letta/schemas/agent.py b/letta/schemas/agent.py index e5380406..6d30afcd 100644 --- a/letta/schemas/agent.py +++ b/letta/schemas/agent.py @@ -3,7 +3,7 @@ from typing import Dict, List, Optional from pydantic import BaseModel, Field, field_validator -from letta.constants import DEFAULT_EMBEDDING_CHUNK_SIZE +from letta.constants import CORE_MEMORY_LINE_NUMBER_WARNING, DEFAULT_EMBEDDING_CHUNK_SIZE from letta.helpers import ToolRulesSolver from letta.schemas.block import CreateBlock from letta.schemas.embedding_config import EmbeddingConfig @@ -284,7 +284,7 @@ def get_prompt_template_for_agent_type(agent_type: Optional[AgentType] = None): return ( "{% for block in blocks %}" '<{{ block.label }} characters="{{ block.value|length }}/{{ block.limit }}">\n' - "# NOTE: Line numbers shown below are to help during editing. Do NOT include line number prefixes in your memory edit tool calls." + f"{CORE_MEMORY_LINE_NUMBER_WARNING}" "{% for line in block.value.split('\\n') %}" "Line {{ loop.index }}: {{ line }}\n" "{% endfor %}"