L3 Memory System
Checkpoints, decision logs, and behavioral lessons that persist across agent sessions.
The L3 layer provides stateful memory that survives context resets, branch switches, and session restarts. It prevents agents from repeating past mistakes and preserves progress across long-running tasks.
Three Memory Primitives
1. Checkpoints
Snapshots of the current agent work state, scoped to the active Git branch and commit.
Agent starts working
│
│ every ~10 changes (or manually)
▼
synap checkpoint create . \
--doing "Refactoring JWT auth" \
--files "src/auth/service.py,tests/test_auth.py" \
--next-step "Run pytest" \
--blockers "None"
│
▼
SQLite: checkpoints table
┌─────────────────────────────────┐
│ checkpoint_id: 18f5e27a... │
│ branch: main │
│ commit_hash: d980cf7f... │
│ doing: Refactoring... │
│ changed_files: [...] │
│ next_step: Run pytest │
│ blockers: None │
│ created_at: 1716000000 │
└─────────────────────────────────┘
│
│ New session / context reset
▼
MCP: restore_checkpoint
→ Returns latest checkpoint on current branch
→ Agent resumes exactly where it left off
MCP tools: create_checkpoint, restore_checkpoint
CLI: synap checkpoint create, synap checkpoint list, synap checkpoint restore latest
2. Decision Log
A permanent audit trail of architectural and design decisions made during development.
# Via MCP (agent calls this automatically)
MCP: log_decision
{
"decision": "Use SQLite WAL mode for concurrent access",
"rationale": "Allows concurrent readers without locking during index writes.",
"tags": ["architecture", "storage"]
}
# Via CLI
synap decision list .
Decisions are injected into retrieval context when relevant queries arrive, giving future agents historical rationale for current design choices.
3. Agent Lessons (Revert Memory)
The most powerful L3 primitive. Lessons prevent agents from repeating failures that required a git revert.
Developer runs: git revert <bad-commit>
│
▼
Daemon detects revert pattern
│
▼
┌───────────────────────────┐
│ PENDING lesson created │
│ (inactive, awaiting │
│ human review) │
└─────────────┬─────────────┘
│
synap lessons review .
│
┌─────────┴──────────┐
▼ ▼
┌──────────┐ ┌──────────┐
│ APPROVED │ │ REJECTED │
│ (active) │ │ (deleted)│
└────┬─────┘ └──────────┘
│
│ age > lesson_expiry_days (default: 7)
▼
┌──────────┐
│ EXPIRED │
│ (pruned) │
└──────────┘
Lifecycle rules:
- Pending lessons are inactive — agents cannot see them
- Only approved lessons are injected into context
- Lessons expire automatically after
lesson_expiry_days(default: 7 days) - Expired lessons can be reviewed and re-approved if still relevant
How Lessons Are Injected
During every search call, approved lessons are prepended to the returned context block:
═══════════════════════════════════════════
APPROVED SYSTEM MEMORY — CRITICAL: ADHERE
═══════════════════════════════════════════
1. [main, approved] Do NOT write un-aliased columns in
Postgres migration scripts. The column name resolver
breaks with implicit aliases. files_affected: migrations/001.sql
2. [main, approved] Always wrap async SQLite writes in
asyncio.to_thread(). Direct awaiting causes event loop blocking.
files_affected: src/storage/sqlite.py
═══════════════════════════════════════════
[Retrieved context follows...]
Memory CLI Commands
# Review pending lessons interactively
synap lessons review .
# Approve a specific lesson
synap lessons approve <lesson-id> .
# Reject a lesson (deletes it)
synap lessons reject <lesson-id> .
# Show memory statistics
synap memory status .
# Force-prune expired lessons
synap memory prune .
# Validate lesson file references are not dangling
synap memory verify .
MCP Memory Tools
| Tool | When to Call |
|---|---|
| get_approved_memory | Always at session start — load all active constraints |
| restore_checkpoint | Always at session start — resume from last state |
| create_checkpoint | Every ~10 significant changes, or before context-heavy operations |
| log_decision | After making any architectural or design choice |
| submit_lesson_analysis | When asked to explain a failed/reverted change |
| signal_low_context | When token usage exceeds 60% of context window capacity |