$npx -y skills add simbajigege/book2skills --skill compact-memory-implementationDeveloper implementation guide for adding compact memory to an Agent — covers fork agent pattern for compaction, trigger strategy, summary format design, and memory restoration in subsequent sessions. Use when a developer asks how to implement compact memory, context compression,
| 1 | # compact-memory-implementation |
| 2 | |
| 3 | A developer guide for building compact memory into an Agent: detect when to compress, fork a compactor sub-agent, produce a structured summary, and restore it in the next session. |
| 4 | |
| 5 | ## Step 1 — Understand the setup |
| 6 | |
| 7 | Before designing anything, clarify: |
| 8 | |
| 9 | - **SDK / language**: Claude Agent SDK? Direct Anthropic API? Python or TypeScript? |
| 10 | - **Agent architecture**: single-agent loop, multi-agent, tool-calling? |
| 11 | - **Session model**: one long-running session or multiple short sessions? |
| 12 | - **What must survive compaction**: task state, decisions, tool results, conversation history? |
| 13 | |
| 14 | This determines which pattern fits. |
| 15 | |
| 16 | --- |
| 17 | |
| 18 | ## Step 2 — When to trigger compact |
| 19 | |
| 20 | Three strategies, pick based on your session model: |
| 21 | |
| 22 | **1. Token threshold** (recommended) |
| 23 | Check `usage.input_tokens` from the previous response. When it exceeds ~70–80% of your model's context limit, trigger compact. |
| 24 | |
| 25 | ```python |
| 26 | COMPACT_THRESHOLD = 150_000 # adjust per model |
| 27 | |
| 28 | if response.usage.input_tokens > COMPACT_THRESHOLD: |
| 29 | compact = compact_memory(history) |
| 30 | history = [] # reset — compact moves to system prompt |
| 31 | ``` |
| 32 | |
| 33 | **2. Turn count** |
| 34 | Compact every N turns. Simpler but less adaptive — misses sessions with a few very long turns. |
| 35 | |
| 36 | ```python |
| 37 | COMPACT_EVERY_N = 30 |
| 38 | |
| 39 | if turn_count % COMPACT_EVERY_N == 0: |
| 40 | compact = compact_memory(history) |
| 41 | ``` |
| 42 | |
| 43 | **3. Phase boundary** |
| 44 | Compact at natural task boundaries (after research, before implementation). Requires the agent to detect phases. Produces summaries that align with meaningful milestones, but harder to implement reliably. |
| 45 | |
| 46 | **Recommended default**: token threshold at 70%, with turn-count fallback at N=40. |
| 47 | |
| 48 | --- |
| 49 | |
| 50 | ## Step 3 — Fork agent for compaction |
| 51 | |
| 52 | The compactor is a **separate agent call** whose only job is to read the current state and return a structured summary. Fork it synchronously — the main agent waits for the result before continuing. |
| 53 | |
| 54 | ```python |
| 55 | def compact_memory(history: list[dict]) -> dict: |
| 56 | response = client.messages.create( |
| 57 | model="claude-haiku-4-5-20251001", # cheaper model is fine for compaction |
| 58 | max_tokens=4096, |
| 59 | system=COMPACTOR_SYSTEM_PROMPT, |
| 60 | messages=[ |
| 61 | { |
| 62 | "role": "user", |
| 63 | "content": format_history_for_compact(history), |
| 64 | } |
| 65 | ], |
| 66 | ) |
| 67 | return json.loads(response.content[0].text) |
| 68 | ``` |
| 69 | |
| 70 | **Why fork instead of self-compact:** |
| 71 | - The main agent may have drifted in focus; the compactor starts fresh with the full picture |
| 72 | - Compaction is a different cognitive task — summarizing vs. executing |
| 73 | - A cheaper, smaller model (Haiku) can do compaction; save the expensive model for main work |
| 74 | - Clean separation makes the compact output easier to validate and test |
| 75 | |
| 76 | --- |
| 77 | |
| 78 | ## Step 4 — How to compact: format and prompt |
| 79 | |
| 80 | ### Compact output schema |
| 81 | |
| 82 | ```json |
| 83 | { |
| 84 | "task": "What the agent is working on and why — the goal, not the steps", |
| 85 | "current_state": "Exact status at compaction point: what is done, what is not, what is in progress", |
| 86 | "key_decisions": [ |
| 87 | { "decision": "...", "reason": "...", "constraint": "..." } |
| 88 | ], |
| 89 | "eliminated_approaches": [ |
| 90 | { "approach": "...", "reason_ruled_out": "..." } |
| 91 | ], |
| 92 | "open_questions": ["..."], |
| 93 | "next_steps": ["..."], |
| 94 | "relevant_tool_results": { |
| 95 | "key": "Only results future steps will need — summarized, not raw dumps" |
| 96 | }, |
| 97 | "compacted_at_turn": 42 |
| 98 | } |
| 99 | ``` |
| 100 | |
| 101 | ### Compactor system prompt |
| 102 | |
| 103 | ``` |
| 104 | You are a conversation compactor. Read the provided conversation and produce a JSON summary that captures everything a fresh agent needs to continue the work without asking what happened. |
| 105 | |
| 106 | Include: |
| 107 | - Current task and goal (not the steps taken to get here) |
| 108 | - Exact current state — what is done and what is not |
| 109 | - Decisions made and WHY (reasoning, not just the choice) |
| 110 | - Approaches tried and ruled out with reasons (prevents re-exploration) |
| 111 | - Open questions and blockers |
| 112 | - Concrete next steps in priority order |
| 113 | - Tool results that future steps will need (summarize, don't dump raw output) |
| 114 | |
| 115 | Omit: |
| 116 | - Intermediate reasoning that led nowhere |
| 117 | - Completed sub-tasks with no future relevance |
| 118 | - Raw tool output that has already been acted on |
| 119 | - Anything derivable by reading the code or running a command |
| 120 | |
| 121 | Output valid JSON matching the schema provided. No prose outside the JSON. |
| 122 | ``` |
| 123 | |
| 124 | ### Format history for compactor |
| 125 | |
| 126 | ```python |
| 127 | def format_history_for_compact(history: list[dict]) -> str: |
| 128 | lines = ["Conversation to compact:\n"] |
| 129 | for msg in history: |
| 130 | role = msg["role"].upper() |
| 131 | content = msg["content"] if isinstance(msg["content"], str) else "[tool use]" |