refactor: make memory subagent self-contained, eliminate defrag skill (#1180)

This commit is contained in:
Devansh Jain
2026-02-26 22:01:55 -08:00
committed by GitHub
parent 1ed619663a
commit 2fcd9bc6ce
2 changed files with 167 additions and 266 deletions

View File

@@ -1,7 +1,7 @@
---
name: memory
description: Decompose and reorganize memory files into focused, single-purpose files using `/` naming
tools: Read, Edit, Write, Glob, Grep, Bash
tools: Read, Edit, Write, Glob, Grep, Bash, TaskOutput
model: sonnet
memoryBlocks: none
permissionMode: bypassPermissions
@@ -68,20 +68,48 @@ Do **not** edit:
## Operating Procedure
### Phase 0: Setup
The memory directory is at:
`~/.letta/agents/$LETTA_AGENT_ID/memory/`
```bash
MEMORY_DIR=~/.letta/agents/$LETTA_AGENT_ID/memory
WORKTREE_DIR=~/.letta/agents/$LETTA_AGENT_ID/memory-worktrees
```
The memory directory should already be a git repo
(initialized when MemFS was enabled). If it's not, or
if git is unavailable, report the issue and exit without
making changes.
**Create worktree:**
```bash
BRANCH="defrag-$(date +%s)"
mkdir -p "$WORKTREE_DIR"
cd "$MEMORY_DIR"
git worktree add "$WORKTREE_DIR/$BRANCH" -b "$BRANCH"
```
All subsequent file operations target the worktree:
`$WORKTREE_DIR/$BRANCH/system/` (not the main memory dir).
### Step 1: Inventory
First, list what files are available:
```bash
ls ~/.letta/agents/$LETTA_AGENT_ID/memory/system/
WORK=$WORKTREE_DIR/$BRANCH/system
ls $WORK/
```
Then read relevant memory files:
```
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" })
Read({ file_path: "$WORK/project.md" })
Read({ file_path: "$WORK/persona.md" })
Read({ file_path: "$WORK/human.md" })
```
### Step 2: Identify system-managed files (skip)
@@ -149,6 +177,139 @@ For each edited file: before/after chars, delta, what was fixed
#### 4) Before/after examples
24 examples showing redundancy removal, contradiction resolution, or structure improvements
### Phase 5: Merge, Push, and Clean Up (MANDATORY)
Your defrag has two completion states:
- **Complete**: merged to main AND pushed to remote.
- **Partially complete**: merged to main, push failed.
Clean up the worktree, but report that local main is
ahead of remote and needs a push.
The commit in the worktree is neither — it's an intermediate
step. Without at least a merge to main, your work is lost.
**Step 5a: Commit in worktree**
```bash
MEMORY_DIR=~/.letta/agents/$LETTA_AGENT_ID/memory
WORKTREE_DIR=~/.letta/agents/$LETTA_AGENT_ID/memory-worktrees
cd $WORKTREE_DIR/$BRANCH
git add -A
```
Check `git status` — if there are no changes to commit,
skip straight to Step 5d (cleanup). Report "no updates
needed" in your output.
If there are changes, commit:
```bash
git commit -m "chore(defrag): <summary>"
```
**Step 5b: Pull + merge to main**
```bash
cd $MEMORY_DIR
```
First, check that main is in a clean state (`git status`).
If a merge or rebase is in progress (lock file, dirty
index), wait and retry up to 3 times with backoff (sleep 2,
5, 10 seconds). Never delete `.git/index.lock` manually.
If still busy after retries, go to Error Handling.
Pull from remote:
```bash
git pull --ff-only
```
If `--ff-only` fails (remote has diverged), fall back:
```bash
git pull --rebase
```
If rebase has conflicts, resolve them autonomously to
stabilize local `main` against remote `main` first. In this
step, prefer **remote main** content for conflicting files,
then run `git rebase --continue`.
Now merge the defrag branch:
```bash
git merge $BRANCH --no-edit
```
If the merge has conflicts, resolve by preferring defrag
branch/worktree content for memory files, stage the resolved
files, and complete with `git commit --no-edit`.
If you cannot resolve conflicts after 2 attempts, go to
Error Handling.
**Step 5c: Push to remote**
```bash
git push
```
If push fails, retry once. If it still fails, report that
local main is ahead of remote and needs a push. Proceed to
cleanup — the merge succeeded and data is safe on local
main.
**Step 5d: Clean up worktree and branch**
Only clean up when merge to main completed (success or
partially complete):
```bash
git worktree remove $WORKTREE_DIR/$BRANCH
git branch -d $BRANCH
```
**Step 5e: Verify**
```bash
git status
git log --oneline -3
```
Confirm main is clean and your defrag commit is visible
in the log.
## Error Handling
If anything goes wrong at any phase:
1. Stabilize main first (abort in-progress operations):
```bash
cd $MEMORY_DIR
git merge --abort 2>/dev/null
git rebase --abort 2>/dev/null
```
2. Do NOT clean up the worktree or branch on failure —
preserve them for debugging and manual recovery.
3. Report clearly in your output:
- What failed and the error message
- Worktree path: `$WORKTREE_DIR/$BRANCH`
- Branch name: `$BRANCH`
- Whether main has uncommitted/dirty state
- Concrete resume commands, e.g.:
```bash
cd ~/.letta/agents/$LETTA_AGENT_ID/memory
git merge <branch-name> --no-edit
git push
git worktree remove ../memory-worktrees/<branch-name>
git branch -d <branch-name>
```
4. Do NOT leave uncommitted changes on main.
## Final Checklist
Before submitting, confirm:
@@ -158,6 +319,7 @@ Before submitting, confirm:
- [ ] **Hierarchy is 23 levels deep**
- [ ] **No file exceeds ~40 lines**
- [ ] **Each file has one concept**
- [ ] **Changes committed, merged to main, and pushed**
**If you have fewer than 15 files, you haven't split enough.**

View File

@@ -1,261 +0,0 @@
---
name: defragmenting-memory
description: Decomposes and reorganizes agent memory blocks into focused, single-purpose components. Use when memory has large multi-topic blocks, redundancy, or poor organization.
---
# Memory Defragmentation Skill
> **Requires Memory Filesystem (memfs)**
>
> This skill works by directly editing memory files on disk. It requires the memory filesystem feature to be enabled.
>
> **To check:** Look for a `memory_filesystem` block in your system prompt. If it shows a tree structure starting with `/memory/` including a `system/` directory, memfs is enabled.
>
> **To enable:** Ask the user to run `/memfs enable`, then reload the CLI.
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.
## When to Use
- Memory blocks have redundant information
- Memory lacks structure (walls of text)
- Memory contains contradictions
- Memory has grown stale or outdated
- After major project milestones
- Every 50-100 conversation turns
## Workflow
### Step 1: Commit Current State (Safety Net)
The memory directory is a git repo. Commit the current state so you can rollback if needed:
```bash
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 commit before proceeding. This is your rollback point.
### Step 2: Spawn Subagent to Edit Memory Files
The memory subagent works directly on the memfs `system/` directory. After it finishes, memfs sync will propagate changes to the API on next CLI startup.
```typescript
Task({
subagent_type: "memory",
run_in_background: true,
description: "Decompose and reorganize memory files",
prompt: `You are decomposing and reorganizing memory files in ~/.letta/agents/${LETTA_AGENT_ID}/memory/system/ to improve clarity and focus.
These files ARE the agent's memory — they sync directly to API memory blocks via memfs. Changes you make here will be picked up automatically.
## Directory Structure
~/.letta/agents/<agent-id>/memory/
├── system/ ← Attached blocks (always loaded in system prompt) — EDIT THESE
├── notes.md ← Detached blocks at root level (on-demand) — can create here
├── archive/ ← Detached blocks can be nested too
└── .sync-state.json ← DO NOT EDIT (internal sync tracking)
## Files to Skip (DO NOT edit)
- memory_filesystem.md (auto-generated tree view)
- .sync-state.json (internal)
## What to Edit
- persona.md → Consider splitting into: persona/identity.md, persona/values.md, persona/approach.md
- project.md → Consider splitting into: project/overview.md, project/architecture.md, project/conventions.md, etc.
- human.md → Consider splitting into: human/identity.md, human/preferences.md, etc.
- Any other non-system blocks present
## How Memfs File ↔ Block Mapping Works
- File path relative to memory root becomes the block label (system/ prefix for attached, root level for detached)
- Example: system/project/tooling/bun.md → block label "project/tooling/bun"
- New files you create will become new memory blocks on next sync
- Files you delete will cause the corresponding blocks to be deleted on next sync
- YAML frontmatter is supported for metadata (label, description, limit, read_only)
## Evaluation Criteria
1. **DECOMPOSITION** - Split large, multi-purpose blocks into focused, single-purpose components
- Example: A "persona" block mixing identity, values, AND approach should become persona/identity.md, persona/values.md, persona/approach.md
- Example: A "project" block with overview, architecture, conventions, and gotchas should split into project/overview.md, project/architecture.md, project/conventions.md, project/gotchas.md
- Goal: Each block should have ONE clear purpose described by its filename
- Use hierarchical / naming (e.g., project/tooling/bun.md, not project-tooling-bun.md)
2. **STRUCTURE** - Organize content with clear markdown formatting
- Use headers (##, ###) for subsections
- Use bullet points for lists
- Make content scannable at a glance
3. **CONCISENESS** - Remove redundancy and unnecessary detail
- Eliminate duplicate information across blocks
- Remove speculation ("probably", "maybe", "I think")
- Keep only what adds unique value
4. **CLARITY** - Resolve contradictions and improve readability
- If blocks contradict, clarify or choose the better guidance
- Use plain language, avoid jargon
- Ensure each statement is concrete and actionable
5. **ORGANIZATION** - Group related information logically
- Within each block, organize content from general to specific
- Order sections by importance
## Workflow
1. **Analyze** - Read each file and identify its purpose(s)
- If a block serves 2+ distinct purposes, it needs decomposition
- Flag blocks where subtopics could be their own focused blocks
2. **Decompose** - Split multi-purpose blocks into specialized files
- Create new files using hierarchical paths (e.g., project/tooling/bun.md)
- Ensure each new block has ONE primary purpose
3. **Clean Up** - For remaining blocks (or new focused blocks):
- Add markdown structure with headers and bullets
- Remove redundancy
- Resolve contradictions
- Improve clarity
4. **Delete** - Remove files only when appropriate
- After moving all content to new decomposed files
- Never delete a focused, single-purpose block
- Only delete if a block contains junk/irrelevant data with no value
## Success Indicators
- No block tries to cover 2+ distinct topics
- Each block title clearly describes its single purpose
- Content within each block is focused and relevant to its title
- Well-organized with markdown structure
- Clear reduction in confusion/overlap across blocks
Provide a detailed report including:
- Files created (new decomposed blocks)
- Files modified (what changed)
- Files deleted (if any, explain why)
- Before/after character counts
- Rationale for how decomposition improves the memory structure`
})
```
The subagent will:
- Read files from `~/.letta/agents/<agent-id>/memory/system/` (and root level for detached)
- Edit them to reorganize and decompose large blocks
- Create new hierarchically-named files (e.g., `project/overview.md`)
- Add clear structure with markdown formatting
- Delete source files after decomposing their content into focused children
- Provide a detailed report of changes
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: Commit current state (MANDATORY)
Bash({
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)
Task({
subagent_type: "memory",
run_in_background: true,
description: "Decompose and reorganize memory files",
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."
})
// Step 3: After subagent completes, commit and push
// Check progress with /task <task_id>, restart CLI to sync when done
```
## Rollback
If something goes wrong, use git to revert:
```bash
cd ~/.letta/agents/$LETTA_AGENT_ID/memory
# 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 <commit-hash>
# Push the rollback
git push --force
```
On next CLI startup, memfs sync will detect the changes and update API blocks accordingly.
## What the Subagent Does
The subagent focuses on decomposing and cleaning up files. It has full tool access (including Bash) and:
- Discovers `.md` files in `~/.letta/agents/<agent-id>/memory/system/` (via Glob or Bash)
- Reads and examines each file's content
- Identifies multi-purpose blocks that serve 2+ distinct purposes
- Splits large blocks into focused, single-purpose components with hierarchical naming
- Modifies/creates .md files for decomposed blocks
- Improves structure with headers and bullet points
- Removes redundancy and speculation across blocks
- 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 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.
## Tips
**What to clean up:**
- Duplicate information (consolidate into one well-organized section)
- Walls of text without structure (add headers and bullets)
- Contradictions (resolve by clarifying or choosing the better guidance)
- Speculation ("probably", "maybe" - make it concrete or remove)
- Transient details that won't matter in a week
**Decomposition Strategy:**
- Split blocks that serve 2+ distinct purposes into focused components
- Use hierarchical `/` naming: `project/tooling/bun.md`, not `project-bun.md`
- Create parent index files that reference children
- Example: A "persona" mixing identity + values + approach → split into `persona/identity.md`, `persona/values.md`, `persona/approach.md`
- Example: A "project" with overview + architecture + conventions → split into `project/overview.md`, `project/architecture.md`, `project/conventions.md`
- Add clear headers and bullet points for scannability
- Group similar information together within focused blocks
**When to DELETE a file:**
- Only delete if file contains junk/irrelevant data with no project value
- Delete source files after fully decomposing content into child files
- Don't delete unique information just to reduce file count
**What to preserve:**
- User preferences (sacred - never delete)
- Project conventions discovered through experience
- Important context for future sessions
- Learnings from past mistakes
- Any information that has unique value
**Good memory structure:**
- Use markdown headers (##, ###)
- Organize with bullet points
- Keep related information together
- Make it scannable at a glance
- Use `/` hierarchy for discoverability