使用Claude Sonnet 4.6进行记忆与上下文管理

本教程面向有编程基础的开发者,深入讲解如何利用Claude Sonnet 4.6的记忆工具和上下文编辑功能,构建跨会话学习和长时间运行的AI代理。通过代码审查助手案例,演示了记忆工具实现跨对话模式学习,以及上下文编辑自动管理上下文窗口,避免信息丢失和成本过高。教程涵盖环境搭建、核心原理、架构设计、最佳实践与安全防护,并提供生产环境优化建议。

技术背景

大型语言模型(LLM)的上下文窗口有限(Claude 4系列为200k token),长对话或复杂任务容易超出限制,且注意力机制呈二次方扩展导致计算成本高昂。跨会话任务中,模型无法保留已学习的模式,每次需重新解释上下文,效率低下。Claude Sonnet 4.6引入记忆工具和上下文编辑功能,分别解决跨对话学习和长会话上下文管理问题,使代理能随时间积累知识并高效运行。

核心原理

记忆工具基于客户端文件系统,Claude通过工具调用(如view、create、str_replace等)读写/memories目录下的文件,实现跨会话持久化。上下文编辑通过两种策略自动清理:clear_tool_uses_20250919在输入token超阈值时清除旧工具结果,clear_thinking_20251015管理扩展思考块(需启用thinking)。组合时clear_thinking必须在前。数据流:用户输入→API调用(含记忆工具和上下文编辑配置)→模型生成响应或工具调用→执行工具并返回结果→循环直至无工具调用。

架构分析

系统采用客户端-服务器模式,客户端负责存储和工具执行,服务器(Anthropic API)负责推理。核心组件包括:MemoryToolHandler(管理记忆文件,含路径验证)、CodeReviewAssistant(对话循环与工具执行)、上下文编辑配置(触发器和保留策略)。设计决策:记忆文件按项目隔离,避免交叉污染;上下文编辑阈值生产环境设为30-40k token,演示中降低以展示效果;思考管理保留最近一轮以平衡缓存命中率。

完整实战教程

上下文编辑与长时间运行代理的记忆管理

跨多个会话运行或处理长时间任务的AI代理面临两个关键挑战:它们在对话之间会丢失已学习的模式,并且在长时间交互过程中上下文窗口会被填满。

本手册演示了如何使用Claude的记忆工具和上下文编辑功能来解决这些挑战。

目录

  1. 引言:为什么记忆很重要
  2. 使用场景
  3. 快速入门示例
  4. 工作原理
  5. 代码审查助手演示
  6. 实际应用
  7. 最佳实践

先决条件

所需知识:

所需工具:

推荐:

设置

对于 VSCode 用户

# 1. Create virtual environment
python -m venv .venv

# 2. Activate it
source .venv/bin/activate  # macOS/Linux
# or: .venv\Scripts\activate  # Windows

# 3. Install dependencies
pip install -r requirements.txt

# 4. In VSCode: Select .venv as kernel (top right)

API Key

cp .env.example .env
# Edit .env and add your ANTHROPIC_API_KEY

从以下地址获取你的 API 密钥:https://console.anthropic.com/

