From 93e453ef8f939e097a9fbbf6b658722faf0600c9 Mon Sep 17 00:00:00 2001 From: Sarah Wooders Date: Thu, 5 Feb 2026 23:32:26 -0800 Subject: [PATCH] fix(core): transform nested block labels on git memory enable (#9339) Co-authored-by: Letta --- letta/server/server.py | 2 +- letta/services/block_manager_git.py | 14 ++++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/letta/server/server.py b/letta/server/server.py index ebe7f190..023694ff 100644 --- a/letta/server/server.py +++ b/letta/server/server.py @@ -658,7 +658,7 @@ class SyncServer(object): if request.memory_blocks: transformed_blocks = [] for block in request.memory_blocks: - if "/" not in block.label: + if not block.label.startswith("system/"): block = block.model_copy(update={"label": f"system/{block.label}"}) transformed_blocks.append(block) updates["memory_blocks"] = transformed_blocks diff --git a/letta/services/block_manager_git.py b/letta/services/block_manager_git.py index a5acf0d4..b1f4d161 100644 --- a/letta/services/block_manager_git.py +++ b/letta/services/block_manager_git.py @@ -369,9 +369,13 @@ class GitEnabledBlockManager(BlockManager): agent_id, ) blocks = await self.get_blocks_by_agent_async(agent_id, actor) - # Ensure blocks have path-based labels before creating repo + # Ensure blocks have path-based labels before creating repo. + # All existing blocks were rendered in the system prompt, so they + # need the system/ prefix. Check startswith (not "/" presence) + # because labels like "letta/letta_town" contain "/" but aren't + # yet in the system/ namespace. for block in blocks: - if "/" not in block.label: + if not block.label.startswith("system/"): old_label = block.label new_label = f"system/{block.label}" async with db_registry.async_session() as session: @@ -389,10 +393,12 @@ class GitEnabledBlockManager(BlockManager): return # Get current blocks for this agent and transform labels to path-based. - # Flat labels (e.g. "human") become "system/human" for the git directory structure. + # All existing blocks were in the system prompt, so they need the system/ prefix. + # Use startswith check (not "/" presence) because labels like "letta/letta_town" + # contain "/" but aren't yet in the system/ namespace. blocks = await self.get_blocks_by_agent_async(agent_id, actor) for block in blocks: - if "/" not in block.label: + if not block.label.startswith("system/"): old_label = block.label new_label = f"system/{block.label}" logger.info(f"Transforming block label '{old_label}' -> '{new_label}' for agent {agent_id}")