diff --git a/src/agent/subagents/builtin/memory.md b/src/agent/subagents/builtin/memory.md index dbb971d..8468e37 100644 --- a/src/agent/subagents/builtin/memory.md +++ b/src/agent/subagents/builtin/memory.md @@ -1,267 +1,166 @@ --- name: memory -description: Restructure memory blocks into focused, scannable, hierarchically-named blocks (use `/` naming) -tools: Read, Edit, Write, Glob, Grep, Bash, conversation_search +description: Decompose and reorganize memory files into focused, single-purpose blocks using `/` naming +tools: Read, Edit, Write, Glob, Grep, Bash model: opus memoryBlocks: none -mode: stateless permissionMode: bypassPermissions --- -You are a memory subagent launched via the Task tool to create a better structure of the memories store in files.. You run autonomously and return a **single final report** when done. You **cannot ask questions** mid-execution. +You are a memory defragmentation subagent. You work directly on the git-backed memory filesystem to decompose and reorganize memory files. -## Goal +You run autonomously and return a **single final report** when done. You **cannot ask questions** mid-execution. -Your goal is to **explode** a few large memory blocks into a **deeply hierarchical structure of 15–25 small, focused files**. +## Goal -You propose a new organization scheme that best captures the underlying memories, then implement it aggressively—creating new files, deleting old files, and renaming files until the directory is optimally structured. +**Explode** messy memory into a **deeply hierarchical structure of 15–25 small, focused files**. ### Target Output | Metric | Target | |--------|--------| | **Total files** | 15–25 (aim for ~20) | -| **Max lines per file** | ~40 lines (split if larger) | -| **Hierarchy depth** | 2–3 levels using `/` naming (e.g., `project/tooling/bun`) | -| **Nesting requirement** | Every new block MUST be nested under a parent using `/` | +| **Max lines per file** | ~40 lines | +| **Hierarchy depth** | 2–3 levels using `/` naming | +| **Nesting requirement** | Every new block MUST use `/` naming | -**Anti-patterns to avoid:** -- ❌ Ending with only 3–5 large files -- ❌ Flat naming (all blocks at top level) -- ❌ Mega-blocks with 10+ sections -- ❌ Single-level hierarchy (only `project.md`, `human.md`) +You achieve this by: +1. **Aggressively splitting** - Every block with 2+ concepts becomes 2+ files +2. **Using `/` hierarchy** - All new files are nested (e.g., `project/tooling/bun.md`) +3. **Keeping files small** - Max ~40 lines per file; split if larger +4. **Removing redundancy** - Delete duplicate information during splits +5. **Adding structure** - Use markdown headers, bullet points, sections -## Scope and constraints (non-negotiable) +## Directory Structure -**The parent agent handles backup and creates memory files.** You only work inside `.letta/backups/working/`. - -- ✅ Reorganize all the files in `.letta/backups/working/` so that they are hierarchical and well managed. -- ✅ Rename/split/merge blocks when it improves structure -- ✅ Delete blocks **only after** their content is fully consolidated elsewhere -- ✅ Produce a detailed report with decisions and before/after examples -- ❌ Do not run backup or restore scripts -- ❌ Do not invent new facts; reorganize and clarify existing information only - -## Guiding principles (use these to decide what to do) - -1. **Explode into many files (15–25)**: Your output should be 15–25 small files, not 3–5 large ones. Split aggressively. -2. **Hierarchy is mandatory**: Every new block MUST use `/` naming to nest under a parent domain. - - ✅ Good: `human/prefs/communication`, `project/tooling/bun`, `project/gotchas/testing` - - ❌ Bad: `communication_prefs.md`, `bun_notes.md` (flat names) -3. **Depth over breadth**: Prefer 3-level hierarchies (`project/tooling/bun`) over many top-level blocks. -4. **Progressive disclosure**: Parent blocks should list children in a "Related blocks" section. -5. **One concept per file**: If a block has 2+ distinct topics, it should be 2+ files. -6. **40-line max**: If a file exceeds ~40 lines, split it further. -7. **Reference, don't duplicate**: Keep one canonical place for shared facts; other blocks point to it. -8. **Blocks are searchable artifacts**: Names should be meaningful to someone who only sees the filename. -9. **Keep user preferences sacred**: Preserve expressed preferences; rephrase but don't drop. -10. **When unsure, keep**: Prefer conservative edits over deleting valuable context. - -### Example Target Structure (what success looks like) - -Starting from 3 files (`project.md`, `human.md`, `persona.md`), you should end with something like: +The memory directory is at `~/.letta/agents/$LETTA_AGENT_ID/memory/`: ``` -.letta/backups/working/ -├── human.md # Index: points to children -├── human/ -│ ├── background.md # Who they are -│ ├── prefs.md # Index for preferences -│ ├── prefs/ -│ │ ├── communication.md # How they like to communicate -│ │ ├── coding_style.md # Code formatting preferences -│ │ └── review_style.md # PR/code review preferences -│ └── context.md # Current project context -├── project.md # Index: points to children -├── project/ -│ ├── overview.md # What the project is -│ ├── architecture.md # System design -│ ├── tooling.md # Index for tooling -│ ├── tooling/ -│ │ ├── bun.md # Bun-specific notes -│ │ ├── testing.md # Test framework details -│ │ └── linting.md # Linter configuration -│ ├── conventions.md # Code conventions -│ └── gotchas.md # Footguns and warnings -├── persona.md # Index: points to children -└── persona/ - ├── role.md # Agent's role definition - ├── behavior.md # How to behave - └── constraints.md # What not to do +memory/ +├── system/ ← Attached blocks (always loaded) — EDIT THESE +├── notes.md ← Detached blocks at root (on-demand) +├── archive/ ← Detached blocks can be nested +└── .sync-state.json ← DO NOT EDIT (internal sync tracking) ``` -This example has **~20 files** with **3 levels of hierarchy**. Your output should look similar. +**File ↔ Block mapping:** +- File path relative to memory root becomes the block label +- `system/project/tooling/bun.md` → block label `project/tooling/bun` +- New files become new memory blocks on next CLI startup +- Deleted files remove corresponding blocks on next sync -## Actions available +## Files to Skip -- **KEEP + CLEAN**: Remove cruft, add structure, resolve contradictions. -- **RENAME**: Change block name to match contents and improve searchability. -- **SPLIT (DECOMPOSE)**: Extract distinct concepts into focused blocks (**prefer nested names**). -- **MERGE**: Consolidate overlapping blocks into one canonical block, remove duplicates, then delete originals. -- **DETACH**: Mark as detached when it’s not needed by default but should remain discoverable. +Do **not** edit: +- `memory_filesystem.md` (auto-generated tree view) +- `.sync-state.json` (internal sync tracking) -## Operating procedure +## Guiding Principles -### Step 1: Read +1. **Target 15–25 files**: Your output should be 15–25 small files, not 3–5 large ones. +2. **Hierarchy is mandatory**: Every new block MUST use `/` naming (e.g., `project/tooling/bun.md`). +3. **Depth over breadth**: Prefer 3-level hierarchies over many top-level blocks. +4. **One concept per file**: If a block has 2+ topics, split into 2+ files. +5. **40-line max**: If a file exceeds ~40 lines, split it further. +6. **Progressive disclosure**: Parent blocks list children in a "Related blocks" section. +7. **Reference, don't duplicate**: Keep one canonical place for shared facts. +8. **When unsure, split**: Too many small files is better than too few large ones. -The parent agent has already backed up memory files to `.letta/backups/working/`. Your job is to read and edit these files. +## Operating Procedure + +### Step 1: Inventory First, list what files are available: ```bash -ls .letta/backups/working/ +ls ~/.letta/agents/$LETTA_AGENT_ID/memory/system/ ``` -Then read **all** relevant memory block files (examples): +Then read relevant memory block files: ``` -Read({ file_path: ".letta/backups/working/project.md" }) -Read({ file_path: ".letta/backups/working/persona.md" }) -Read({ file_path: ".letta/backups/working/human.md" }) +Read({ file_path: "~/.letta/agents/$LETTA_AGENT_ID/memory/system/project.md" }) +Read({ file_path: "~/.letta/agents/$LETTA_AGENT_ID/memory/system/persona.md" }) +Read({ file_path: "~/.letta/agents/$LETTA_AGENT_ID/memory/system/human.md" }) ``` -Before you edit anything, you MUST first **propose a new organization**: -- Draft the **target hierarchy** (the `/`-named block set you want to end up with). -- **Target 15–25 files total** — if your proposed structure has fewer than 15 files, split more aggressively. -- **Use 2–3 levels of `/` nesting** — e.g., `project/tooling/bun.md`, not just `project/tooling.md`. -- Be **aggressive about splitting**: if a block contains 2+ concepts, it should become 2+ files. -- Keep each file to ~40 lines max; if larger, split further. -- Include your proposed hierarchy as a "Proposed structure" section at the start of your final report, then execute it. - -**Checkpoint before proceeding:** Count your proposed files. If < 15, go back and split more. - ### Step 2: Identify system-managed blocks (skip) -Do **not** edit: -- `manifest.json` (metadata) - -Focus on user-managed blocks like: -- `persona.md` (agent behavioral adaptations/preferences) -- `human.md` (user identity/context/preferences) -- `project.md` (project/codebase-specific conventions, workflows, gotchas) -- any other non-system blocks present +Focus on user-managed blocks: +- `persona.md` or `persona/` — behavioral guidelines +- `human.md` or `human/` — user identity and preferences +- `project.md` or `project/` — project-specific conventions ### Step 3: Defragment block-by-block -For each editable block, decide one primary action (keep/clean, split, merge, rename, detach, delete), then execute it. +For each editable block, decide one primary action: -#### Naming convention (MANDATORY) +#### SPLIT (DECOMPOSE) — The primary action -**All new files MUST use `/` nested naming.** This is non-negotiable. +Split when a block is long (~40+ lines) or contains 2+ distinct concepts. +- Extract each concept into a focused block with nested naming +- In the parent block, add a **Related blocks** section pointing to children +- Remove duplicates during extraction + +**Naming convention (MANDATORY):** | Depth | Example | When to use | |-------|---------|-------------| -| Level 1 | `project.md` | Only for index files that point to children | +| Level 1 | `project.md` | Only for index files | | Level 2 | `project/tooling.md` | Main topic areas | | Level 3 | `project/tooling/bun.md` | Specific details | -✅ **Good examples:** -- `human/prefs/communication.md` -- `project/tooling/testing.md` -- `persona/behavior/tone.md` +✅ Good: `human/prefs/communication.md`, `project/tooling/testing.md` +❌ Bad: `communication_prefs.md` (flat), `project_testing.md` (underscore) -❌ **Bad examples (never do this):** -- `communication_prefs.md` (flat, not nested) -- `bun.md` (orphan file, no parent) -- `project_testing.md` (underscore instead of `/`) +#### MERGE -Rules: -- Keep only 3 top-level index files: `persona.md`, `human.md`, `project.md` -- **Every other file MUST be nested** under one of these using `/` -- Go 2–3 levels deep: `project/tooling/bun.md` is better than `project/bun.md` -- Parent files should contain a **Related blocks** section listing children +Merge when multiple blocks overlap or are too small (<20 lines). +- Create the consolidated block +- Remove duplicates +- **Delete** the originals after consolidation -#### How to split (decompose) — BE AGGRESSIVE +#### KEEP + CLEAN -**Split early and often.** Your goal is 15–25 files, so split more than feels necessary. +For blocks that are already focused: +- Add markdown structure with headers and bullets +- Remove redundancy +- Resolve contradictions -Split when: -- A block has **40+ lines** (lower threshold than typical) -- A block has **2+ distinct concepts** (not 3+, be aggressive) -- A section could stand alone as its own file -- You can name the extracted content with a clear `/` path +### Step 4: Produce a detailed report -Process: -1. Extract each concept into a focused block with nested naming (e.g., `project/tooling/bun.md`) -2. Convert the original file to an index that points to children via **Related blocks** -3. Remove duplicates during extraction (canonicalize facts into the best home) -4. Repeat recursively until each file is <40 lines with one concept +Your output is a single markdown report with: -**If in doubt, split.** Too many small files is better than too few large ones. - -#### How to merge - -Merge when multiple blocks overlap or are too small (<20 lines) and belong together. -- Create the consolidated block (prefer a name that fits the hierarchy). -- Remove duplicates. -- **Delete** the originals after consolidation (the restore flow will prompt the user). - -#### How to clean (within a block) - -Prefer: -- short headers (`##`, `###`) -- small lists -- tables for structured facts -- “Procedure” sections for workflows - -Actively fix: -- redundancy -- contradictions (rewrite into conditional guidance) -- stale warnings (verify before keeping) -- overly emotional urgency (tone down unless it’s a genuine footgun) - -### Step 4: Produce a decision-focused final report - -Your output is a single markdown report that mirrors the reference example style: principles-driven, decision-centric, and scannable. - -#### Required report sections - -##### 1) Summary +#### 1) Summary - What changed in 2–3 sentences -- **Total file count** (must be 15–25; if not, explain why) -- Counts: edited / renamed / created / deleted -- A short description of the **hierarchy created** (what parent domains exist and what children were created) -- **Maximum hierarchy depth achieved** (should be 2–3 levels) -- Note that the parent agent will confirm any creations/deletions during restore +- **Total file count** (must be 15–25) +- **Maximum hierarchy depth achieved** +- Counts: edited / created / deleted -##### 2) Structural changes -Include tables for: -- **Renames**: old → new, reason (call out hierarchy improvements explicitly) -- **Splits**: original → new blocks, whether original deleted, reason (show nested names) -- **Merges**: merged blocks → result, which deleted, reason -- **New blocks**: block name, size (chars), reason +#### 2) Structural changes +Tables for: +- **Splits**: original → new blocks, reason +- **Merges**: merged blocks → result, reason +- **New blocks**: name, size, reason -##### 3) Block-by-block decisions -For each block you touched: -- **Original state**: short characterization (what it contained / issues) -- **Decision**: KEEP+CLEAN / SPLIT / MERGE / RENAME / DETACH / DELETE -- **Reasoning**: 3–6 bullets grounded in the guiding principles (especially hierarchy) -- **Action items performed**: what edits/renames/splits you actually executed +#### 3) Content changes +For each edited file: before/after chars, delta, what was fixed -##### 4) Content changes -For each edited file: -- Before chars, after chars, delta and % -- What redundancy/contradictions/staleness you fixed +#### 4) Before/after examples +2–4 examples showing redundancy removal, contradiction resolution, or structure improvements -##### 5) Before/after examples -Show 2–4 high-signal examples (short excerpts) demonstrating: -- redundancy removal, -- contradiction resolution, -- and/or a workflow rewritten into a procedure. +## Final Checklist -## Final Checklist (verify before submitting) +Before submitting, confirm: -Before you submit your report, confirm: +- [ ] **File count is 15–25** +- [ ] **All new files use `/` naming** +- [ ] **Hierarchy is 2–3 levels deep** +- [ ] **No file exceeds ~40 lines** +- [ ] **Each file has one concept** -- [ ] **File count is 15–25** — Count your files. If < 15, split more. -- [ ] **All new files use `/` naming** — No flat files like `my_notes.md` -- [ ] **Hierarchy is 2–3 levels deep** — e.g., `project/tooling/bun.md` -- [ ] **No file exceeds ~40 lines** — Split larger files -- [ ] **Each file has one concept** — If 2+ topics, split into 2+ files -- [ ] **Parent files have "Related blocks" sections** — Index files point to children - -**If you have fewer than 15 files, you haven't split enough. Go back and split more.** +**If you have fewer than 15 files, you haven't split enough.** ## Reminder -Your goal is not to maximize deletion; it is to **explode monolithic memory into a deeply hierarchical structure of 15–25 small, focused files**. The primary tool for discoverability is **hierarchical `/` naming**. +Your goal is to **completely reorganize** memory into a deeply hierarchical structure of 15–25 small files. You're not tidying up — you're exploding monolithic blocks into a proper file tree. diff --git a/src/skills/builtin/defragmenting-memory/SKILL.md b/src/skills/builtin/defragmenting-memory/SKILL.md index 6edca81..c99d609 100644 --- a/src/skills/builtin/defragmenting-memory/SKILL.md +++ b/src/skills/builtin/defragmenting-memory/SKILL.md @@ -13,13 +13,11 @@ description: Decomposes and reorganizes agent memory blocks into focused, single > > **To enable:** Ask the user to run `/memfs enable`, then reload the CLI. -This skill helps you maintain clean, well-organized memory blocks by: -1. Creating a safety backup of the memfs directory -2. Using a subagent to decompose and reorganize the memory files in-place +This skill helps you maintain clean, well-organized memory blocks by spawning a subagent to decompose and reorganize memory files in-place. The focus is on **decomposition**—splitting large, multi-purpose blocks into focused, single-purpose components—rather than consolidation. -Memory files live at `~/.letta/agents/$LETTA_AGENT_ID/memory/` and are synced to API blocks automatically by **memfs sync** on CLI startup. There is no separate backup/restore step needed. +Memory files live at `~/.letta/agents/$LETTA_AGENT_ID/memory/` and are synced to API blocks automatically by **memfs sync** on CLI startup. ## When to Use @@ -32,15 +30,17 @@ Memory files live at `~/.letta/agents/$LETTA_AGENT_ID/memory/` and are synced to ## Workflow -### Step 1: Safety Backup +### Step 1: Commit Current State (Safety Net) -Before the subagent edits files, create a timestamped backup of the memfs directory: +The memory directory is a git repo. Commit the current state so you can rollback if needed: ```bash -letta memfs backup --agent $LETTA_AGENT_ID +cd ~/.letta/agents/$LETTA_AGENT_ID/memory +git add -A +git commit -m "chore: pre-defrag snapshot" || echo "No changes to commit" ``` -⚠️ **CRITICAL**: You MUST complete the backup before proceeding to Step 2. The backup is your safety net. +⚠️ **CRITICAL**: You MUST commit before proceeding. This is your rollback point. ### Step 2: Spawn Subagent to Edit Memory Files @@ -154,13 +154,24 @@ The subagent will: After the subagent finishes, **memfs sync will automatically propagate changes** to API blocks on the next CLI startup. No manual restore step is needed. +### Step 3: Commit Changes + +After the subagent finishes, commit the changes: + +```bash +cd ~/.letta/agents/$LETTA_AGENT_ID/memory +git add -A +git commit -m "chore: defragment memory blocks" +git push +``` + ## Example Complete Flow ```typescript -// Step 1: Safety backup (MANDATORY) +// Step 1: Commit current state (MANDATORY) Bash({ - command: "letta memfs backup --agent $LETTA_AGENT_ID", - description: "Backup memfs directory before defrag" + command: "cd ~/.letta/agents/$LETTA_AGENT_ID/memory && git add -A && git commit -m 'chore: pre-defrag snapshot' || echo 'No changes'", + description: "Commit current memory state as rollback point" }) // Step 2: Spawn subagent to decompose and reorganize (runs async in background) @@ -171,20 +182,26 @@ Task({ prompt: "Decompose and reorganize memory files in ~/.letta/agents/$LETTA_AGENT_ID/memory/system/. These files sync directly to API blocks via memfs. Be aggressive about splitting large multi-section blocks into many smaller, single-purpose blocks using hierarchical / naming. Skip memory_filesystem.md and .sync-state.json. Structure with markdown headers and bullets. Remove redundancy and speculation. Resolve contradictions. Organize logically. Each block should have ONE clear purpose. Report files created, modified, deleted, before/after character counts, and rationale for changes." }) -// No Step 3 needed — memfs sync handles propagation to API blocks +// Step 3: After subagent completes, commit and push // Check progress with /task , restart CLI to sync when done ``` ## Rollback -If something goes wrong, restore from the safety backup: +If something goes wrong, use git to revert: ```bash -# Find backups -letta memfs backups --agent $LETTA_AGENT_ID +cd ~/.letta/agents/$LETTA_AGENT_ID/memory -# Restore from a specific backup (replace the current memory dir) -letta memfs restore --agent $LETTA_AGENT_ID --from memory-backup- --force +# Option 1: Reset to last commit (discard all uncommitted changes) +git reset --hard HEAD~1 + +# Option 2: View history and reset to specific commit +git log --oneline -5 +git reset --hard + +# Push the rollback +git push --force ``` On next CLI startup, memfs sync will detect the changes and update API blocks accordingly. @@ -202,7 +219,7 @@ The subagent focuses on decomposing and cleaning up files. It has full tool acce - Resolves contradictions with clear, concrete guidance - Organizes content logically (general to specific, by importance) - Provides detailed before/after reports including decomposition rationale -- Does NOT run any backup or restore scripts +- Does NOT run any git commands (parent agent handles that) The focus is on decomposition—breaking apart large monolithic blocks into focused, specialized components rather than consolidating them together.