{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Memory & Context Management with Claude Sonnet 4.5\n", "\n", "Learn how to build AI agents that learn and improve across conversations using Claude's memory tool and context editing capabilities." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Table of Contents\n", "\n", "1. [Introduction: Why Memory Matters](#introduction)\n", "2. [Use Cases](#use-cases)\n", "3. [Quick Start Examples](#quick-start)\n", "4. [How It Works](#how-it-works)\n", "5. [Code Review Assistant Demo](#demo)\n", "6. [Real-World Applications](#real-world)\n", "7. [Best Practices](#best-practices)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Setup\n", "\n", "### For VSCode Users\n", "\n", "```bash\n", "# 1. Create virtual environment\n", "python -m venv .venv\n", "\n", "# 2. Activate it\n", "source .venv/bin/activate # macOS/Linux\n", "# or: .venv\\Scripts\\activate # Windows\n", "\n", "# 3. Install dependencies\n", "pip install -r requirements.txt\n", "\n", "# 4. In VSCode: Select .venv as kernel (top right)\n", "```\n", "\n", "### API Key\n", "\n", "```bash\n", "cp .env.example .env\n", "# Edit .env and add your ANTHROPIC_API_KEY\n", "```\n", "\n", "Get your API key from: https://console.anthropic.com/\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 1. Introduction: Why Memory Matters {#introduction}\n", "\n", "### The Problem\n", "\n", "Large language models have finite context windows (200k tokens for Claude 4). While this seems large, several challenges emerge:\n", "\n", "- **Context limits**: Long conversations or complex tasks can exceed available context\n", "- **Computational cost**: Processing large contexts is expensive - attention mechanisms scale quadratically\n", "- **Repeated patterns**: Similar tasks across conversations require re-explaining context every time\n", "- **Information loss**: When context fills up, earlier important information gets lost\n", "\n", "### The Solution\n", "\n", "Claude Sonnet 4.5 introduces two powerful capabilities:\n", "\n", "1. **Memory Tool** (`memory_20250818`): Enables cross-conversation learning\n", " - Claude can write down what it learns for future reference\n", " - File-based system under `/memories` directory\n", " - Client-side implementation gives you full control\n", "\n", "2. **Context Editing** (`clear_tool_uses_20250919`): Automatically manages context\n", " - Clears old tool results when context grows large\n", " - Keeps recent context while preserving memory\n", " - Configurable triggers and retention policies\n", "\n", "### The Benefit\n", "\n", "Build AI agents that **get better at your specific tasks over time**:\n", "\n", "- **Session 1**: Claude solves a problem, writes down the pattern\n", "- **Session 2**: Claude applies the learned pattern immediately (faster!)\n", "- **Long sessions**: Context editing keeps conversations manageable\n", "\n", "Think of it as giving Claude a notebook to take notes and refer back to - just like humans do." ] }, { "cell_type": "markdown", "metadata": {}, "source": "## 2. Use Cases {#use-cases}\n\nMemory and context management enable powerful new workflows:\n\n### ๐Ÿ” Code Review Assistant\n- Learns debugging patterns from past reviews\n- Recognizes similar bugs instantly in future sessions\n- Builds team-specific code quality knowledge\n- **Production ready**: Integrate with [claude-code-action](https://github.com/anthropics/claude-code-action) for GitHub PR reviews\n\n### ๐Ÿ“š Research Assistant\n- Accumulates knowledge on topics over multiple sessions\n- Connects insights across different research threads\n- Maintains bibliography and source tracking\n\n### ๐Ÿ’ฌ Customer Support Bot\n- Learns user preferences and communication style\n- Remembers common issues and solutions\n- Builds product knowledge base from interactions\n\n### ๐Ÿ“Š Data Analysis Helper\n- Remembers dataset patterns and anomalies\n- Stores analysis techniques that work well\n- Builds domain-specific insights over time\n\n**Supported Models**: Claude Opus 4 (`claude-opus-4-20250514`), Claude Opus 4.1 (`claude-opus-4-1-20250805`), Claude Sonnet 4 (`claude-sonnet-4-20250514`), and Claude Sonnet 4.5 (`claude-sonnet-4-5-20250929`)\n\n**This cookbook focuses on the Code Review Assistant** as it clearly demonstrates both memory (learning patterns) and context editing (handling long reviews)." }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 3. Quick Start Examples {#quick-start}\n", "\n", "Let's see memory and context management in action with simple examples." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Setup\n", "\n", "First, install dependencies and configure your environment:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m24.0\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m25.2\u001b[0m\n", "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpip install --upgrade pip\u001b[0m\n", "Note: you may need to restart the kernel to use updated packages.\n" ] } ], "source": [ "# Install required packages\n", "# Option 1: From requirements.txt\n", "# %pip install -q -r requirements.txt\n", "\n", "# Option 2: Direct install\n", "%pip install -q anthropic python-dotenv ipykernel\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**โš ๏ธ Important**: Create a `.env` file in this directory:\n", "\n", "```bash\n", "# Copy .env.example to .env and add your API key\n", "cp .env.example .env\n", "```\n", "\n", "Then edit `.env` to add your Anthropic API key from https://console.anthropic.com/" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": "import os\nfrom typing import Any, cast\n\nfrom anthropic import Anthropic\nfrom dotenv import load_dotenv\n\n# Load environment variables\nload_dotenv()\n\nAPI_KEY = os.getenv(\"ANTHROPIC_API_KEY\")\nMODEL = os.getenv(\"ANTHROPIC_MODEL\")\n\nif not API_KEY:\n raise ValueError(\n \"ANTHROPIC_API_KEY not found. \"\n \"Copy .env.example to .env and add your API key.\"\n )\n\nif not MODEL:\n raise ValueError(\n \"ANTHROPIC_MODEL not found. \"\n \"Copy .env.example to .env and set the model.\"\n )\n\nMODEL = cast(str, MODEL)\n\nclient = Anthropic(api_key=API_KEY)\n\nprint(\"โœ“ API key loaded\")\nprint(f\"โœ“ Using model: {MODEL}\")" }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Example 1: Basic Memory Usage\n", "\n", "Let's see Claude use memory to store information for future reference." ] }, { "cell_type": "markdown", "source": "**Helper Functions**\n\nThese examples use helper functions from `demo_helpers.py`:\n\n- **`run_conversation_loop()`**: Handles the API conversation loop\n - Calls Claude's API with memory tool enabled\n - Executes tool uses (memory operations)\n - Continues until Claude stops using tools\n - Returns the final response\n\n- **`run_conversation_turn()`**: Single turn (used in Example 3)\n - Same as above but returns after one API call\n - Useful when you need fine-grained control\n\n- **`print_context_management_info()`**: Displays context clearing stats\n - Shows tokens saved, tool uses cleared\n - Helps visualize when context editing triggers", "metadata": {} }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": "# Import helper functions\nfrom memory_demo.demo_helpers import run_conversation_loop, run_conversation_turn, print_context_management_info\nfrom memory_tool import MemoryToolHandler\n\n# Initialize\nclient = Anthropic(api_key=API_KEY)\nmemory = MemoryToolHandler(base_path=\"./demo_memory\")\n\n# Clear any existing memories to start fresh\nprint(\"๐Ÿงน Clearing previous memories...\")\nmemory.clear_all_memory()\nprint(\"โœ“ Memory cleared\\n\")\n\n# Load example code with a race condition bug\nwith open(\"memory_demo/sample_code/web_scraper_v1.py\", \"r\") as f:\n code_to_review = f.read()\n\nmessages = [\n {\n \"role\": \"user\",\n \"content\": f\"I'm reviewing a multi-threaded web scraper that sometimes returns fewer results than expected. The count is inconsistent across runs. Can you find the issue?\\n\\n```python\\n{code_to_review}\\n```\"\n }\n]\n\nprint(\"=\" * 60)\nprint(\"๐Ÿ“ SESSION 1: Learning from a bug\")\nprint(\"=\" * 60)\n\n# Run conversation loop\nresponse = run_conversation_loop(\n client=client,\n model=MODEL,\n messages=messages,\n memory_handler=memory,\n system=\"You are a code reviewer. Always check memory first, then store important patterns.\",\n max_tokens=2048,\n max_turns=5,\n verbose=True\n)\n\nprint(\"\\n\" + \"=\" * 60)\nprint(\"โœ… Session 1 complete!\")\nprint(\"=\" * 60)" }, { "cell_type": "markdown", "metadata": {}, "source": "**What happened?**\n\n1. Claude checked its memory (empty on first run)\n2. Identified the bug: **race condition** - multiple threads modifying shared state (`self.results` and `self.failed_urls`) without synchronization\n3. Stored the concurrency pattern in memory for future reference\n\nNow let's see the magic - Claude applying this learned pattern in a **new conversation**:" }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Example 2: Cross-Conversation Learning\n", "\n", "Start a completely new conversation - memory persists!" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": "# NEW conversation (empty messages)\n# Load API client code with similar concurrency issue\nwith open(\"memory_demo/sample_code/api_client_v1.py\", \"r\") as f:\n code_to_review = f.read()\n\nmessages = [\n {\n \"role\": \"user\",\n \"content\": f\"Review this API client code:\\n\\n```python\\n{code_to_review}\\n```\"\n }\n]\n\nprint(\"=\" * 60)\nprint(\"๐Ÿš€ SESSION 2: Applying learned pattern\")\nprint(\"=\" * 60)\n\n# Run conversation loop\nresponse = run_conversation_loop(\n client=client,\n model=MODEL,\n messages=messages,\n memory_handler=memory,\n system=\"You are a code reviewer. Always check memory first.\",\n max_tokens=2048,\n max_turns=5,\n verbose=True\n)\n\nprint(\"\\n\" + \"=\" * 60)\nprint(\"โœ… Session 2 complete!\")\nprint(\"=\" * 60)" }, { "cell_type": "markdown", "metadata": {}, "source": "**Notice the difference:**\n\n- Claude **immediately checked memory** and found the thread-safety/concurrency pattern\n- Recognized the similar issue in async code **instantly** without re-learning\n- Response was **faster** because it applied stored knowledge about shared mutable state\n\nThis is **cross-conversation learning** in action!" }, { "cell_type": "markdown", "source": "### Example 3: Context Clearing While Preserving Memory\n\nWhat happens during a **long review session** with many code files?\n\n- Context fills up with tool results from previous reviews\n- But memory (learned patterns) must persist!\n\nLet's trigger **context editing** to see how Claude manages this automatically.", "metadata": {} }, { "cell_type": "code", "source": "# Configure context management to clear aggressively for demo\nCONTEXT_MANAGEMENT = {\n \"edits\": [\n {\n \"type\": \"clear_tool_uses_20250919\",\n \"trigger\": {\"type\": \"input_tokens\", \"value\": 15000}, # Lower threshold to trigger clearing sooner\n \"keep\": {\"type\": \"tool_uses\", \"value\": 2}, # Keep only the last 2 tool uses\n \"clear_at_least\": {\"type\": \"input_tokens\", \"value\": 3000}\n }\n ]\n}\n\n# Continue from previous session - memory persists!\n# Add multiple code reviews to build up context\n\nprint(\"=\" * 60)\nprint(\"๐Ÿ“š SESSION 3: Long review session with context clearing\")\nprint(\"=\" * 60)\nprint()\n\n# Review 1: Data processor (larger file)\nwith open(\"memory_demo/sample_code/data_processor_v1.py\", \"r\") as f:\n data_processor_code = f.read()\n\nmessages.extend([\n {\n \"role\": \"user\",\n \"content\": f\"Review this data processor:\\n\\n```python\\n{data_processor_code}\\n```\"\n }\n])\n\nprint(\"๐Ÿ“ Review 1: Data processor\")\nresponse = run_conversation_turn(\n client=client,\n model=MODEL,\n messages=messages,\n memory_handler=memory,\n system=\"You are a code reviewer. Always check memory first.\",\n context_management=CONTEXT_MANAGEMENT,\n max_tokens=2048,\n verbose=True\n)\n\n# Add response to messages\nmessages.append({\"role\": \"assistant\", \"content\": response[1]})\nif response[2]:\n messages.append({\"role\": \"user\", \"content\": response[2]})\n\nprint(f\" ๐Ÿ“Š Input tokens: {response[0].usage.input_tokens:,}\")\ncontext_cleared, saved = print_context_management_info(response[0])\nprint()\n\n# Review 2: Add SQL code\nwith open(\"memory_demo/sample_code/sql_query_builder.py\", \"r\") as f:\n sql_code = f.read()\n\nmessages.extend([\n {\n \"role\": \"user\",\n \"content\": f\"Review this SQL query builder:\\n\\n```python\\n{sql_code}\\n```\"\n }\n])\n\nprint(\"๐Ÿ“ Review 2: SQL query builder\")\nresponse = run_conversation_turn(\n client=client,\n model=MODEL,\n messages=messages,\n memory_handler=memory,\n system=\"You are a code reviewer. Always check memory first.\",\n context_management=CONTEXT_MANAGEMENT,\n max_tokens=2048,\n verbose=True\n)\n\nmessages.append({\"role\": \"assistant\", \"content\": response[1]})\nif response[2]:\n messages.append({\"role\": \"user\", \"content\": response[2]})\n\nprint(f\" ๐Ÿ“Š Input tokens: {response[0].usage.input_tokens:,}\")\ncontext_cleared, saved = print_context_management_info(response[0])\nprint()\n\nprint(\"=\" * 60)\nprint(\"โœ… Session 3 complete!\")\nprint(\"=\" * 60)", "metadata": {}, "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "source": "**What just happened?**\n\nAs context grew during multiple reviews:\n1. **Context clearing triggered automatically** when input tokens exceeded the threshold\n2. **Old tool results were removed** (data processor review details)\n3. **Memory files remained intact** - Claude can still query learned patterns\n4. **Token usage decreased** - saved thousands of tokens while preserving knowledge\n\nThis demonstrates the key benefit:\n- **Short-term memory** (conversation context) โ†’ Cleared to save space\n- **Long-term memory** (stored patterns) โ†’ Persists across sessions\n\nLet's verify memory survived the clearing:", "metadata": {} }, { "cell_type": "code", "source": "# Verify memory persists after context clearing\nimport os\n\nprint(\"๐Ÿ“‚ Memory files in demo_memory/:\")\nprint()\n\nfor root, dirs, files in os.walk(\"./demo_memory\"):\n # Calculate relative path for display\n level = root.replace(\"./demo_memory\", \"\").count(os.sep)\n indent = \" \" * level\n folder_name = os.path.basename(root) or \"demo_memory\"\n print(f\"{indent}{folder_name}/\")\n \n sub_indent = \" \" * (level + 1)\n for file in files:\n file_path = os.path.join(root, file)\n size = os.path.getsize(file_path)\n print(f\"{sub_indent}โ”œโ”€โ”€ {file} ({size} bytes)\")\n\nprint()\nprint(\"โœ… All learned patterns preserved despite context clearing!\")", "metadata": {}, "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "source": "## 4. How It Works {#how-it-works}\n\n### Memory Tool Architecture\n\nThe memory tool is **client-side** - you control the storage. Claude makes tool calls, your application executes them.\n\n#### Memory Tool Commands\n\n| Command | Description | Example |\n|---------|-------------|---------|\n| `view` | Show directory or file contents | `{\"command\": \"view\", \"path\": \"/memories\"}` |\n| `create` | Create or overwrite a file | `{\"command\": \"create\", \"path\": \"/memories/notes.md\", \"file_text\": \"...\"}` |\n| `str_replace` | Replace text in a file | `{\"command\": \"str_replace\", \"path\": \"...\", \"old_str\": \"...\", \"new_str\": \"...\"}` |\n| `insert` | Insert text at line number | `{\"command\": \"insert\", \"path\": \"...\", \"insert_line\": 2, \"insert_text\": \"...\"}` |\n| `delete` | Delete a file or directory | `{\"command\": \"delete\", \"path\": \"/memories/old.txt\"}` |\n| `rename` | Rename or move a file | `{\"command\": \"rename\", \"old_path\": \"...\", \"new_path\": \"...\"}` |\n\nSee `memory_tool.py` for the complete implementation with path validation and security measures.", "metadata": {} }, { "cell_type": "markdown", "metadata": {}, "source": "### Understanding the Demo Code\n\nKey implementation details from `code_review_demo.py`:\n\n```python\nclass CodeReviewAssistant:\n def __init__(self, memory_storage_path=\"./memory_storage\"):\n self.client = Anthropic(api_key=API_KEY)\n self.memory_handler = MemoryToolHandler(base_path=memory_storage_path)\n self.messages = []\n \n def review_code(self, code, filename, description=\"\"):\n # 1. Add user message\n self.messages.append({...})\n \n # 2. Conversation loop with tool execution\n while True:\n response = self.client.beta.messages.create(\n model=MODEL,\n system=self._create_system_prompt(),\n messages=self.messages,\n tools=[{\"type\": \"memory_20250818\", \"name\": \"memory\"}],\n betas=[\"context-management-2025-06-27\"],\n context_management=CONTEXT_MANAGEMENT\n )\n \n # 3. Execute tool uses\n tool_results = []\n for content in response.content:\n if content.type == \"tool_use\":\n result = self._execute_tool_use(content)\n tool_results.append({...})\n \n # 4. Continue if there are tool uses, otherwise done\n if tool_results:\n self.messages.append({\"role\": \"user\", \"content\": tool_results})\n else:\n break\n```\n\n**The key pattern**: Keep calling the API while there are tool uses, executing them and feeding results back." }, { "cell_type": "markdown", "metadata": {}, "source": [ "### What Claude Actually Learns\n", "\n", "This is what makes memory powerful - **semantic pattern recognition**, not just syntax:\n", "\n", "**Session 1: Thread-Based Web Scraper**\n", "\n", "```python\n", "# Bug: Race condition\n", "class WebScraper:\n", " def __init__(self):\n", " self.results = [] # Shared state!\n", " \n", " def scrape_urls(self, urls):\n", " with ThreadPoolExecutor() as executor:\n", " for future in as_completed(futures):\n", " self.results.append(future.result()) # RACE!\n", "```\n", "\n", "**Pattern Stored** (`/memories/concurrency_patterns/thread_safety.md`):\n", "- **Symptom**: Inconsistent results in concurrent operations\n", "- **Cause**: Shared mutable state (lists/dicts) modified from multiple threads\n", "- **Solution**: Use locks, thread-safe data structures, or return results instead\n", "- **Red flags**: Instance variables in thread callbacks, unused locks, counter increments\n", "\n", "---\n", "\n", "**Session 2: Async API Client** (New conversation!)\n", "\n", "Claude checks memory FIRST, finds the thread-safety pattern, then:\n", "1. **Recognizes** similar pattern in async code (coroutines can interleave too)\n", "2. **Applies** the solution immediately (no re-learning needed)\n", "3. **Explains** with reference to stored knowledge\n", "\n", "```python\n", "# Claude spots this immediately:\n", "async def fetch_all(self, endpoints):\n", " for coro in asyncio.as_completed(tasks):\n", " self.responses.append(await coro) # Same pattern!\n", "```\n", "\n", "---\n", "\n", "**Why This Matters:**\n", "\n", "- โŒ **Syntax checkers** miss race conditions entirely\n", "- โœ… **Claude learns** architectural patterns and applies them across contexts\n", "- โœ… **Cross-language**: Pattern applies to Go, Java, Rust concurrency too\n", "- โœ… **Gets better**: Each review adds to the knowledge base\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": "### Sample Code Files\n\nThe demo uses these sample files (all have concurrency/thread-safety bugs):\n\n- `memory_demo/sample_code/web_scraper_v1.py` - Race condition: threads modifying shared state\n- `memory_demo/sample_code/api_client_v1.py` - Similar concurrency bug in async context\n- `memory_demo/sample_code/data_processor_v1.py` - Multiple concurrency issues for long session demo\n\nLet's look at one:" }, { "cell_type": "markdown", "execution_count": null, "metadata": {}, "outputs": [], "source": "**`memory_demo/sample_code/web_scraper_v1.py`**\n\n```python\n\"\"\"\nConcurrent web scraper with a race condition bug.\nMultiple threads modify shared state without synchronization.\n\"\"\"\n\nimport time\nfrom concurrent.futures import ThreadPoolExecutor, as_completed\nfrom typing import List, Dict\n\nimport requests\n\n\nclass WebScraper:\n \"\"\"Web scraper that fetches multiple URLs concurrently.\"\"\"\n\n def __init__(self, max_workers: int = 10):\n self.max_workers = max_workers\n self.results = [] # BUG: Shared mutable state accessed by multiple threads!\n self.failed_urls = [] # BUG: Another race condition!\n\n def fetch_url(self, url: str) -> Dict[str, any]:\n \"\"\"Fetch a single URL and return the result.\"\"\"\n try:\n response = requests.get(url, timeout=5)\n response.raise_for_status()\n return {\n \"url\": url,\n \"status\": response.status_code,\n \"content_length\": len(response.content),\n }\n except requests.exceptions.RequestException as e:\n return {\"url\": url, \"error\": str(e)}\n\n def scrape_urls(self, urls: List[str]) -> List[Dict[str, any]]:\n \"\"\"\n Scrape multiple URLs concurrently.\n\n BUG: self.results is accessed from multiple threads without locking!\n This causes race conditions where results can be lost or corrupted.\n \"\"\"\n with ThreadPoolExecutor(max_workers=self.max_workers) as executor:\n futures = [executor.submit(self.fetch_url, url) for url in urls]\n\n for future in as_completed(futures):\n result = future.result()\n\n # RACE CONDITION: Multiple threads append to self.results simultaneously\n if \"error\" in result:\n self.failed_urls.append(result[\"url\"]) # RACE CONDITION\n else:\n self.results.append(result) # RACE CONDITION\n\n return self.results\n```" }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Bug**: Multiple threads modify `self.results` and `self.failed_urls` without locking!\n", "\n", "Claude will:\n", "1. Identify the race conditions\n", "2. Store the pattern in `/memories/concurrency_patterns/thread_safety.md`\n", "3. Apply this concurrency pattern to async code in Session 2" ] }, { "cell_type": "markdown", "metadata": {}, "source": "### Demo Overview\n\nWe've built a complete Code Review Assistant. The implementation is in `memory_demo/code_review_demo.py`.\n\n**To run the interactive demo:**\n```bash\npython memory_demo/code_review_demo.py\n```\n\nThe demo demonstrates:\n1. **Session 1**: Review Python code with a bug โ†’ Claude learns the pattern\n2. **Session 2**: Review similar code (new conversation) โ†’ Claude applies the pattern\n3. **Session 3**: Long review session โ†’ Context editing keeps it manageable" }, { "cell_type": "markdown", "source": "## 7. Best Practices & Security {#best-practices}\n\n### Memory Management\n\n**Do:**\n- โœ… Store task-relevant patterns, not conversation history\n- โœ… Organize with clear directory structure\n- โœ… Use descriptive file names\n- โœ… Periodically review and clean up memory\n\n**Don't:**\n- โŒ Store sensitive information (passwords, API keys, PII)\n- โŒ Let memory grow unbounded\n- โŒ Store everything indiscriminately\n\n### Security: Path Traversal Protection\n\n**Critical**: Always validate paths to prevent directory traversal attacks. See `memory_tool.py` for implementation.\n\n### Security: Memory Poisoning\n\n**โš ๏ธ Critical Risk**: Memory files are read back into Claude's context, making them a potential vector for prompt injection.\n\n**Mitigation strategies:**\n1. **Content Sanitization**: Filter dangerous patterns before storing\n2. **Memory Scope Isolation**: Per-user/per-project isolation \n3. **Memory Auditing**: Log and scan all memory operations\n4. **Prompt Engineering**: Instruct Claude to ignore instructions in memory\n\nSee `memory_tool.py` for complete security implementation and tests in `tests/`.", "metadata": {} }, { "cell_type": "markdown", "source": "## Next Steps\n\n### Resources\n\n- **API Docs**: [docs.anthropic.com](https://docs.anthropic.com)\n- **GitHub Action**: [claude-code-action](https://github.com/anthropics/claude-code-action)\n- **Support**: [support.anthropic.com](https://support.anthropic.com)\n\n### Feedback\n\nMemory and context management are in **beta**. Share your feedback to help us improve!", "metadata": {} } ], "metadata": { "kernelspec": { "display_name": ".venv", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.13" } }, "nbformat": 4, "nbformat_minor": 4 }