1. 引言:为什么记忆很重要 {#introduction}

本食谱演示了 AI 代理的有效上下文工程 中描述的上下文工程模式的实践实现。该文章涵盖了为什么上下文是有限资源、注意力预算如何工作,以及构建有效代理的策略——你将在这里看到这些技术的实际应用。

问题

大型语言模型具有有限的上下文窗口(Claude 4 系列模型为 200k 个 token)。虽然这看起来很大,但出现了几个挑战:

解决方案

Claude 4 模型引入了强大的上下文管理功能:

  1. 记忆工具 (memory_20250818):实现跨对话学习
  1. 上下文编辑:通过两种策略自动管理上下文:

好处

构建随着时间的推移在您的特定任务上变得更好的 AI 代理:

可以把它想象成给 Claude 一个笔记本,让它做笔记并参考——就像人类一样。

您将学到什么

在本食谱结束时,您将能够:

1. 引言:为什么记忆很重要 {#introduction}

本手册演示了 AI 代理的有效上下文工程 中描述的上下文工程模式的实践实现。该文章涵盖了为什么上下文是有限资源、注意力预算如何工作,以及构建有效代理的策略——你将在这里看到这些技术的实际应用。

问题

大型语言模型具有有限的上下文窗口(Claude 4 为 200k 个 token)。虽然这看起来很大,但出现了几个挑战:

解决方案

Claude Sonnet 4.6 引入了两个强大的功能:

  1. 记忆工具 (memory_20250818):支持跨对话学习

支持的模型:Claude Opus 4.1 (claude-opus-4-1)、Claude Opus 4 (claude-opus-4)、Claude Sonnet 4.6 (claude-sonnet-4-6)、Claude Sonnet 4 (claude-sonnet-4) 和 Claude Haiku 4.5 (claude-haiku-4-5)

好处

构建能够随着时间的推移在你的特定任务上变得更好的 AI 代理:

可以把它想象成给 Claude 一个笔记本,让它做笔记并参考——就像人类一样。

2. 使用场景 {#use-cases}

记忆与上下文管理能够实现强大的新工作流:

🔍 代码审查助手

📚 研究助手

💬 客户支持机器人

📊 数据分析助手

支持的模型:Claude Opus 4.1 (claude-opus-4-1) 和 Claude Sonnet 4.6 (claude-sonnet-4-6)

本手册重点介绍代码审查助手,因为它清晰地展示了记忆(学习模式)和上下文编辑(处理长审查)两个方面。

3. 快速入门示例 {#quick-start}

让我们通过简单的示例来看看内存和上下文管理的实际应用。

环境设置

首先,安装依赖并配置你的环境:

%%capture
# Install required packages
# Option 1: From requirements.txt
# %pip install -q -r requirements.txt

# Option 2: Direct install
%pip install -q anthropic python-dotenv ipykernel

⚠️ 重要提示:在此目录下创建一个 .env 文件:

# Copy .env.example to .env and add your API key
cp .env.example .env

然后编辑 .env 文件,添加来自 https://console.anthropic.com/ 的 Anthropic API 密钥。

import os
from typing import cast

from anthropic import Anthropic
from dotenv import load_dotenv

# Load environment variables
load_dotenv()

# Model configuration - use alias for automatic updates
MODEL = "claude-sonnet-4-6"  # Can override via ANTHROPIC_MODEL env var
if os.getenv("ANTHROPIC_MODEL"):
    MODEL = os.getenv("ANTHROPIC_MODEL")

if not API_KEY:
    raise ValueError("ANTHROPIC_API_KEY not found. Copy .env.example to .env and add your API key.")

if not MODEL:
    raise ValueError("ANTHROPIC_MODEL not found. Copy .env.example to .env and set the model.")

MODEL = cast(str, MODEL)

client = Anthropic(api_key=API_KEY)

print("✓ API key loaded")
print(f"✓ Using model: {MODEL}")

示例1:基本记忆使用

让我们看看Claude如何使用记忆来存储信息以供将来参考。

辅助函数

这些示例使用了 demo_helpers.py 中的辅助函数:

⚠️ 关于清除记忆的说明

以下单元格会清除所有记忆文件,以便为本演示提供一个干净的环境。这对于多次运行笔记本以获得一致结果非常有用。

在生产应用中,您应仔细考虑是否要清除所有记忆,因为这会永久移除已学习的模式。建议改用选择性删除或将记忆组织到特定项目的目录中。

# Import helper functions
from memory_demo.demo_helpers import (
    run_conversation_loop,
    run_conversation_turn,
    print_context_management_info,
)
from memory_tool import MemoryToolHandler

# Initialize
client = Anthropic()
memory = MemoryToolHandler(base_path="./demo_memory")

# Clear any existing memories to start fresh
print("🧹 Clearing previous memories...")
memory.clear_all_memory()
print("✓ Memory cleared\n")

# Load example code with a race condition bug
with open("memory_demo/sample_code/web_scraper_v1.py", "r") as f:
    code_to_review = f.read()

messages = [
    {
        "role": "user",
        "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```",
    }
]

print("=" * 60)
print("📝 SESSION 1: Learning from a bug")
print("=" * 60)

# Run conversation loop
response = run_conversation_loop(
    client=client,
    model=MODEL,
    messages=messages,
    memory_handler=memory,
    system="You are a code reviewer.",
    max_tokens=2048,
    max_turns=5,
    verbose=True,
)

print("\n" + "=" * 60)
print("✅ Session 1 complete!")
print("=" * 60)

发生了什么?

  1. Claude 检查了它的记忆(首次运行时为空)
  2. 识别出 bug:竞态条件 - 多个线程在没有同步的情况下修改共享状态(self.results 和 self.failed_urls)
  3. 将并发模式存储在记忆中,以备将来参考

现在让我们看看神奇之处——Claude 在一个新的对话中应用这个学到的模式:

示例2:跨对话学习

开启一个全新的对话——记忆依然存在!

# NEW conversation (empty messages)
# Load API client code with similar concurrency issue
with open("memory_demo/sample_code/api_client_v1.py", "r") as f:
    code_to_review = f.read()

messages = [
    {"role": "user", "content": f"Review this API client code:\n\n```python\n{code_to_review}\n```"}
]

print("=" * 60)
print("🚀 SESSION 2: Applying learned pattern")
print("=" * 60)

# Run conversation loop
response = run_conversation_loop(
    client=client,
    model=MODEL,
    messages=messages,
    memory_handler=memory,
    system="You are a code reviewer.",
    max_tokens=2048,
    max_turns=5,
    verbose=True,
)

print("\n" + "=" * 60)
print("✅ Session 2 complete!")
print("=" * 60)

注意区别:

这就是跨对话学习的实际应用!

示例 3:保留记忆的同时清除上下文

在包含许多代码文件的长时间审查会话中会发生什么?

让我们触发上下文编辑,看看 Claude 如何自动管理这一点。

配置说明: 我们使用 clear_at_least: 50 个 token,因为记忆工具操作的结果很小(每个约 50-150 个 token)。在生产环境中,如果工具结果较大(如网络搜索或代码执行),您应使用更高的值,如 3000-5000 个 token。

# Configure context management with BOTH clearing strategies
# Low thresholds for demo - in production use 30-40k tokens
CONTEXT_MANAGEMENT = {
    "edits": [
        # Thinking management MUST come first when combining strategies
        {
            "type": "clear_thinking_20251015",
            "keep": {"type": "thinking_turns", "value": 1}  # Keep only last turn's thinking
        },
        {
            "type": "clear_tool_uses_20250919",
            "trigger": {"type": "input_tokens", "value": 5000},  # Low threshold for demo
            "keep": {"type": "tool_uses", "value": 2},  # Keep last 2 tool uses
            "clear_at_least": {"type": "input_tokens", "value": 2000}
        }
    ]
}

# Extended thinking config (required for clear_thinking strategy)
THINKING = {
    "type": "enabled",
    "budget_tokens": 1024  # Budget for thinking per turn
}

# Continue from previous session - memory persists!
print("=" * 60)
print("📚 SESSION 3: Long review session with context clearing")
print("=" * 60)
print()

# Clean up messages - remove any empty content from previous session
# This ensures we have a valid message state to continue from
cleaned_messages = []
for msg in messages:
    if isinstance(msg.get("content"), list):
        # Filter out empty content blocks
        content = [c for c in msg["content"] if c]
        if content:
            cleaned_messages.append({"role": msg["role"], "content": content})
    elif msg.get("content"):
        cleaned_messages.append(msg)

messages = cleaned_messages

# Review 1: Data processor (larger file)
with open("memory_demo/sample_code/data_processor_v1.py", "r") as f:
    data_processor_code = f.read()

messages.append({
    "role": "user",
    "content": f"Review this data processor:\n\n```python\n{data_processor_code}\n```"
})

print("📝 Review 1: Data processor")
response = run_conversation_turn(
    client=client,
    model=MODEL,
    messages=messages,
    memory_handler=memory,
    system="You are a code reviewer.",
    context_management=CONTEXT_MANAGEMENT,
    thinking=THINKING,
    max_tokens=4096,
    verbose=True
)

# Add response to messages
messages.append({"role": "assistant", "content": response[1]})
if response[2]:
    messages.append({"role": "user", "content": response[2]})

print(f"  📊 Input tokens: {response[0].usage.input_tokens:,}")
context_cleared, saved = print_context_management_info(response[0])
print()

# Review 2: SQL code
with open("memory_demo/sample_code/sql_query_builder.py", "r") as f:
    sql_code = f.read()

messages.append({
    "role": "user",
    "content": f"Review this SQL query builder:\n\n```python\n{sql_code}\n```"
})

print("📝 Review 2: SQL query builder")
response = run_conversation_turn(
    client=client,
    model=MODEL,
    messages=messages,
    memory_handler=memory,
    system="You are a code reviewer.",
    context_management=CONTEXT_MANAGEMENT,
    thinking=THINKING,
    max_tokens=4096,
    verbose=True
)

messages.append({"role": "assistant", "content": response[1]})
if response[2]:
    messages.append({"role": "user", "content": response[2]})

print(f"  📊 Input tokens: {response[0].usage.input_tokens:,}")
context_cleared, saved = print_context_management_info(response[0])
print()

# Review 3: Add one more review to ensure we trigger clearing
with open("memory_demo/sample_code/web_scraper_v1.py", "r") as f:
    scraper_code = f.read()

messages.append({
    "role": "user",
    "content": f"Quick check - any issues here?\n\n```python\n{scraper_code}\n```"
})

print("📝 Review 3: Web scraper (should trigger clearing)")
response = run_conversation_turn(
    client=client,
    model=MODEL,
    messages=messages,
    memory_handler=memory,
    system="You are a code reviewer.",
    context_management=CONTEXT_MANAGEMENT,
    thinking=THINKING,
    max_tokens=4096,
    verbose=True
)

messages.append({"role": "assistant", "content": response[1]})
if response[2]:
    messages.append({"role": "user", "content": response[2]})

print(f"  📊 Input tokens: {response[0].usage.input_tokens:,}")
context_cleared, saved = print_context_management_info(response[0])

print()
print("=" * 60)
print("✅ Session 3 complete!")
print("=" * 60)

刚才发生了什么?

在启用扩展思考的多轮审查中,随着上下文增长,应用了上下文编辑:

  1. 思考块被清除 - 首先移除之前轮次的旧思考
  2. 工具结果被清除 - 当超过阈值时,移除旧的记忆工具结果
  3. 记忆文件完好 - Claude 仍然可以查询已学习的模式
  4. 令牌使用得到管理 - 从思考和工具结果中节省了令牌

这展示了关键优势:

让我们验证记忆在清除后是否仍然存在:

# Verify memory persists after context clearing
import os

print("📂 Memory files in demo_memory/:")
print()

for root, dirs, files in os.walk("./demo_memory"):
    # Calculate relative path for display
    level = root.replace("./demo_memory", "").count(os.sep)
    indent = "  " * level
    folder_name = os.path.basename(root) or "demo_memory"
    print(f"{indent}{folder_name}/")

    sub_indent = "  " * (level + 1)
    for file in files:
        file_path = os.path.join(root, file)
        size = os.path.getsize(file_path)
        print(f"{sub_indent}├── {file} ({size} bytes)")

print()
print("✅ All learned patterns preserved despite context clearing!")

4. 工作原理 {#how-it-works}

记忆工具架构

记忆工具是客户端的——由你控制存储。Claude 发出工具调用,你的应用程序执行它们。

记忆工具命令

| 命令 | 描述 | 示例 |

|---------|-------------|---------|

| view | 显示目录或文件内容 | {"command": "view", "path": "/memories"} |

| create | 创建或覆盖文件 | {"command": "create", "path": "/memories/notes.md", "file_text": "..."} |

| str_replace | 替换文件中的文本 | {"command": "str_replace", "path": "...", "old_str": "...", "new_str": "..."} |

| insert | 在指定行号插入文本 | {"command": "insert", "path": "...", "insert_line": 2, "insert_text": "..."} |

| delete | 删除文件或目录 | {"command": "delete", "path": "/memories/old.txt"} |

| rename | 重命名或移动文件 | {"command": "rename", "old_path": "...", "new_path": "..."} |

完整的实现(包括路径验证和安全措施)请参阅 memory_tool.py。

思维管理(clear_thinking_20251015)

使用扩展思维时,思维块会不断累积并消耗令牌。clear_thinking 策略会自动管理这些思维块。

重要:此策略要求在你的 API 调用中启用 thinking。

API 调用模式(启用扩展思维时):

response = client.beta.messages.create(
    betas=["context-management-2025-06-27"],  # Required beta flag
    model="claude-sonnet-4-6",
    messages=messages,
    tools=[{"type": "memory_20250818", "name": "memory"}],
    thinking={"type": "enabled", "budget_tokens": 10000},  # Enable thinking
    context_management={  # Context editing config
        "edits": [
            {
                "type": "clear_thinking_20251015",
                "keep": {"type": "thinking_turns", "value": 1}  # Keep last turn only
            },
            {
                "type": "clear_tool_uses_20250919",
                "trigger": {"type": "input_tokens", "value": 35000},
                "keep": {"type": "tool_uses", "value": 5}
            }
        ]
    },
    max_tokens=2048
)

关键要点:

理解演示代码

code_review_demo.py 中的关键实现细节:

class CodeReviewAssistant:
    def __init__(self, memory_storage_path="./memory_storage"):
        self.client = Anthropic()
        self.memory_handler = MemoryToolHandler(base_path=memory_storage_path)
        self.messages = []
    
    def review_code(self, code, filename, description=""):
        # 1. Add user message
        self.messages.append({...})
        
        # 2. Conversation loop with tool execution
        while True:
            response = self.client.beta.messages.create(
                model=MODEL,
                system=self._create_system_prompt(),
                messages=self.messages,
                tools=[{"type": "memory_20250818", "name": "memory"}],
                betas=["context-management-2025-06-27"],
                context_management=CONTEXT_MANAGEMENT
            )
            
            # 3. Execute tool uses
            tool_results = []
            for content in response.content:
                if content.type == "tool_use":
                    result = self._execute_tool_use(content)
                    tool_results.append({...})
            
            # 4. Continue if there are tool uses, otherwise done
            if tool_results:
                self.messages.append({"role": "user", "content": tool_results})
            else:
                break

关键模式:只要有工具调用,就持续调用 API,执行这些工具并将结果反馈回去。

Claude 实际学到的东西

这正是记忆强大之处——语义模式识别,而不仅仅是语法:

会话 1:基于线程的网页爬虫

# Bug: Race condition
class WebScraper:
    def __init__(self):
        self.results = []  # Shared state!
    
    def scrape_urls(self, urls):
        with ThreadPoolExecutor() as executor:
            for future in as_completed(futures):
                self.results.append(future.result())  # RACE!

Claude 在记忆中存储的内容(示例文件:/memories/concurrency_patterns/thread_safety.md):

当 Claude 遇到这种模式时,它会将以下见解存储到其记忆文件中:

会话 2:异步 API 客户端(新对话!)

Claude 首先检查记忆,找到线程安全模式,然后:

  1. 识别异步代码中的类似模式(协程也可能交错执行)
  2. 立即应用解决方案(无需重新学习)
  3. 解释时参考已存储的知识
# Claude spots this immediately:
async def fetch_all(self, endpoints):
    for coro in asyncio.as_completed(tasks):
        self.responses.append(await coro)  # Same pattern!

为什么这很重要:

示例代码文件

演示使用这些示例文件(均包含并发/线程安全问题):

让我们看一个:

memory_demo/sample_code/web_scraper_v1.py

"""
Concurrent web scraper with a race condition bug.
Multiple threads modify shared state without synchronization.
"""

import time
from concurrent.futures import ThreadPoolExecutor, as_completed
from typing import List, Dict

import requests


class WebScraper:
    """Web scraper that fetches multiple URLs concurrently."""

    def __init__(self, max_workers: int = 10):
        self.max_workers = max_workers
        self.results = []  # BUG: Shared mutable state accessed by multiple threads!
        self.failed_urls = []  # BUG: Another race condition!

    def fetch_url(self, url: str) -> Dict[str, any]:
        """Fetch a single URL and return the result."""
        try:
            response = requests.get(url, timeout=5)
            response.raise_for_status()
            return {
                "url": url,
                "status": response.status_code,
                "content_length": len(response.content),
            }
        except requests.exceptions.RequestException as e:
            return {"url": url, "error": str(e)}

    def scrape_urls(self, urls: List[str]) -> List[Dict[str, any]]:
        """
        Scrape multiple URLs concurrently.

        BUG: self.results is accessed from multiple threads without locking!
        This causes race conditions where results can be lost or corrupted.
        """
        with ThreadPoolExecutor(max_workers=self.max_workers) as executor:
            futures = [executor.submit(self.fetch_url, url) for url in urls]

            for future in as_completed(futures):
                result = future.result()

                # RACE CONDITION: Multiple threads append to self.results simultaneously
                if "error" in result:
                    self.failed_urls.append(result["url"])  # RACE CONDITION
                else:
                    self.results.append(result)  # RACE CONDITION

        return self.results

Bug:多个线程在没有锁的情况下修改 self.results 和 self.failed_urls!

Claude 将:

  1. 识别竞态条件
  2. 将模式存储在 /memories/concurrency_patterns/thread_safety.md
  3. 在会话 2 中将此并发模式应用于异步代码

演示概览

我们构建了一个完整的代码审查助手。实现位于 memory_demo/code_review_demo.py。

运行交互式演示:

python memory_demo/code_review_demo.py

该演示展示了:

  1. 会话 1:审查带有 bug 的 Python 代码 → Claude 学习该模式
  2. 会话 2:审查类似代码(新对话)→ Claude 应用该模式
  3. 会话 3:长时间审查会话 → 上下文编辑使其保持可管理

7. 最佳实践与安全 {#best-practices}

内存管理

应做:

不应做:

安全:路径遍历防护

关键:始终验证路径以防止目录遍历攻击。参见 memory_tool.py 中的实现。

安全:内存投毒

⚠️ 严重风险:内存文件会被读回 Claude 的上下文中,使其成为提示注入的潜在载体。

缓解策略:

  1. 内容净化:在存储前过滤危险模式
  2. 内存范围隔离:按用户/项目隔离
  3. 内存审计:记录并扫描所有内存操作
  4. 提示工程:指示 Claude 忽略内存中的指令

完整的安全实现参见 memory_tool.py,测试参见 tests/。

结论

你完成了什么

在本教程中,你学会了:

应用这些模式

对于你的项目:

  1. 从单个记忆文件开始,用于存储模式(例如,/memories/patterns.md)
  2. 在生产环境中,将上下文编辑触发器设置为 30-40k 个令牌
  3. 实现按项目隔离记忆,以防止交叉污染

其他应用:

后续步骤

资源

记忆和上下文管理处于 测试阶段。分享您的反馈以帮助我们改进!

常见问题

常见错误:1) 未设置ANTHROPIC_API_KEY导致ValueError,需复制.env.example并配置。2) 组合上下文编辑策略时顺序错误,clear_thinking必须放在首位。3) 启用clear_thinking但未开启thinking参数,导致API报错。4) 路径遍历攻击,需在MemoryToolHandler中实现路径验证。排查方法:检查API返回错误信息,确认beta标志context-management-2025-06-27已设置,验证记忆文件权限和路径。生产优化:提高触发阈值至30-40k,使用keep: "all"最大化缓存命中,定期清理记忆文件。

企业应用扩展

可扩展方向:1) 集成claude-code-action实现GitHub PR自动审查。2) 按用户或项目隔离记忆,防止数据泄露。3) 实现记忆内容净化,过滤提示注入。4) 探索其他应用场景,如客户支持、研究助手、数据分析。5) 结合扩展思考优化复杂推理任务。

总结

本教程面向有编程基础的开发者,深入讲解如何利用Claude Sonnet 4.6的记忆工具和上下文编辑功能,构建跨会话学习和长时间运行的AI代理。通过代码审查助手案例,演示了记忆工具实现跨对话模式学习,以及上下文编辑自动管理上下文窗口,避免信息丢失和成本过高。教程涵盖环境搭建、核心原理、架构设计、最佳实践与安全防护,并提供生产环境优化建议。

内容来源与验证

继续系统学习

站内还有更多完整实战教程

加入会员,解锁全部教程、完整代码与持续更新内容。

加入会员
查看全部AI 智能体教程