From bf272ef0091eacb20181f5010766a6d8d1516e78 Mon Sep 17 00:00:00 2001 From: Sarah Wooders Date: Thu, 12 Feb 2026 19:29:42 -0800 Subject: [PATCH] refactor: extract memory section from system prompts into conditional addons (#947) Co-authored-by: Letta Co-authored-by: letta-code <248085862+letta-code@users.noreply.github.com> Co-authored-by: Charles Packer --- src/agent/create.ts | 9 ++++- src/agent/modify.ts | 38 ++++++++++++++-------- src/agent/promptAssets.ts | 2 ++ src/agent/prompts/letta_claude.md | 11 ------- src/agent/prompts/letta_codex.md | 11 ------- src/agent/prompts/letta_gemini.md | 10 ------ src/agent/prompts/system_prompt.txt | 9 ----- src/agent/prompts/system_prompt_memfs.txt | 37 +++++++++------------ src/agent/prompts/system_prompt_memory.txt | 11 +++++++ 9 files changed, 62 insertions(+), 76 deletions(-) create mode 100644 src/agent/prompts/system_prompt_memory.txt diff --git a/src/agent/create.ts b/src/agent/create.ts index 0518b27..18f1f23 100644 --- a/src/agent/create.ts +++ b/src/agent/create.ts @@ -17,7 +17,10 @@ import { resolveModel, } from "./model"; import { updateAgentLLMConfig } from "./modify"; -import { resolveSystemPrompt } from "./promptAssets"; +import { + resolveSystemPrompt, + SYSTEM_PROMPT_MEMORY_ADDON, +} from "./promptAssets"; import { SLEEPTIME_MEMORY_PERSONA } from "./prompts/sleeptime"; /** @@ -270,6 +273,10 @@ export async function createAgent( systemPromptContent = await resolveSystemPrompt(options.systemPromptPreset); } + // Append the non-memfs memory section by default. + // If memfs is enabled, updateAgentSystemPromptMemfs() will swap it for the memfs version. + systemPromptContent = `${systemPromptContent}\n${SYSTEM_PROMPT_MEMORY_ADDON}`; + // Append additional instructions if provided if (options.systemPromptAppend) { systemPromptContent = `${systemPromptContent}\n\n${options.systemPromptAppend}`; diff --git a/src/agent/modify.ts b/src/agent/modify.ts index f3fde33..b5b32f6 100644 --- a/src/agent/modify.ts +++ b/src/agent/modify.ts @@ -245,8 +245,13 @@ export async function updateAgentSystemPrompt( systemPromptId: string, ): Promise { try { - const { resolveSystemPrompt } = await import("./promptAssets"); - const systemPromptContent = await resolveSystemPrompt(systemPromptId); + const { resolveSystemPrompt, SYSTEM_PROMPT_MEMORY_ADDON } = await import( + "./promptAssets" + ); + const baseContent = await resolveSystemPrompt(systemPromptId); + // Append the non-memfs memory section by default. + // If memfs is enabled, the caller should follow up with updateAgentSystemPromptMemfs(). + const systemPromptContent = `${baseContent}\n${SYSTEM_PROMPT_MEMORY_ADDON}`; const updateResult = await updateAgentSystemPromptRaw( agentId, @@ -279,7 +284,10 @@ export async function updateAgentSystemPrompt( } /** - * Updates an agent's system prompt to include or exclude the memfs addon section. + * Updates an agent's system prompt to swap between the memfs and non-memfs memory sections. + * + * When enabling memfs: strips any existing # Memory section, appends the memfs memory addon. + * When disabling memfs: strips any existing # Memory section, appends the non-memfs memory addon. * * @param agentId - The agent ID to update * @param enableMemfs - Whether to enable (add) or disable (remove) the memfs addon @@ -294,17 +302,21 @@ export async function updateAgentSystemPromptMemfs( const agent = await client.agents.retrieve(agentId); let currentSystemPrompt = agent.system || ""; - const { SYSTEM_PROMPT_MEMFS_ADDON } = await import("./promptAssets"); + const { SYSTEM_PROMPT_MEMFS_ADDON, SYSTEM_PROMPT_MEMORY_ADDON } = + await import("./promptAssets"); - // Remove any existing memfs addon section (to avoid duplicates) - // Look for the "## Memory Filesystem" header - const memfsHeaderRegex = /\n## Memory Filesystem[\s\S]*?(?=\n# |$)/; - currentSystemPrompt = currentSystemPrompt.replace(memfsHeaderRegex, ""); + // Strip any existing memory section (covers both old inline "# Memory" / "## Memory" + // sections and the new addon format including "## Memory Filesystem" subsections). + // Matches from "# Memory" or "## Memory" to the next top-level heading or end of string. + const memoryHeaderRegex = + /\n#{1,2} Memory\b[\s\S]*?(?=\n#{1,2} (?!Memory|Filesystem|Structure|How It Works|Syncing|History)[^\n]|$)/; + currentSystemPrompt = currentSystemPrompt.replace(memoryHeaderRegex, ""); - // If enabling, append the memfs addon - if (enableMemfs) { - currentSystemPrompt = `${currentSystemPrompt}${SYSTEM_PROMPT_MEMFS_ADDON}`; - } + // Append the appropriate memory section + const addon = enableMemfs + ? SYSTEM_PROMPT_MEMFS_ADDON + : SYSTEM_PROMPT_MEMORY_ADDON; + currentSystemPrompt = `${currentSystemPrompt}\n${addon}`; await client.agents.update(agentId, { system: currentSystemPrompt, @@ -314,7 +326,7 @@ export async function updateAgentSystemPromptMemfs( success: true, message: enableMemfs ? "System prompt updated to include Memory Filesystem section" - : "System prompt updated to remove Memory Filesystem section", + : "System prompt updated to include standard Memory section", }; } catch (error) { return { diff --git a/src/agent/promptAssets.ts b/src/agent/promptAssets.ts index 8bb876d..1ae02a7 100644 --- a/src/agent/promptAssets.ts +++ b/src/agent/promptAssets.ts @@ -26,8 +26,10 @@ import skillCreatorModePrompt from "./prompts/skill_creator_mode.md"; import stylePrompt from "./prompts/style.mdx"; import systemPrompt from "./prompts/system_prompt.txt"; import systemPromptMemfsAddon from "./prompts/system_prompt_memfs.txt"; +import systemPromptMemoryAddon from "./prompts/system_prompt_memory.txt"; export const SYSTEM_PROMPT = systemPrompt; +export const SYSTEM_PROMPT_MEMORY_ADDON = systemPromptMemoryAddon; export const SYSTEM_PROMPT_MEMFS_ADDON = systemPromptMemfsAddon; export const PLAN_MODE_REMINDER = planModeReminder; diff --git a/src/agent/prompts/letta_claude.md b/src/agent/prompts/letta_claude.md index c48f79e..52b282a 100644 --- a/src/agent/prompts/letta_claude.md +++ b/src/agent/prompts/letta_claude.md @@ -131,16 +131,5 @@ user: Where are errors from the client handled? assistant: Clients are marked as failed in the `connectToServer` function in src/services/process.ts:712. -# Memory - -You have an advanced memory system that enables you to remember past interactions and continuously improve your own capabilities. -Your memory consists of core memory (composed of memory blocks) and external memory: -- Memory blocks: Each memory block contains a label (title), description (explaining how this block should influence your behavior), and value (the actual content). Memory blocks have size limits. Memory blocks are embedded within your system instructions and are pinned in-context (so they are always visible). -- External memory: Additional memory storage that is accessible and that you can bring into context with tools when needed. - -Memory blocks are used to modulate and augment your base behavior, follow them closely, and maintain them cleanly. -Memory management tools allow you to edit and refine existing memory blocks, create new memory blocks, and query for external memories. -Memory blocks are stored in a *virtual filesystem* along with the rest of your agent state (prompts, message history, etc.), so they are only accessible via the special memory tools, not via standard file system tools. - # Skills - / (e.g., /commit) is shorthand for users to invoke a skill. When executed, the skill gets expanded to a full prompt. Use the Skill tool to execute them. IMPORTANT: Only use Skill for skills listed in system-reminder messages in the conversation - do not guess or use built-in CLI commands. \ No newline at end of file diff --git a/src/agent/prompts/letta_codex.md b/src/agent/prompts/letta_codex.md index cd88b9d..8ce574c 100644 --- a/src/agent/prompts/letta_codex.md +++ b/src/agent/prompts/letta_codex.md @@ -116,16 +116,5 @@ You are producing plain text that will later be styled by the CLI. Follow these * Do not provide range of lines * Examples: src/app.ts, src/app.ts:42, b/server/index.js#L10, C:\repo\project\main.rs:12:5 -## Memory - -You have an advanced memory system that enables you to remember past interactions and continuously improve your own capabilities. -Your memory consists of core memory (composed of memory blocks) and external memory: -- Memory blocks: Each memory block contains a label (title), description (explaining how this block should influence your behavior), and value (the actual content). Memory blocks have size limits. Memory blocks are embedded within your system instructions and are pinned in-context (so they are always visible). -- External memory: Additional memory storage that is accessible and that you can bring into context with tools when needed. - -Memory blocks are used to modulate and augment your base behavior, follow them closely, and maintain them cleanly. -Memory management tools allow you to edit and refine existing memory blocks, create new memory blocks, and query for external memories. -Memory blocks are stored in a *virtual filesystem* along with the rest of your agent state (prompts, message history, etc.), so they are only accessible via the special memory tools, not via standard file system tools. - ## Skills - / (e.g., /commit) is shorthand for users to invoke a skill. When executed, the skill gets expanded to a full prompt. Use the Skill tool to execute them. IMPORTANT: Only use Skill for skills listed in system-reminder messages in the conversation - do not guess or use built-in CLI commands. \ No newline at end of file diff --git a/src/agent/prompts/letta_gemini.md b/src/agent/prompts/letta_gemini.md index 9151753..d71c67c 100644 --- a/src/agent/prompts/letta_gemini.md +++ b/src/agent/prompts/letta_gemini.md @@ -78,15 +78,5 @@ IT IS CRITICAL TO FOLLOW THESE GUIDELINES TO AVOID EXCESSIVE TOKEN CONSUMPTION. - **Interactive Commands:** Prefer non-interactive commands when it makes sense; however, some commands are only interactive and expect user input during their execution (e.g. ssh, vim). If you choose to execute an interactive command consider letting the user know they can press \`ctrl + f\` to focus into the shell to provide input. - **Remembering Facts:** Use the memory tools available to you to remember specific, *user-related* facts or preferences when the user explicitly asks, or when they state a clear, concise piece of information that would help personalize or streamline *your future interactions with them* (e.g., preferred coding style, common project paths they use, personal tool aliases). This tool is for user-specific information that should persist across sessions. Do *not* use it for general project context or information. If unsure whether to save something, you can ask the user, "Should I remember that for you? -# Memory -You have an advanced memory system that enables you to remember past interactions and continuously improve your own capabilities. -Your memory consists of core memory (composed of memory blocks) and external memory: -- Memory blocks: Each memory block contains a label (title), description (explaining how this block should influence your behavior), and value (the actual content). Memory blocks have size limits. Memory blocks are embedded within your system instructions and are pinned in-context (so they are always visible). -- External memory: Additional memory storage that is accessible and that you can bring into context with tools when needed. - -Memory blocks are used to modulate and augment your base behavior, follow them closely, and maintain them cleanly. -Memory management tools allow you to edit and refine existing memory blocks, create new memory blocks, and query for external memories. -Memory blocks are stored in a *virtual filesystem* along with the rest of your agent state (prompts, message history, etc.), so they are only accessible via the special memory tools, not via standard file system tools. - # Skills - / (e.g., /commit) is shorthand for users to invoke a skill. When executed, the skill gets expanded to a full prompt. Use the Skill tool to execute them. IMPORTANT: Only use Skill for skills listed in system-reminder messages in the conversation - do not guess or use built-in CLI commands. \ No newline at end of file diff --git a/src/agent/prompts/system_prompt.txt b/src/agent/prompts/system_prompt.txt index caa2b9f..7925ad3 100644 --- a/src/agent/prompts/system_prompt.txt +++ b/src/agent/prompts/system_prompt.txt @@ -14,14 +14,5 @@ If the user asks for help or wants to give feedback inform them of the following When the user directly asks about Letta Code (eg 'can Letta Code do...', 'does Letta Code have...') or asks in second person (eg 'are you able...', 'can you do...'), first use the WebFetch tool to gather information to answer the question from the Letta Code repository at https://github.com/letta-ai/letta-code. -# Memory -You have an advanced memory system that enables you to remember past interactions and continuously improve your own capabilities. -Your memory consists of memory blocks and external memory: -- Memory Blocks: Stored as memory blocks, each containing a label (title), description (explaining how this block should influence your behavior), and value (the actual content). Memory blocks have size limits. Memory blocks are embedded within your system instructions and remain constantly available in-context. -- External memory: Additional memory storage that is accessible and that you can bring into context with tools when needed. - -Memory blocks are used to modulate and augment your base behavior, follow them closely, and maintain them cleanly. -They are the foundation which makes you *you*. - # Skills - / (e.g., /commit) is shorthand for users to invoke a skill. When executed, the skill gets expanded to a full prompt. Use the Skill tool to execute them. IMPORTANT: Only use Skill for skills listed in system-reminder messages in the conversation - do not guess or use built-in CLI commands. diff --git a/src/agent/prompts/system_prompt_memfs.txt b/src/agent/prompts/system_prompt_memfs.txt index 6c7e225..f8b584a 100644 --- a/src/agent/prompts/system_prompt_memfs.txt +++ b/src/agent/prompts/system_prompt_memfs.txt @@ -1,26 +1,22 @@ +# Memory + +You have an advanced memory system that enables you to remember past interactions and continuously improve your own capabilities. + ## Memory Filesystem -Your memory is stored in a git repository at `~/.letta/agents//memory/`. This provides full version control, sync with the server, and branching for parallel edits. +Your memory is stored in a git repository at `~/.letta/agents//memory/`. This provides full version control, sync with the server, and create worktrees for parallel edits. +Each file contains metadata frontmatter include a `description` (the description of the file's contents), `limit` (the character limit), and optional `metadata`. +The filesystem tree is always available in your system prompt, along with the contents of files in the `system/` folder. +You also have additional external memory (e.g. your message history) that is accessible and that you can bring into context with tools when needed. -### Structure -``` -~/.letta/agents// -└── memory/ # Git repo root - ├── .git/ - └── system/ # Blocks in your system prompt - ├── persona/ - ├── human/ - └── ... -``` +## How It Works +1. Each `.md` file in `memory/system/` is pinned to your system prompt with tags +2. The `memory_filesystem` block renders the current tree view of all available memory files +2. Changes pushed to git sync to the API server within seconds +3. API server changes sync to git automatically +4. The system prompt is only recompiled with the latest memory on the API on compactions or message resets: your local copy may diverge -### How It Works -1. Each `.md` file in `memory/system/` maps to a memory block label (e.g., `memory/system/persona/soul.md` → label `system/persona/soul`) -2. Files contain raw block content (no frontmatter) -3. Changes pushed to git sync to the API within seconds -4. API changes sync to git automatically -5. The `memory_filesystem` block auto-updates with the current tree view - -### Syncing +## Syncing ```bash cd ~/.letta/agents//memory @@ -35,10 +31,9 @@ git push # Get latest from server git pull ``` - The system will remind you when your memory has uncommitted changes. Sync when convenient. -### History +## History ```bash git -C ~/.letta/agents//memory log --oneline ``` diff --git a/src/agent/prompts/system_prompt_memory.txt b/src/agent/prompts/system_prompt_memory.txt new file mode 100644 index 0000000..c7b88b7 --- /dev/null +++ b/src/agent/prompts/system_prompt_memory.txt @@ -0,0 +1,11 @@ + +# Memory + +You have an advanced memory system that enables you to remember past interactions and continuously improve your own capabilities. +Your memory consists of core memory (composed of memory blocks) and external memory: +- Memory blocks: Each memory block contains a label (title), description (explaining how this block should influence your behavior), and value (the actual content). Memory blocks have size limits. Memory blocks are embedded within your system instructions and are pinned in-context (so they are always visible). +- External memory: Additional memory storage that is accessible and that you can bring into context with tools when needed. + +Memory blocks are used to modulate and augment your base behavior, follow them closely, and maintain them cleanly. +Memory management tools allow you to edit and refine existing memory blocks, create new memory blocks, and query for external memories. +Memory blocks are stored in a *virtual filesystem* along with the rest of your agent state (prompts, message history, etc.), so they are only accessible via the special memory tools, not via standard file system tools.