<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Claude Code Context Management on On My Way</title>
    <link>https://tuanzi-wow.cn/%E4%B8%8A%E4%B8%8B%E6%96%87%E5%B7%A5%E7%A8%8B/claudecode_context_management_cn/</link>
    <description>Recent content in Claude Code Context Management on On My Way</description>
    <generator>Hugo</generator>
    <language>zh-CN</language>
    <atom:link href="https://tuanzi-wow.cn/%E4%B8%8A%E4%B8%8B%E6%96%87%E5%B7%A5%E7%A8%8B/claudecode_context_management_cn/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>构建编排模式</title>
      <link>https://tuanzi-wow.cn/%E4%B8%8A%E4%B8%8B%E6%96%87%E5%B7%A5%E7%A8%8B/claudecode_context_management_cn/mid-conversation-effort-example/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://tuanzi-wow.cn/%E4%B8%8A%E4%B8%8B%E6%96%87%E5%B7%A5%E7%A8%8B/claudecode_context_management_cn/mid-conversation-effort-example/</guid>
      <description>构建一个会话级模式：为多智能体 fan-out 授予持续性授权，并通过会话中途的 system messages 打开和关闭。</description>
      <content:encoded><![CDATA[<p>编排模式是一个会话级开关：开启时，模型对每一个实质性请求都投入最大程度的彻底性，自行侦察任务，然后默认将工作 fan-out 给并行子代理。关闭时，同一个编排工具恢复为按请求 opt-in。</p>
<p>该模式不是 API 参数。它完全由文档中已有的组件构成：</p>
<ol>
<li><strong>一个 effort 级别：</strong> 请求以文档中的 <a href="https://platform.claude.com/docs/en/build-with-claude/effort">Effort</a> 值运行，例如 <code>xhigh</code>。该页面所列级别之上没有隐藏级别。本示例在每个请求的顶层设置 effort，无需 beta header。</li>
<li><strong>一条模式提醒：</strong> 一条 <a href="https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages">会话中途的 system message</a> 告知模型该模式处于活动状态，每隔若干轮附带一行刷新提醒，并在关闭模式时发送退出通知。顶层 <code>system</code> 字段始终不变，因此缓存前缀保持完整。</li>
<li><strong>工具描述中的持续性授权：</strong> 编排工具的描述写明：模式开启时，模型应为每一个实质性任务编写并运行 workflow，无需事先询问。</li>
</ol>
<Note>
  本示例使用会话中途的 system messages；关于支持它们的模型与平台，见 [会话中途的 system messages](https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages)。fan-out 本身会成倍增加 token 用量：一次请求可以催生许多子代理对话，因此请把该模式留给值得付出成本的工作。
</Note>
<h2 id="设置循环">设置循环</h2>
<p>该示例是单个文件。常量控制 effort 级别、fan-out 形态，以及模式刷新提醒的重发频率。<code>MAX_CONCURRENT</code> 限制同时运行的子代理数量（PHP 移植版是顺序执行并忽略该值）；<code>MAX_TOTAL_SUBTASKS</code> 限制模型在单次 Workflow 调用中可以排队的数量。把两者分开，让模型可以规划大量积压任务，而不必一次全部启动。当设置了环境变量 <code>DOC_TEST_MODE</code> 时，该检查会把循环限制为单轮，以便自动化文档 harness 验证文件能够编译并迅速结束，而无需跑完整编排；你自己运行示例时请保持其未设置。</p>
<CodeGroup>
  ```python Python
  import atexit
  import concurrent.futures
  import hashlib
  import json
  import os
  import shutil
  import subprocess
  import sys
  import tempfile
  import threading
<p>import anthropic</p>
<p>client = anthropic.Anthropic()</p>
<p>MODEL = &ldquo;claude-opus-5&rdquo;
EFFORT = &ldquo;xhigh&rdquo;</p>
<p>SYSTEM_PROMPT = &ldquo;You are a helpful general-purpose agent. Answer the user&rsquo;s request directly.&rdquo;</p>
<p>REQUEST_TIMEOUT_SECONDS = 600
BASH_TIMEOUT_SECONDS = 60
TOOL_RESULT_MAX_CHARS = 8000
MAX_CONCURRENT = 10
DOC_TEST_MODE = bool(os.environ.get(&ldquo;DOC_TEST_MODE&rdquo;))
MAX_TOTAL_SUBTASKS = 2 if DOC_TEST_MODE else 200
MAX_SUBAGENT_TURNS = 1 if DOC_TEST_MODE else 15
MAX_MAIN_TURNS = 1 if DOC_TEST_MODE else 30
TURNS_BETWEEN_REFRESHERS = 10
JOURNAL_PATH = os.environ.get(&ldquo;ORCH_JOURNAL&rdquo;) or &ldquo;orchestration_journal.json&rdquo;</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="o">&lt;/</span><span class="n">CodeGroup</span><span class="o">&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">## 定义模式提醒</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">提醒刻意写得很短。它们切换模式，并指向工具描述——重量级指令就放在那里。全文只在模式开启时发送一次，刷新提醒只在若干用户轮次之后才重发，退出通知在模式关闭时发送一次。</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="o">&lt;</span><span class="n">CodeGroup</span><span class="o">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="err">```</span><span class="n">python</span> <span class="n">Python</span>
</span></span><span class="line"><span class="cl"><span class="n">MODE_ENTER</span> <span class="o">=</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Orchestration mode is on: optimize for the most exhaustive, correct answer rather than &#34;</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;the fastest one. Use the Workflow tool on every substantive task, sized to the problem&#39;s &#34;</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;natural decomposition rather than the maximum the tool allows. See the Workflow tool&#39;s &#34;</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;description for standing consent, granularity guidance, and quality patterns. Work solo &#34;</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;only on conversational or trivial turns.&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">MODE_REFRESH</span> <span class="o">=</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Orchestration mode is still on. Use the Workflow tool; see its standing consent section.&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">MODE_EXIT</span> <span class="o">=</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Orchestration mode is off. The Workflow tool&#39;s standard opt-in rule applies again.&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span></code></pre></td></tr></table>
</div>
</div></CodeGroup>
<h2 id="在工具描述中授予持续性授权">在工具描述中授予持续性授权</h2>
<p>Workflow 工具承载真正的行为契约：opt-in 规则、模式开启期间适用的持续性授权、用于确定 fan-out 规模的粒度指引，以及模型可以取用的质量模式（验证波、完备性批评者、多阶段分步）。子代理还会得到一个 <code>report_findings</code> 工具，使其结果以结构化 JSON 而非散文返回；bash 工具则是 Anthropic 定义的 <code>bash_20250124</code> 工具，在本地运行。</p>
<CodeGroup>
  ```python Python
  WORKFLOW_TOOL = {
      "name": "Workflow",
      "description": (
          "Orchestrate a multiagent workflow: split a large task into independent subtasks "
          "and run them as parallel agents, then collect their results.\n\n"
          "Opt-in: only use this tool when the user explicitly asks for a workflow, or when a "
          "system message confirms that orchestration mode is on.\n\n"
          "Quality patterns: adversarial verification (a second wave of agents checks the first "
          "wave's findings against the source), a completeness critic (one agent hunts for what "
          "the others missed), and multiphase sequencing (understand, design, implement, and "
          "review as separate workflow calls, reading results between phases). A useful default "
          "is hybrid: scout inline first to discover the work-list, then fan out over it.\n\n"
          "Granularity: scope each subtask to a distinct concern, component, or question rather "
          "than per line or per file section. Scale the count to what the user asked for: a "
          "focused review of a module of a few hundred lines rarely needs more than about ten "
          "subtasks; a broad audit of a large codebase can justify more.\n\n"
          "Standing consent: while a system message confirms orchestration mode is on, that "
          "opt-in is standing. Author and run a workflow for every substantive task by default, "
          "and lean toward verifying findings adversarially. Work solo only on conversational "
          "turns or trivial mechanical edits. When a system message says the mode is off, "
          "revert to the opt-in rule above."
      ),
      "input_schema": {
          "type": "object",
          "properties": {
              "subtasks": {
                  "type": "array",
                  "items": {"type": "string"},
                  "description": "Independent subtask prompts to run as parallel agents",
              }
          },
          "required": ["subtasks"],
      },
  }
<p>BASH_TOOL = {&ldquo;type&rdquo;: &ldquo;bash_20250124&rdquo;, &ldquo;name&rdquo;: &ldquo;bash&rdquo;}</p>
<p>REPORT_TOOL = {
&ldquo;name&rdquo;: &ldquo;report_findings&rdquo;,
&ldquo;description&rdquo;: (
&ldquo;Report the final findings for your subtask. Call this exactly once, when you are &quot;
&ldquo;done investigating; it ends your task.&rdquo;
),
&ldquo;input_schema&rdquo;: {
&ldquo;type&rdquo;: &ldquo;object&rdquo;,
&ldquo;properties&rdquo;: {
&ldquo;summary&rdquo;: {&ldquo;type&rdquo;: &ldquo;string&rdquo;, &ldquo;description&rdquo;: &ldquo;Two or three sentences of synthesis&rdquo;},
&ldquo;findings&rdquo;: {
&ldquo;type&rdquo;: &ldquo;array&rdquo;,
&ldquo;items&rdquo;: {
&ldquo;type&rdquo;: &ldquo;object&rdquo;,
&ldquo;properties&rdquo;: {
&ldquo;claim&rdquo;: {&ldquo;type&rdquo;: &ldquo;string&rdquo;, &ldquo;description&rdquo;: &ldquo;The finding, one sentence&rdquo;},
&ldquo;evidence&rdquo;: {
&ldquo;type&rdquo;: &ldquo;string&rdquo;,
&ldquo;description&rdquo;: &ldquo;How it was verified (file, line, or command output)&rdquo;,
},
&ldquo;severity&rdquo;: {&ldquo;type&rdquo;: &ldquo;string&rdquo;, &ldquo;enum&rdquo;: [&ldquo;high&rdquo;, &ldquo;medium&rdquo;, &ldquo;low&rdquo;, &ldquo;info&rdquo;]},
},
&ldquo;required&rdquo;: [&ldquo;claim&rdquo;, &ldquo;evidence&rdquo;, &ldquo;severity&rdquo;],
},
},
},
&ldquo;required&rdquo;: [&ldquo;summary&rdquo;, &ldquo;findings&rdquo;],
},
}</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span><span class="lnt">45
</span><span class="lnt">46
</span><span class="lnt">47
</span><span class="lnt">48
</span><span class="lnt">49
</span><span class="lnt">50
</span><span class="lnt">51
</span><span class="lnt">52
</span><span class="lnt">53
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-mysql" data-lang="mysql"><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="o">&lt;/</span><span class="n">CodeGroup</span><span class="o">&gt;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="c1">## 在本地运行 bash 工具
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="n">bash</span><span class="w"> </span><span class="err">处理器以超时运行所请求的命令，捕获合并后的</span><span class="w"> </span><span class="n">stdout</span><span class="w"> </span><span class="err">和</span><span class="w"> </span><span class="n">stderr</span><span class="err">，并截断结果，以免失控命令淹没上下文窗口。命令在你启动示例时所在的目录中运行，因此要指向某个项目，就从那里启动；当设置了</span><span class="w"> </span><span class="o">`</span><span class="n">DOC_TEST_MODE</span><span class="o">`</span><span class="w"> </span><span class="err">时，</span><span class="n">harness</span><span class="w"> </span><span class="err">会改为给</span><span class="w"> </span><span class="n">bash</span><span class="w"> </span><span class="err">一个退出时删除的小型一次性夹具目录。这里没有沙箱：命令以启动该示例的进程的权限运行。为清晰起见，本示例在全新的</span><span class="w"> </span><span class="n">subshell</span><span class="w"> </span><span class="err">中运行每一次调用，而不是维护</span><span class="w"> </span><span class="o">`</span><span class="n">bash_20250124</span><span class="o">`</span><span class="w"> </span><span class="err">契约所描述的持久会话；生产级代理应用长生命周期</span><span class="w"> </span><span class="n">shell</span><span class="w"> </span><span class="err">支撑该工具，使工作目录、环境以及</span><span class="w"> </span><span class="o">`</span><span class="n">restart</span><span class="o">`</span><span class="w"> </span><span class="err">动作按文档行为。</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="o">&lt;</span><span class="n">CodeGroup</span><span class="o">&gt;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="o">```</span><span class="n">python</span><span class="w"> </span><span class="n">Python</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="c1"># Run bash where the example was launched. In DOC_TEST_MODE the docs harness
</span></span></span><span class="line"><span class="cl"><span class="c1"># points it at a throwaway fixture directory instead, removed on exit.
</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="w"> </span><span class="n">DOC_TEST_MODE</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">WORK_DIR</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">tempfile</span><span class="p">.</span><span class="nf">mkdtemp</span><span class="p">(</span><span class="n">prefix</span><span class="o">=</span><span class="s2">&#34;orchestration-&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">atexit</span><span class="p">.</span><span class="nf">register</span><span class="p">(</span><span class="n">shutil</span><span class="p">.</span><span class="n">rmtree</span><span class="p">,</span><span class="w"> </span><span class="n">WORK_DIR</span><span class="p">,</span><span class="w"> </span><span class="n">ignore_errors</span><span class="o">=</span><span class="no">True</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="k">with</span><span class="w"> </span><span class="nf">open</span><span class="p">(</span><span class="n">os</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="k">join</span><span class="p">(</span><span class="n">WORK_DIR</span><span class="p">,</span><span class="w"> </span><span class="s2">&#34;sample.py&#34;</span><span class="p">),</span><span class="w"> </span><span class="s2">&#34;w&#34;</span><span class="p">)</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="n">fixture</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">fixture</span><span class="p">.</span><span class="k">write</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="s2">&#34;def fib(n):\n&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="s2">&#34;    return n if n &lt; 2 else fib(n - 1) + fib(n - 2)\n\n&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="s2">&#34;print(fib(10))\n&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">WORK_DIR</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">os</span><span class="p">.</span><span class="nf">getcwd</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="n">def</span><span class="w"> </span><span class="nf">run_bash</span><span class="p">(</span><span class="n">command</span><span class="p">:</span><span class="w"> </span><span class="n">str</span><span class="p">)</span><span class="w"> </span><span class="o">-&gt;</span><span class="w"> </span><span class="n">tuple</span><span class="p">[</span><span class="n">str</span><span class="p">,</span><span class="w"> </span><span class="kt">bool</span><span class="p">]:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="s2">&#34;&#34;&#34;Run a shell command and return (output, is_error). No sandbox: example code only.&#34;&#34;&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nf">print</span><span class="p">(</span><span class="n">f</span><span class="s2">&#34;[bash] {command}&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">file</span><span class="o">=</span><span class="n">sys</span><span class="p">.</span><span class="n">stderr</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">try</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">proc</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">subprocess</span><span class="p">.</span><span class="nf">run</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">[</span><span class="s2">&#34;bash&#34;</span><span class="p">,</span><span class="w"> </span><span class="s2">&#34;-c&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">command</span><span class="p">],</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">cwd</span><span class="o">=</span><span class="n">WORK_DIR</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">capture_output</span><span class="o">=</span><span class="no">True</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="kt">text</span><span class="o">=</span><span class="no">True</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">errors</span><span class="o">=</span><span class="s2">&#34;replace&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">timeout</span><span class="o">=</span><span class="n">BASH_TIMEOUT_SECONDS</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">except</span><span class="w"> </span><span class="n">subprocess</span><span class="p">.</span><span class="n">TimeoutExpired</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="n">f</span><span class="s2">&#34;command timed out after {BASH_TIMEOUT_SECONDS}s&#34;</span><span class="p">,</span><span class="w"> </span><span class="no">True</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">output</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">proc</span><span class="p">.</span><span class="n">stdout</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">proc</span><span class="p">.</span><span class="n">stderr</span><span class="p">).</span><span class="nf">strip</span><span class="p">()</span><span class="w"> </span><span class="k">or</span><span class="w"> </span><span class="s2">&#34;(no output)&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="nf">len</span><span class="p">(</span><span class="n">output</span><span class="p">)</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">TOOL_RESULT_MAX_CHARS</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">output</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">output</span><span class="p">[:</span><span class="n">TOOL_RESULT_MAX_CHARS</span><span class="p">]</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">f</span><span class="s2">&#34;\n(truncated at {TOOL_RESULT_MAX_CHARS} chars)&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="n">proc</span><span class="p">.</span><span class="n">returncode</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="mi">0</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">output</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">f</span><span class="s2">&#34;(exit code {proc.returncode})\n{output}&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="n">output</span><span class="p">,</span><span class="w"> </span><span class="n">proc</span><span class="p">.</span><span class="n">returncode</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="mi">0</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="n">def</span><span class="w"> </span><span class="nf">handle_bash_block</span><span class="p">(</span><span class="n">block</span><span class="p">)</span><span class="w"> </span><span class="o">-&gt;</span><span class="w"> </span><span class="n">tuple</span><span class="p">[</span><span class="n">str</span><span class="p">,</span><span class="w"> </span><span class="kt">bool</span><span class="p">]:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="n">block</span><span class="p">.</span><span class="n">input</span><span class="p">.</span><span class="nf">get</span><span class="p">(</span><span class="s2">&#34;restart&#34;</span><span class="p">)</span><span class="w"> </span><span class="k">is</span><span class="w"> </span><span class="no">True</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="s2">&#34;Shell restarted.&#34;</span><span class="p">,</span><span class="w"> </span><span class="no">False</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">command</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">block</span><span class="p">.</span><span class="n">input</span><span class="p">.</span><span class="nf">get</span><span class="p">(</span><span class="s2">&#34;command&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="k">not</span><span class="w"> </span><span class="nf">isinstance</span><span class="p">(</span><span class="n">command</span><span class="p">,</span><span class="w"> </span><span class="n">str</span><span class="p">)</span><span class="w"> </span><span class="k">or</span><span class="w"> </span><span class="k">not</span><span class="w"> </span><span class="n">command</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="s2">&#34;bash error: no command was provided.&#34;</span><span class="p">,</span><span class="w"> </span><span class="no">True</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nf">run_bash</span><span class="p">(</span><span class="n">command</span><span class="p">)</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div></CodeGroup>
<h2 id="运行一个子代理">运行一个子代理</h2>
<p>每一个 workflow 子任务都会变成带 bash 工具的小型代理循环，并以与主循环相同的 effort 运行。每次 API 调用都有按请求的超时上限，因此连接中断只会让一个子代理降级，而不会卡住整次运行。</p>
<CodeGroup>
  ```python Python
  def run_subagent(model: str, prompt: str) -> str:
      """One subagent: a small nested agent loop with the bash tool plus report_findings.
      Subagents inherit the main loop's effort level."""
      subagent_system = (
          "You are one agent in a larger parallel fan-out, assigned a single subtask. "
          "Investigate it directly, using bash to check facts rather than guessing, and finish "
          "by calling report_findings exactly once. Return findings, not narration."
      )
      messages = [{"role": "user", "content": prompt}]
      for _ in range(MAX_SUBAGENT_TURNS):
          with client.messages.stream(
              model=model,
              max_tokens=64000,
              system=subagent_system,
              output_config={"effort": EFFORT},
              tools=[BASH_TOOL, REPORT_TOOL],
              messages=messages,
              timeout=REQUEST_TIMEOUT_SECONDS,
          ) as stream:
              response = stream.get_final_message()
          messages.append({"role": "assistant", "content": response.content})
          if response.stop_reason == "pause_turn":
              continue
          if response.stop_reason != "tool_use":
              text = "".join(block.text for block in response.content if block.type == "text")
              if response.stop_reason == "max_tokens":
                  text += "\n\n(warning: subagent response was truncated at max_tokens)"
              return text
          tool_results = []
          report = None
          for block in response.content:
              if block.type != "tool_use":
                  continue
              if block.name == "report_findings":
                  report = json.dumps(block.input, indent=2)
                  output, is_error = "Findings recorded.", False
              elif block.name == "bash":
                  output, is_error = handle_bash_block(block)
              else:
                  output, is_error = f"unknown tool: {block.name}", True
              tool_results.append(
                  {
                      "type": "tool_result",
                      "tool_use_id": block.id,
                      "content": output,
                      "is_error": is_error,
                  }
              )
          if report is not None:
              return report
          messages.append({"role": "user", "content": tool_results})
      return "(subagent hit the turn limit before finishing)"
  ```
</CodeGroup>
<h2 id="将结果写入-journal以便重跑时续跑">将结果写入 journal，以便重跑时续跑</h2>
<p>催生数十个子代理的 fan-out，从头重启代价很高。一个小型内容寻址 journal 使其幂等：在派发子代理之前，在本地 JSON 文件中查找其 prompt 的 SHA-256，若已有记录则返回该结果。中断运行后再重跑，只有从未完成的子任务才会被重新计算。journal 在多次运行之间去重，而不是在单次 fan-out 波次之内；删除 journal 文件即可重新开始。</p>
<CodeGroup>
  ```python Python
  _journal_lock = threading.Lock()
<p>def _load_journal() -&gt; dict:
try:
with open(JOURNAL_PATH) as file:
return json.load(file) or {}
except (OSError, json.JSONDecodeError):
return {}</p>
<p>def journaled(prompt: str, compute) -&gt; str:
&ldquo;&ldquo;&ldquo;Return a cached result for this exact prompt, or compute and persist it. This
makes the fan-out resumable: interrupt the run, rerun it, and only the subtasks
that never finished are recomputed. Delete the journal file to start fresh.&rdquo;&rdquo;&rdquo;
key = hashlib.sha256(prompt.encode()).hexdigest()
cached = _load_journal().get(key)
if cached is not None:
print(f&rdquo;[journal] cache hit for {key[:12]}&quot;, file=sys.stderr)
return cached
result = compute()
try:
with _journal_lock:  # fan-out writes from many threads
journal = _load_journal()
journal[key] = result
temp = f&quot;{JOURNAL_PATH}.tmp&quot;
with open(temp, &ldquo;w&rdquo;) as file:
json.dump(journal, file)
os.replace(temp, JOURNAL_PATH)  # atomic on POSIX and Windows
except OSError as error:  # the journal is best-effort; never discard a computed result
print(f&quot;[journal] write failed: {error}&quot;, file=sys.stderr)
return result</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span><span class="lnt">45
</span><span class="lnt">46
</span><span class="lnt">47
</span><span class="lnt">48
</span><span class="lnt">49
</span><span class="lnt">50
</span><span class="lnt">51
</span><span class="lnt">52
</span><span class="lnt">53
</span><span class="lnt">54
</span><span class="lnt">55
</span><span class="lnt">56
</span><span class="lnt">57
</span><span class="lnt">58
</span><span class="lnt">59
</span><span class="lnt">60
</span><span class="lnt">61
</span><span class="lnt">62
</span><span class="lnt">63
</span><span class="lnt">64
</span><span class="lnt">65
</span><span class="lnt">66
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="o">&lt;/</span><span class="n">CodeGroup</span><span class="o">&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">## 先 fan-out，再验证</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">fan</span><span class="o">-</span><span class="n">out</span> <span class="err">最多接受</span> <span class="err">`</span><span class="n">MAX_TOTAL_SUBTASKS</span><span class="err">`</span> <span class="err">条</span> <span class="n">prompt</span><span class="err">，经</span> <span class="n">journal</span> <span class="err">运行，同时进行中的不超过</span> <span class="err">`</span><span class="n">MAX_CONCURRENT</span><span class="err">`</span> <span class="err">个（</span><span class="n">PHP</span> <span class="err">移植版为顺序执行），并隔离失败，使一个损坏的子代理降级为错误字符串，而不是结束整次运行。第一波完成后，第二波复用同一条子代理路径，试图反驳每一条结果：每个验证者从源头重新推导这些论断，不确定时默认判定为已反驳。原始结果及其裁决都会返回给编排器，以便一并权衡。</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="o">&lt;</span><span class="n">CodeGroup</span><span class="o">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="err">```</span><span class="n">python</span> <span class="n">Python</span>
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">normalize_subtasks</span><span class="p">(</span><span class="n">raw</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">list</span><span class="p">[</span><span class="nb">str</span><span class="p">]:</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;&#34;&#34;Accept the subtasks input in whatever shape the model emits: an array, the array
</span></span></span><span class="line"><span class="cl"><span class="s2">    JSON-encoded as a single string, or a newline-separated list.&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="n">isinstance</span><span class="p">(</span><span class="n">raw</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="n">try</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="n">raw</span> <span class="o">=</span> <span class="n">json</span><span class="o">.</span><span class="n">loads</span><span class="p">(</span><span class="n">raw</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">except</span> <span class="n">json</span><span class="o">.</span><span class="n">JSONDecodeError</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="n">raw</span> <span class="o">=</span> <span class="n">raw</span><span class="o">.</span><span class="n">splitlines</span><span class="p">()</span> <span class="k">if</span> <span class="s2">&#34;</span><span class="se">\n</span><span class="s2">&#34;</span> <span class="ow">in</span> <span class="n">raw</span> <span class="k">else</span> <span class="p">[</span><span class="n">raw</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="ow">not</span> <span class="n">isinstance</span><span class="p">(</span><span class="n">raw</span><span class="p">,</span> <span class="n">list</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="p">[</span><span class="n">task</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span> <span class="k">for</span> <span class="n">task</span> <span class="ow">in</span> <span class="n">raw</span> <span class="k">if</span> <span class="n">isinstance</span><span class="p">(</span><span class="n">task</span><span class="p">,</span> <span class="nb">str</span><span class="p">)</span> <span class="ow">and</span> <span class="n">task</span><span class="o">.</span><span class="n">strip</span><span class="p">()]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">verify_prompt_for</span><span class="p">(</span><span class="n">subtask</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">result</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;Adversarially verify the subagent result below: try to REFUTE it. Re-derive the &#34;</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;claims yourself with bash rather than trusting the result, and look for evidence &#34;</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;that contradicts them. Default to refuted if uncertain. Call report_findings with &#34;</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;summary &#39;refuted: &lt;why&gt;&#39; or &#39;confirmed: &lt;why&gt;&#39;, citing the file:line or command &#34;</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;output that decided it.</span><span class="se">\n\n</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="n">f</span><span class="s2">&#34;Subtask: {subtask}</span><span class="se">\n\n</span><span class="s2">Result to verify:</span><span class="se">\n</span><span class="s2">{result}&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">run_workflow</span><span class="p">(</span><span class="n">model</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">raw_subtasks</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">tuple</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="ne">bool</span><span class="p">]:</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;&#34;&#34;Run subtasks as parallel subagents, then run a second verification wave over
</span></span></span><span class="line"><span class="cl"><span class="s2">    the results, and return both. MAX_TOTAL_SUBTASKS bounds how many the model can
</span></span></span><span class="line"><span class="cl"><span class="s2">    queue; MAX_CONCURRENT bounds how many run at once.&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="n">all_subtasks</span> <span class="o">=</span> <span class="n">normalize_subtasks</span><span class="p">(</span><span class="n">raw_subtasks</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">subtasks</span> <span class="o">=</span> <span class="n">all_subtasks</span><span class="p">[:</span><span class="n">MAX_TOTAL_SUBTASKS</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="n">dropped</span> <span class="o">=</span> <span class="n">len</span><span class="p">(</span><span class="n">all_subtasks</span><span class="p">)</span> <span class="o">-</span> <span class="n">len</span><span class="p">(</span><span class="n">subtasks</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="ow">not</span> <span class="n">subtasks</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="s2">&#34;Workflow error: no usable subtasks were provided.&#34;</span><span class="p">,</span> <span class="n">True</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="n">f</span><span class="s2">&#34;[workflow] fanning out {len(subtasks)} agents&#34;</span><span class="p">,</span> <span class="n">file</span><span class="o">=</span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">run_one</span><span class="p">(</span><span class="n">prompt</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">try</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="n">journaled</span><span class="p">(</span><span class="n">prompt</span><span class="p">,</span> <span class="n">lambda</span><span class="p">:</span> <span class="n">run_subagent</span><span class="p">(</span><span class="n">model</span><span class="p">,</span> <span class="n">prompt</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">        <span class="n">except</span> <span class="n">Exception</span> <span class="n">as</span> <span class="n">error</span><span class="p">:</span>  <span class="c1"># isolation boundary: one bad subagent should not end the run</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="n">f</span><span class="s2">&#34;(subagent failed: {type(error).__name__}: {error})&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">with</span> <span class="n">concurrent</span><span class="o">.</span><span class="n">futures</span><span class="o">.</span><span class="n">ThreadPoolExecutor</span><span class="p">(</span><span class="n">max_workers</span><span class="o">=</span><span class="n">MAX_CONCURRENT</span><span class="p">)</span> <span class="n">as</span> <span class="n">pool</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">results</span> <span class="o">=</span> <span class="n">list</span><span class="p">(</span><span class="n">pool</span><span class="o">.</span><span class="n">map</span><span class="p">(</span><span class="n">run_one</span><span class="p">,</span> <span class="n">subtasks</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="n">f</span><span class="s2">&#34;[workflow] verifying {len(results)} results&#34;</span><span class="p">,</span> <span class="n">file</span><span class="o">=</span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">verify_prompts</span> <span class="o">=</span> <span class="p">[</span><span class="n">verify_prompt_for</span><span class="p">(</span><span class="n">task</span><span class="p">,</span> <span class="n">result</span><span class="p">)</span> <span class="k">for</span> <span class="n">task</span><span class="p">,</span> <span class="n">result</span> <span class="ow">in</span> <span class="n">zip</span><span class="p">(</span><span class="n">subtasks</span><span class="p">,</span> <span class="n">results</span><span class="p">)]</span>
</span></span><span class="line"><span class="cl">        <span class="n">verdicts</span> <span class="o">=</span> <span class="n">list</span><span class="p">(</span><span class="n">pool</span><span class="o">.</span><span class="n">map</span><span class="p">(</span><span class="n">run_one</span><span class="p">,</span> <span class="n">verify_prompts</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">joined</span> <span class="o">=</span> <span class="s2">&#34;</span><span class="se">\n\n</span><span class="s2">&#34;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="n">f</span><span class="s2">&#34;[agent {index + 1}: {task}]</span><span class="se">\n</span><span class="s2">{result}</span><span class="se">\n\n</span><span class="s2">[verify {index + 1}]</span><span class="se">\n</span><span class="s2">{verdict}&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="n">index</span><span class="p">,</span> <span class="p">(</span><span class="n">task</span><span class="p">,</span> <span class="n">result</span><span class="p">,</span> <span class="n">verdict</span><span class="p">)</span> <span class="ow">in</span> <span class="n">enumerate</span><span class="p">(</span><span class="n">zip</span><span class="p">(</span><span class="n">subtasks</span><span class="p">,</span> <span class="n">results</span><span class="p">,</span> <span class="n">verdicts</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="n">dropped</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">joined</span> <span class="o">=</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl">            <span class="n">f</span><span class="s2">&#34;(note: {dropped} subtasks beyond MAX_TOTAL_SUBTASKS={MAX_TOTAL_SUBTASKS} were not &#34;</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;run; rerun them in a follow-up Workflow call)</span><span class="se">\n\n</span><span class="s2">&#34;</span> <span class="o">+</span> <span class="n">joined</span>
</span></span><span class="line"><span class="cl">        <span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">joined</span><span class="p">,</span> <span class="n">False</span>
</span></span></code></pre></td></tr></table>
</div>
</div></CodeGroup>
<h2 id="用会话中途的-system-messages-切换模式">用会话中途的 system messages 切换模式</h2>
<p>代理先追加用户消息，再追加本轮应付的任何 system messages：退出通知、进入时的完整模式文本，或周期性刷新提醒。把 system message 放在用户轮次之后，可使它前面的每一个缓存字节保持未动，并满足 system message 跟在用户轮次之后的放置规则。</p>
<CodeGroup>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span><span class="lnt">45
</span><span class="lnt">46
</span><span class="lnt">47
</span><span class="lnt">48
</span><span class="lnt">49
</span><span class="lnt">50
</span><span class="lnt">51
</span><span class="lnt">52
</span><span class="lnt">53
</span><span class="lnt">54
</span><span class="lnt">55
</span><span class="lnt">56
</span><span class="lnt">57
</span><span class="lnt">58
</span><span class="lnt">59
</span><span class="lnt">60
</span><span class="lnt">61
</span><span class="lnt">62
</span><span class="lnt">63
</span><span class="lnt">64
</span><span class="lnt">65
</span><span class="lnt">66
</span><span class="lnt">67
</span><span class="lnt">68
</span><span class="lnt">69
</span><span class="lnt">70
</span><span class="lnt">71
</span><span class="lnt">72
</span><span class="lnt">73
</span><span class="lnt">74
</span><span class="lnt">75
</span><span class="lnt">76
</span><span class="lnt">77
</span><span class="lnt">78
</span><span class="lnt">79
</span><span class="lnt">80
</span><span class="lnt">81
</span><span class="lnt">82
</span><span class="lnt">83
</span><span class="lnt">84
</span><span class="lnt">85
</span><span class="lnt">86
</span><span class="lnt">87
</span><span class="lnt">88
</span><span class="lnt">89
</span><span class="lnt">90
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">ModeAgent</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;&#34;&#34;An agent loop whose orchestration mode is toggled with mid-conversation system messages.&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">model</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">mode_on</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">True</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">model</span> <span class="o">=</span> <span class="n">model</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">mode_on</span> <span class="o">=</span> <span class="n">mode_on</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">messages</span><span class="p">:</span> <span class="nb">list</span><span class="p">[</span><span class="nb">dict</span><span class="p">]</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">_mode_announced</span> <span class="o">=</span> <span class="kc">False</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">_exit_pending</span> <span class="o">=</span> <span class="kc">False</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">_turns_since_reminder</span> <span class="o">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">set_mode</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">mode_on</span><span class="p">:</span> <span class="nb">bool</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;&#34;&#34;Turn the mode on or off. The notice is delivered with the next user turn.&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="n">mode_on</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">mode_on</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="ow">not</span> <span class="n">mode_on</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_mode_announced</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">                <span class="bp">self</span><span class="o">.</span><span class="n">_exit_pending</span> <span class="o">=</span> <span class="kc">True</span>
</span></span><span class="line"><span class="cl">        <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="bp">self</span><span class="o">.</span><span class="n">_exit_pending</span> <span class="o">=</span> <span class="kc">False</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">mode_on</span> <span class="o">=</span> <span class="n">mode_on</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">_due_system_messages</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">list</span><span class="p">[</span><span class="nb">dict</span><span class="p">]:</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;&#34;&#34;System messages owed on this turn: an exit notice, the full mode text on entry,
</span></span></span><span class="line"><span class="cl"><span class="s2">        or a one-line refresher every TURNS_BETWEEN_REFRESHERS user turns.&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="n">due</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_exit_pending</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="bp">self</span><span class="o">.</span><span class="n">_exit_pending</span> <span class="o">=</span> <span class="kc">False</span>
</span></span><span class="line"><span class="cl">            <span class="bp">self</span><span class="o">.</span><span class="n">_mode_announced</span> <span class="o">=</span> <span class="kc">False</span>
</span></span><span class="line"><span class="cl">            <span class="n">due</span><span class="o">.</span><span class="n">append</span><span class="p">({</span><span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;system&#34;</span><span class="p">,</span> <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="n">MODE_EXIT</span><span class="p">})</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">mode_on</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">_mode_announced</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">                <span class="bp">self</span><span class="o">.</span><span class="n">_mode_announced</span> <span class="o">=</span> <span class="kc">True</span>
</span></span><span class="line"><span class="cl">                <span class="bp">self</span><span class="o">.</span><span class="n">_turns_since_reminder</span> <span class="o">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl">                <span class="n">due</span><span class="o">.</span><span class="n">append</span><span class="p">({</span><span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;system&#34;</span><span class="p">,</span> <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="n">MODE_ENTER</span><span class="p">})</span>
</span></span><span class="line"><span class="cl">            <span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">_turns_since_reminder</span> <span class="o">&gt;=</span> <span class="n">TURNS_BETWEEN_REFRESHERS</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">                <span class="bp">self</span><span class="o">.</span><span class="n">_turns_since_reminder</span> <span class="o">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl">                <span class="n">due</span><span class="o">.</span><span class="n">append</span><span class="p">({</span><span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;system&#34;</span><span class="p">,</span> <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="n">MODE_REFRESH</span><span class="p">})</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">due</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">turn</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">user_input</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="c1"># Mid-conversation system messages follow the user turn they apply to, which keeps</span>
</span></span><span class="line"><span class="cl">        <span class="c1"># the cached prefix ahead of them untouched.</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">messages</span><span class="o">.</span><span class="n">append</span><span class="p">({</span><span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span> <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="n">user_input</span><span class="p">})</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">messages</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_due_system_messages</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">_turns_since_reminder</span> <span class="o">+=</span> <span class="mi">1</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">MAX_MAIN_TURNS</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">            <span class="k">with</span> <span class="n">client</span><span class="o">.</span><span class="n">messages</span><span class="o">.</span><span class="n">stream</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">                <span class="n">model</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">model</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="n">max_tokens</span><span class="o">=</span><span class="mi">64000</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="n">system</span><span class="o">=</span><span class="n">SYSTEM_PROMPT</span><span class="p">,</span>  <span class="c1"># static for the whole session</span>
</span></span><span class="line"><span class="cl">                <span class="n">output_config</span><span class="o">=</span><span class="p">{</span><span class="s2">&#34;effort&#34;</span><span class="p">:</span> <span class="n">EFFORT</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">                <span class="n">tools</span><span class="o">=</span><span class="p">[</span><span class="n">WORKFLOW_TOOL</span><span class="p">,</span> <span class="n">BASH_TOOL</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">                <span class="n">messages</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">messages</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="n">timeout</span><span class="o">=</span><span class="n">REQUEST_TIMEOUT_SECONDS</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="p">)</span> <span class="k">as</span> <span class="n">stream</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">                <span class="n">response</span> <span class="o">=</span> <span class="n">stream</span><span class="o">.</span><span class="n">get_final_message</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">            <span class="bp">self</span><span class="o">.</span><span class="n">messages</span><span class="o">.</span><span class="n">append</span><span class="p">({</span><span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;assistant&#34;</span><span class="p">,</span> <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="n">response</span><span class="o">.</span><span class="n">content</span><span class="p">})</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="n">response</span><span class="o">.</span><span class="n">stop_reason</span> <span class="o">==</span> <span class="s2">&#34;pause_turn&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">                <span class="k">continue</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="n">response</span><span class="o">.</span><span class="n">stop_reason</span> <span class="o">!=</span> <span class="s2">&#34;tool_use&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">                <span class="n">text</span> <span class="o">=</span> <span class="s2">&#34;&#34;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">block</span><span class="o">.</span><span class="n">text</span> <span class="k">for</span> <span class="n">block</span> <span class="ow">in</span> <span class="n">response</span><span class="o">.</span><span class="n">content</span> <span class="k">if</span> <span class="n">block</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="s2">&#34;text&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                <span class="k">if</span> <span class="n">response</span><span class="o">.</span><span class="n">stop_reason</span> <span class="o">==</span> <span class="s2">&#34;max_tokens&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">                    <span class="c1"># Drop the truncated assistant message so later turns don&#39;t build on it.</span>
</span></span><span class="line"><span class="cl">                    <span class="bp">self</span><span class="o">.</span><span class="n">messages</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">                    <span class="n">text</span> <span class="o">+=</span> <span class="s2">&#34;</span><span class="se">\n\n</span><span class="s2">(warning: response was truncated at max_tokens)&#34;</span>
</span></span><span class="line"><span class="cl">                <span class="k">return</span> <span class="n">text</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">            <span class="n">tool_results</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl">            <span class="k">for</span> <span class="n">block</span> <span class="ow">in</span> <span class="n">response</span><span class="o">.</span><span class="n">content</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">                <span class="k">if</span> <span class="n">block</span><span class="o">.</span><span class="n">type</span> <span class="o">!=</span> <span class="s2">&#34;tool_use&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">                    <span class="k">continue</span>
</span></span><span class="line"><span class="cl">                <span class="k">if</span> <span class="n">block</span><span class="o">.</span><span class="n">name</span> <span class="o">==</span> <span class="s2">&#34;Workflow&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">                    <span class="n">output</span><span class="p">,</span> <span class="n">is_error</span> <span class="o">=</span> <span class="n">run_workflow</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">model</span><span class="p">,</span> <span class="n">block</span><span class="o">.</span><span class="n">input</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&#34;subtasks&#34;</span><span class="p">,</span> <span class="p">[]))</span>
</span></span><span class="line"><span class="cl">                <span class="k">elif</span> <span class="n">block</span><span class="o">.</span><span class="n">name</span> <span class="o">==</span> <span class="s2">&#34;bash&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">                    <span class="n">output</span><span class="p">,</span> <span class="n">is_error</span> <span class="o">=</span> <span class="n">handle_bash_block</span><span class="p">(</span><span class="n">block</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">                    <span class="n">output</span><span class="p">,</span> <span class="n">is_error</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">&#34;unknown tool: </span><span class="si">{</span><span class="n">block</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">,</span> <span class="kc">True</span>
</span></span><span class="line"><span class="cl">                <span class="n">tool_results</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">                    <span class="p">{</span>
</span></span><span class="line"><span class="cl">                        <span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;tool_result&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                        <span class="s2">&#34;tool_use_id&#34;</span><span class="p">:</span> <span class="n">block</span><span class="o">.</span><span class="n">id</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                        <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="n">output</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                        <span class="s2">&#34;is_error&#34;</span><span class="p">:</span> <span class="n">is_error</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                    <span class="p">}</span>
</span></span><span class="line"><span class="cl">                <span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="bp">self</span><span class="o">.</span><span class="n">messages</span><span class="o">.</span><span class="n">append</span><span class="p">({</span><span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span> <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="n">tool_results</span><span class="p">})</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="s2">&#34;(hit the main loop turn limit before finishing)&#34;</span>
</span></span></code></pre></td></tr></table>
</div>
</div></CodeGroup>
<h2 id="运行它">运行它</h2>
<Warning>
  本示例中的 bash 工具会在你的机器上直接运行模型编写的命令，没有沙箱，而且 fan-out 会并行运行若干这样的代理。请在你愿意暴露的目录和环境中运行，并在把它改造成超出本地实验用途之前加上沙箱。
</Warning>
<CodeGroup>
  ```python Python
  if __name__ == "__main__":
      task = (
          sys.argv[1]
          if len(sys.argv) > 1
          else "Explore the current directory, then give a thorough review: what it does, "
          "code-quality issues, and concrete improvements."
      )
      agent = ModeAgent(MODEL)
      print(agent.turn(task))
      agent.set_mode(False)
      print(agent.turn("Briefly summarize what you found above, no fan-out needed."))
  ```
</CodeGroup>
<p>从你希望代理工作的目录启动该示例，例如要审查的仓库根目录：</p>
<p>模式开启时，预期模型会用几条 bash 命令侦察，主动派发 Workflow 工具，并把子代理报告综合成最终答案。琐碎或对话性请求会保持单独处理，正如提醒所指示的。</p>
<h2 id="迈向生产级-harness">迈向生产级 harness</h2>
<p>本示例刻意保持精简。面向真实工作负载的 harness 通常还会加上：</p>
<ul>
<li><strong>带沙箱的编排脚本：</strong> 让模型发出一段简短的编排程序（分支、循环和 reduce 步骤），并在隔离的解释器中运行，而不是只接受扁平的子任务字符串列表。</li>
<li><strong>持久 journaling：</strong> 用能在进程重启后存活、且在跨机器并发写入下安全的存储，替换本地 JSON 文件。</li>
<li><strong>预算强制：</strong> 跟踪整个会话中启动的子代理总数，而不只是每次 Workflow 调用，并拒绝超过硬上限，以免失控计划耗尽你的配额。</li>
</ul>
<p>本示例中的模式（模式提醒、工具描述中的持续性授权、journaling，以及验证波）原样沿用；只是它们周围的执行基底会更稳健。</p>
<h2 id="相关内容">相关内容</h2>
<CardGroup cols={2}>
  <Card title="会话中途的 system messages" icon="message" href="https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages">
    模式提醒所使用的机制，以及它如何与 Prompt Caching 交互。
  </Card>
  <Card title="Effort" icon="gauge" href="https://platform.claude.com/docs/en/build-with-claude/effort">
    API 接受的 effort 级别，以及如何选择。
  </Card>
  <Card title="使用 Claude 的工具调用" icon="wrench" href="https://platform.claude.com/docs/en/agents-and-tools/tool-use/overview">
    定义工具、处理工具调用，以及工具结果。
  </Card>
  <Card title="Bash tool" icon="terminal" href="https://platform.claude.com/docs/en/agents-and-tools/tool-use/bash-tool">
    本示例在本地执行的 Anthropic 定义的 bash 工具。
  </Card>
</CardGroup>]]></content:encoded>
    </item>
    <item>
      <title>Cache diagnostics</title>
      <link>https://tuanzi-wow.cn/%E4%B8%8A%E4%B8%8B%E6%96%87%E5%B7%A5%E7%A8%8B/claudecode_context_management_cn/cache-diagnostics/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://tuanzi-wow.cn/%E4%B8%8A%E4%B8%8B%E6%96%87%E5%B7%A5%E7%A8%8B/claudecode_context_management_cn/cache-diagnostics/</guid>
      <description>通过对比连续请求，精确定位 prompt 前缀的分歧点，从而诊断意外的提示词缓存未命中。</description>
      <content:encoded><![CDATA[<h2 id="兼容性">兼容性</h2>
<ul>
<li>状态：Beta</li>
<li><a href="https://platform.claude.com/docs/en/api/beta-headers">Beta header</a>: <code>cache-diagnosis-2026-04-07</code></li>
<li><a href="https://platform.claude.com/docs/en/manage-claude/api-and-data-retention">ZDR</a>（零数据保留）: 符合资格（不包括 <a href="https://platform.claude.com/docs/en/manage-claude/api-and-data-retention#model-specific-data-retention-requirements">Covered Models</a>）</li>
<li>平台：Claude API (beta)；在 Claude Platform on AWS、Amazon Bedrock、Google Cloud、Microsoft Foundry 上不可用</li>
</ul>
<p><a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching">Prompt Caching</a> 能显著降低延迟和成本，但前提是 prompt 的开头必须与近期某次请求逐字节相同。被重排的 tool、插入到 system prompt 中的时间戳，或对更早消息的编辑，都可能悄无声息地使缓存失效。没有 cache diagnostics 时，唯一信号是 <code>usage.cache_read_input_tokens</code> 降为零，却无法得知什么发生了变化。</p>
<p>Cache diagnostics 填补了这一缺口。传入上一次响应的 <code>id</code>，API 会对比两次请求，并告诉你它们在何处分叉（model、system prompt、tools 或消息历史），从而让你修复根因，而不是猜测。</p>
<h2 id="cache-diagnostics-如何工作">Cache diagnostics 如何工作</h2>
<p>当 beta header 存在时，API 会为每个请求存储一份轻量 fingerprint，并以响应 <code>id</code> 作为键。在下一次请求中，将该 <code>id</code> 作为 <code>diagnostics.previous_message_id</code> 传入。API 会为新请求重建 fingerprint，与已存储的那份对比，并在响应上附加一个 <code>diagnostics</code> 对象，描述第一个分歧点。</p>
<p>对比针对的是请求结构，与缓存是否实际命中无关。关于如何将 <code>diagnostics</code> 结果与 <code>usage.cache_read_input_tokens</code> 结合使用，见 <a href="https://platform.claude.com/docs/en/build-with-claude/cache-diagnostics#reading-diagnostics-alongside-usage">结合 usage 解读 diagnostics</a>。</p>
<p>Fingerprint 仅包含哈希和 token 数量估计（绝不包含原始 prompt 内容），保留时间有限，作用域限定在你的 organization 和 workspace，且不会用于任何其他目的。</p>
<h2 id="基本用法">基本用法</h2>
<p>每一 turn 都发送 beta header。第一 turn 传入 <code>&quot;previous_message_id&quot;: null</code> 以选择加入，此时没有可供对比的先前消息。后续 turn 传入上一次响应中的 <code>id</code>。</p>
<CodeGroup>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">client</span> <span class="o">=</span> <span class="n">anthropic</span><span class="o">.</span><span class="n">Anthropic</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">SYSTEM</span> <span class="o">=</span> <span class="s2">&#34;You are an AI assistant analyzing a large document. &lt;document&gt;...&lt;/document&gt;&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Turn 1: opt in with previous_message_id=None</span>
</span></span><span class="line"><span class="cl"><span class="n">r1</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">beta</span><span class="o">.</span><span class="n">messages</span><span class="o">.</span><span class="n">create</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">model</span><span class="o">=</span><span class="s2">&#34;claude-opus-5&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">max_tokens</span><span class="o">=</span><span class="mi">1024</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">cache_control</span><span class="o">=</span><span class="p">{</span><span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;ephemeral&#34;</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="n">system</span><span class="o">=</span><span class="n">SYSTEM</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">messages</span><span class="o">=</span><span class="p">[{</span><span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span> <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;Summarize section 1.&#34;</span><span class="p">}],</span>
</span></span><span class="line"><span class="cl">    <span class="n">diagnostics</span><span class="o">=</span><span class="p">{</span><span class="s2">&#34;previous_message_id&#34;</span><span class="p">:</span> <span class="kc">None</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="n">betas</span><span class="o">=</span><span class="p">[</span><span class="s2">&#34;cache-diagnosis-2026-04-07&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Turn 2: reference the previous response id</span>
</span></span><span class="line"><span class="cl"><span class="n">r2</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">beta</span><span class="o">.</span><span class="n">messages</span><span class="o">.</span><span class="n">create</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">model</span><span class="o">=</span><span class="s2">&#34;claude-opus-5&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">max_tokens</span><span class="o">=</span><span class="mi">1024</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">cache_control</span><span class="o">=</span><span class="p">{</span><span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;ephemeral&#34;</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="n">system</span><span class="o">=</span><span class="n">SYSTEM</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">messages</span><span class="o">=</span><span class="p">[</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span><span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span> <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;Summarize section 1.&#34;</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span><span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;assistant&#34;</span><span class="p">,</span> <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="n">r1</span><span class="o">.</span><span class="n">content</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span><span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span> <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;Now summarize section 2.&#34;</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">],</span>
</span></span><span class="line"><span class="cl">    <span class="n">diagnostics</span><span class="o">=</span><span class="p">{</span><span class="s2">&#34;previous_message_id&#34;</span><span class="p">:</span> <span class="n">r1</span><span class="o">.</span><span class="n">id</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="n">betas</span><span class="o">=</span><span class="p">[</span><span class="s2">&#34;cache-diagnosis-2026-04-07&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">diagnostics</span> <span class="o">=</span> <span class="n">r2</span><span class="o">.</span><span class="n">diagnostics</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="n">diagnostics</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;No divergence detected.&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="k">elif</span> <span class="n">diagnostics</span><span class="o">.</span><span class="n">cache_miss_reason</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Comparison still pending.&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;cache_miss_reason: </span><span class="si">{</span><span class="n">diagnostics</span><span class="o">.</span><span class="n">cache_miss_reason</span><span class="o">.</span><span class="n">type</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span></code></pre></td></tr></table>
</div>
</div></CodeGroup>
<h2 id="流式">流式</h2>
<p>在流式响应中，<code>diagnostics</code> 出现在 <code>message_start</code> 事件上。</p>
<CodeGroup>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="c1"># Turn 2: stream, referencing the previous response id</span>
</span></span><span class="line"><span class="cl"><span class="k">with</span> <span class="n">client</span><span class="o">.</span><span class="n">beta</span><span class="o">.</span><span class="n">messages</span><span class="o">.</span><span class="n">stream</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">model</span><span class="o">=</span><span class="s2">&#34;claude-opus-5&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">max_tokens</span><span class="o">=</span><span class="mi">1024</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">cache_control</span><span class="o">=</span><span class="p">{</span><span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;ephemeral&#34;</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="n">system</span><span class="o">=</span><span class="n">SYSTEM</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">messages</span><span class="o">=</span><span class="p">[</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span><span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span> <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;Summarize section 1.&#34;</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span><span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;assistant&#34;</span><span class="p">,</span> <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="n">r1</span><span class="o">.</span><span class="n">content</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span><span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span> <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;Now summarize section 2.&#34;</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">],</span>
</span></span><span class="line"><span class="cl">    <span class="n">diagnostics</span><span class="o">=</span><span class="p">{</span><span class="s2">&#34;previous_message_id&#34;</span><span class="p">:</span> <span class="n">r1</span><span class="o">.</span><span class="n">id</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="n">betas</span><span class="o">=</span><span class="p">[</span><span class="s2">&#34;cache-diagnosis-2026-04-07&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span> <span class="k">as</span> <span class="n">stream</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">text</span> <span class="ow">in</span> <span class="n">stream</span><span class="o">.</span><span class="n">text_stream</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="n">text</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s2">&#34;&#34;</span><span class="p">,</span> <span class="n">flush</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    <span class="n">r2</span> <span class="o">=</span> <span class="n">stream</span><span class="o">.</span><span class="n">get_final_message</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">diagnostics</span> <span class="o">=</span> <span class="n">r2</span><span class="o">.</span><span class="n">diagnostics</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="n">diagnostics</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;No divergence detected.&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="k">elif</span> <span class="n">diagnostics</span><span class="o">.</span><span class="n">cache_miss_reason</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Comparison still pending.&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;cache_miss_reason: </span><span class="si">{</span><span class="n">diagnostics</span><span class="o">.</span><span class="n">cache_miss_reason</span><span class="o">.</span><span class="n">type</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span></code></pre></td></tr></table>
</div>
</div></CodeGroup>
<p><code>message_start</code> 事件携带完整的 <code>diagnostics</code> 字段；可能的取值见 <a href="https://platform.claude.com/docs/en/build-with-claude/cache-diagnostics#response-format">响应格式</a>。</p>
<h2 id="在对话循环中贯穿-diagnostics">在对话循环中贯穿 diagnostics</h2>
<p>在多 turn 对话中，每一 turn 都将最新响应的 <code>id</code> 作为 <code>previous_message_id</code> 向前传递。第一次迭代传入 <code>null</code> 以选择加入；之后每次迭代传入上一次响应中的 <code>id</code>。</p>
<Tabs>
  <Tab title="cURL">
    <Info>
      该工作流不太适合写成一次性的 shell 命令。循环模式见 SDK 各 tab；每一 turn 的 HTTP 请求与 [基本用法](https://platform.claude.com/docs/en/build-with-claude/cache-diagnostics#basic-usage) 相同。
    </Info>
  </Tab>
  <Tab title="CLI">
    <Info>
      该工作流不太适合写成一次性的 shell 命令。循环模式见 SDK 各 tab；每一 turn 的 CLI 调用与 [基本用法](https://platform.claude.com/docs/en/build-with-claude/cache-diagnostics#basic-usage) 相同。
    </Info>
  </Tab>
  <Tab title="Python">
    ```python
    client = anthropic.Anthropic()
<pre><code>SYSTEM = &quot;You are an AI assistant analyzing a large document. &lt;document&gt;...&lt;/document&gt;&quot;

messages = []
prev_id = None

for i, user_message in enumerate(
    [&quot;Summarize section 1.&quot;, &quot;Now section 2.&quot;, &quot;Now section 3.&quot;]
):
    messages.append({&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: user_message})

    r = client.beta.messages.create(
        model=&quot;claude-opus-5&quot;,
        max_tokens=1024,
        cache_control={&quot;type&quot;: &quot;ephemeral&quot;},
        system=SYSTEM,
        messages=messages,
        diagnostics={&quot;previous_message_id&quot;: prev_id},
        betas=[&quot;cache-diagnosis-2026-04-07&quot;],
    )

    if r.diagnostics is not None and r.diagnostics.cache_miss_reason is not None:
        print(f&quot;Turn {i + 1} cache_miss_reason: {r.diagnostics.cache_miss_reason.type}&quot;)

    messages.append({&quot;role&quot;: &quot;assistant&quot;, &quot;content&quot;: r.content})
    prev_id = r.id
```
</code></pre>
<h2 id="响应格式">响应格式</h2>
<p>响应 <code>Message</code> 上的 <code>diagnostics</code> 字段有四种可能状态：</p>
<table>
	<thead>
			<tr>
					<th>取值</th>
					<th>含义</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>字段缺失</td>
					<td>请求未包含 <code>diagnostics</code>，或缺少 beta header。</td>
			</tr>
			<tr>
					<td><code>null</code></td>
					<td>要么 <code>previous_message_id</code> 为 <code>null</code>（第一 turn，没有可对比的内容），要么对比已完成且未发现分叉。</td>
			</tr>
			<tr>
					<td><code>{&quot;cache_miss_reason&quot;: null}</code></td>
					<td>响应序列化时对比仍在进行。响应启动非常快时可能出现这种情况。将其视为尚无结论，并在下一 turn 再检查。</td>
			</tr>
			<tr>
					<td><code>{&quot;cache_miss_reason&quot;: {...}}</code></td>
					<td>附带了 <code>cache_miss_reason</code>。对于 <code>*_changed</code> 类型，它标识第一个分歧点；<code>previous_message_not_found</code> 和 <code>unavailable</code> 表示未产生对比结果。</td>
			</tr>
	</tbody>
</table>
<p>当 <code>cache_miss_reason</code> 非 null 时，形态如下：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;id&#34;</span><span class="p">:</span> <span class="s2">&#34;msg_01Xyz...&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;message&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;assistant&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;content&#34;</span><span class="p">:</span> <span class="p">[{</span> <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;text&#34;</span><span class="p">,</span> <span class="nt">&#34;text&#34;</span><span class="p">:</span> <span class="s2">&#34;...&#34;</span> <span class="p">}],</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;usage&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;input_tokens&#34;</span><span class="p">:</span> <span class="mi">42</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;cache_read_input_tokens&#34;</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;cache_creation_input_tokens&#34;</span><span class="p">:</span> <span class="mi">41850</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;output_tokens&#34;</span><span class="p">:</span> <span class="mi">210</span>
</span></span><span class="line"><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;diagnostics&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;cache_miss_reason&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;system_changed&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;cache_missed_input_tokens&#34;</span><span class="p">:</span> <span class="mi">41850</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="缓存未命中原因类型">缓存未命中原因类型</h2>
<p><code>cache_miss_reason</code> 是以 <code>type</code> 为判别字段的联合类型。响应只报告最早的分歧点，因此先修复它；更后面的分歧可能被它挡住。</p>
<table>
	<thead>
			<tr>
					<th>类型</th>
					<th>含义</th>
					<th>需要改什么</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>model_changed</code></td>
					<td><code>model</code> 与上一次请求不同（例如路由器、A/B 测试或回退选择了不同的 model）。缓存是按 model 隔离的。</td>
					<td>在使用缓存的对话中保持 model 不变。</td>
			</tr>
			<tr>
					<td><code>system_changed</code></td>
					<td><code>system</code> 参数不同。通常是时间戳、request ID 或其他每次请求都会变的值被插入到了 system prompt 中。</td>
					<td>将 system prompt 做成逐字节稳定的常量，并把动态数据移到缓存断点之后的第一条 <code>user</code> 消息中。</td>
			</tr>
			<tr>
					<td><code>tools_changed</code></td>
					<td><code>tools</code> 数组不同：turn 之间添加、删除或重排了 tools，或者 tool 的 <code>input_schema</code> JSON 序列化不稳定。</td>
					<td>每一 turn 以固定顺序发送相同的 tool 列表，并使用确定性序列化的 schema（例如对 key 排序）。</td>
			</tr>
			<tr>
					<td><code>messages_changed</code></td>
					<td>model、system 和 tools 都匹配，但 <code>messages</code> 中更早的某条被改动、重排或删除，而不是追加。通常是对话历史被截断或编辑，或在重发时 assistant turn 和 <code>tool_result</code> 块被以不同方式重新序列化。</td>
					<td>将历史视为只追加；原样回传 assistant <code>content</code> 和 tool 结果。</td>
			</tr>
			<tr>
					<td><code>previous_message_not_found</code></td>
					<td>所提供的 <code>previous_message_id</code> 没有对应的已存储 fingerprint。这并不证明你的请求发生了变化。通常是上一次请求未携带 beta header、来自不同的 workspace，或距离发送已经过了太久。</td>
					<td>每一 turn 都发送 beta header，并让连续 turn 在时间上尽量靠近。</td>
			</tr>
			<tr>
					<td><code>unavailable</code></td>
					<td>本次请求没有可用的 diagnostic 信息。包括 <code>model</code>、<code>system</code> 和 <code>tools</code> 都匹配，但另一个会影响 prompt 的请求参数（<code>tool_choice</code>、<code>thinking</code>、<code>context_management</code>、<code>output_config</code>、<code>output_format</code>，或当前生效的 <code>anthropic-beta</code> header 集合）不同，以及超长对话中分歧点超出对比范围的情况。你的请求已正常处理。</td>
					<td>在使用缓存的对话生命周期内，保持会影响 prompt 的请求参数不变。若问题持续，按提示词缓存页面 <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#troubleshooting-common-issues">排查常见问题</a> 下的手动检查处理。</td>
			</tr>
	</tbody>
</table>
<Note>
  四种 `*_changed` 类型还会附带一个 `cache_missed_input_tokens` 整数：估计有多少 input token 落在分歧点之后，让你对损失了多少可缓存前缀有个量级感。该值由 tokenization 之前的字节长度推导，因此应视为量级指标而非计费数字。它可能与 `usage.input_tokens` 不同（偶尔还会更大）。
</Note>
<h2 id="结合-usage-解读-diagnostics">结合 usage 解读 diagnostics</h2>
<p><code>diagnostics</code> 回答「我的请求变了吗？」，而 <code>usage.cache_read_input_tokens</code> 回答「缓存命中了吗？」。两者结合能告诉你该往哪看。</p>
<p>该矩阵适用于传入了真实 <code>previous_message_id</code> 的 turn。第一 turn（<code>previous_message_id: null</code>）时，<code>diagnostics</code> 始终为 <code>null</code>，且 <code>cache_read_input_tokens</code> 通常为零，因为缓存正在写入而非读取；无需排查。当 <code>cache_miss_reason</code> 为 <code>null</code>（对比仍在进行；检查下一 turn），或其 <code>type</code> 为 <code>previous_message_not_found</code> 或 <code>unavailable</code>（未产生对比）时，该矩阵同样不适用。</p>
<table>
	<thead>
			<tr>
					<th>Diagnostics 结果</th>
					<th>缓存读取 token</th>
					<th>解读</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>null</code></td>
					<td>高</td>
					<td>符合预期。你的前缀稳定且缓存命中。</td>
			</tr>
			<tr>
					<td><code>null</code></td>
					<td>低或为零</td>
					<td>请求匹配，但缓存条目已不再可用。考虑缩短 turn 之间的间隔，或使用 <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#1-hour-cache-duration">1 小时缓存 TTL</a>。</td>
			</tr>
			<tr>
					<td><code>cache_miss_reason</code> 为 <code>*_changed</code> 类型</td>
					<td>低或为零</td>
					<td>你这边的 bug。请求发生了变化；按 <code>type</code> 所示原因修复。</td>
			</tr>
			<tr>
					<td><code>cache_miss_reason</code> 为 <code>*_changed</code> 类型</td>
					<td>高</td>
					<td>少见。变化发生在 prompt 较后位置，但更早的 <code>cache_control</code> 断点仍然命中。值得修复，但影响较小。</td>
			</tr>
	</tbody>
</table>
<h2 id="限制">限制</h2>
<ul>
<li><strong>Beta：</strong> 该功能处于 beta 期间，字段名和语义可能会变化。</li>
<li><strong>仅 Claude API：</strong> 在 Amazon Bedrock 或 Google Cloud 上不可用。</li>
<li><strong>保留时间有限：</strong> 用于 <code>previous_message_id</code> 查找的 fingerprint 会在短时间后过期。在间隔较近的请求之间运行 diagnostic 对比。</li>
<li><strong>同一 workspace：</strong> 上一次请求必须运行在同一 organization 和 workspace。要核对此点，对比两次响应上的 <code>anthropic-workspace-id</code> <a href="https://platform.claude.com/docs/en/api/overview#response-headers">响应 header</a>。</li>
<li><strong>对比范围：</strong> 对于超长对话，若唯一变化深藏在消息列表中，响应可能是 <code>unavailable</code> 而非精确位置。</li>
<li><strong>尽力而为：</strong> Diagnostics 从不阻塞或导致请求失败。若 diagnostic 信息不可用，响应会返回 <code>unavailable</code>，或在对比仍在进行时返回 <code>cache_miss_reason: null</code>。</li>
</ul>
<h2 id="数据保留">数据保留</h2>
<p>Cache diagnostics 符合 ZDR 资格（qualified）。Anthropic 不会为此功能存储你的 prompt 原文或 Claude 的输出。</p>
<p>为每个请求存储的 fingerprint 仅包含加密哈希和 token 数量估计，以响应 <code>id</code> 为键，作用域限定在你的 organization 和 workspace。Fingerprint 会在短时间后过期，且不会用于任何其他目的。</p>
<p>各功能的 ZDR 资格，见 <a href="https://platform.claude.com/docs/en/manage-claude/api-and-data-retention">API 与数据保留</a>。</p>
<h2 id="另见">另见</h2>
<ul>
<li><a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching">Prompt Caching</a></li>
<li><a href="https://platform.claude.com/docs/en/build-with-claude/token-counting">Token counting</a></li>
<li><a href="https://platform.claude.com/docs/en/api/beta-headers">Beta headers</a></li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>Claude上下文</title>
      <link>https://tuanzi-wow.cn/%E4%B8%8A%E4%B8%8B%E6%96%87%E5%B7%A5%E7%A8%8B/claudecode_context_management_cn/claude-context-reference/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://tuanzi-wow.cn/%E4%B8%8A%E4%B8%8B%E6%96%87%E5%B7%A5%E7%A8%8B/claudecode_context_management_cn/claude-context-reference/</guid>
      <description>Claude上下文相关学习笔记与实践要点。</description>
      <content:encoded><![CDATA[<h1 id="上下文窗口">上下文窗口</h1>
<h2 id="context-rot随着上下文token数地增长准确性和召回率会下降的现象">context rot:随着上下文token数地增长,准确性和召回率会下降的现象</h2>
<h2 id="对于一个request包含的内容">对于一个request包含的内容:</h2>
<ol>
<li>tools:能够给模型提供tools,包含其名称,描述,参数</li>
<li>System prompt:系统提示词</li>
<li>一些harness设置的信息,比如ClaudeCode的CLAUDE.md或者codex的AGENTS.md等等</li>
<li>user message: prompt,tool calling,thinking block,tool result等等</li>
</ol>
<h2 id="区分三个概念">区分三个概念:</h2>
<p>input_tokens;cache_read_input_tokens;cache_creation_input_token</p>
<p>这和prompt caching还有price有关</p>
<h2 id="带thinking的上下文窗口">带thinking的上下文窗口</h2>
<p>thinking tokens是max_tokens的子集</p>
<p>关于assistant turn中的think blocks是否保留在上下文由模型决定
不过现在大部分的模型都是全量保留
不过在context_editing中你可以在通过设置来清楚think blocks腾出更多的上下文空间</p>
<p>对于启用了剥离thinking blocks的模型:</p>
<ul>
<li>thinking blocks会作为上一轮assistant turn的output,但是不会作为下一轮的user turn的input</li>
<li>计费:think blocks作为输出计费,如果被保留,在下一轮对话中也会作为上下文输出,按输入再次计费</li>
</ul>
<h2 id="上下文的感知context-awareness">上下文的感知(context awareness):</h2>
<h3 id="工作原理">工作原理:</h3>
<p>之前:每个request的system prompt中会包含总的上下文窗口
每次工具调用之后,API会向Claude提供剩余用量的更新
之后:
不会收到这些注入的标签了
通过task_budgets给模型一个显示预算</p>
<h2 id="用压缩管理上下文">用压缩管理上下文:</h2>
<p>server-side compaction时最常见的管理上下文的方式
对于更为专业的需求,在context-editing中提供了额外的策略:</p>
<ul>
<li>tool result clearing: 清楚工具调用的结果,可通过设置也清楚工具调用的请求信息</li>
<li>thinking blocks clearing:在extending thinking时清楚thinking blocks</li>
</ul>
<h1 id="compaction">Compaction</h1>
<p>server-side Compaction是管理上下文的最常见的方式,他会自动处理上下文管理</p>
<p>when:</p>
<p>压缩会在上下文窗口的大小接近上限时自动摘要较久的上下文</p>
<p>适用于:</p>
<ul>
<li>基于聊天的多轮对话</li>
<li>需要大量后续工作,且可能超出上下文窗口的面向任务的prompt</li>
</ul>
<h2 id="压缩如何工作的">压缩如何工作的</h2>
<p>当快要到达对话设定的阈值的时候,会自动触发上下文压缩:</p>
<ol>
<li>检测输出的token是否达到你设定的阈值</li>
<li>生成当前对话的摘要</li>
<li>创建包含该摘要的compaction block</li>
<li>使用压缩后的上下文进行回复</li>
</ol>
<h2 id="基本用法">基本用法:</h2>
<p>在message API请求的context_management.edits中添加compact_20260112的策略来启用缓存</p>
<h2 id="参数">参数</h2>
<table>
	<thead>
			<tr>
					<th>参数</th>
					<th>类型</th>
					<th>默认值</th>
					<th>说明</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>trigger</code></td>
					<td>object</td>
					<td><code>{&quot;type&quot;: &quot;input_tokens&quot;, &quot;value&quot;: 150000}</code></td>
					<td>何时触发压缩。<code>input_tokens</code> 是唯一支持的触发类型。<code>value</code> 必须至少为 50,000 tokens。</td>
			</tr>
			<tr>
					<td><code>pause_after_compaction</code></td>
					<td>boolean</td>
					<td><code>false</code></td>
					<td>生成压缩摘要后是否暂停</td>
			</tr>
			<tr>
					<td><code>instructions</code></td>
					<td>string</td>
					<td><code>null</code></td>
					<td>自定义摘要 prompt。提供后会完全替换默认 prompt。</td>
			</tr>
			<tr>
					<td><code>type</code></td>
					<td>string</td>
					<td>Required</td>
					<td>必须为 <code>&quot;compact_20260112&quot;</code></td>
			</tr>
	</tbody>
</table>
<h3 id="触发配置">触发配置:</h3>
<p>使用trigger参数配置何时触发压缩</p>
<h3 id="自定义摘要指令">自定义摘要指令:</h3>
<p>默认的prompt因模型而异,但是可以通过instruction参数提供自定义的指令
而且它不会补充默认的指令,而是完全代替它</p>
<h3 id="压缩后暂停">压缩后暂停:</h3>
<p>使用pause_after_compaction参数设置,这可以使得在继续生成回复之前添加额外的content block(例如保留最近的消息或者特定的指令导向消息)</p>
<p>启用后,API在生成compaction block后会返回带有compaction stop reason的消息</p>
<h2 id="处理compaction-block">处理compaction block:</h2>
<p>触发压缩后,会在压缩完成后assistant回复的开头返回一个compaction block
长时间运行的对话可能会存在多次compaction,最后一个compaction block反应了prompt的最终状态</p>
<h3 id="回传compaction-block">回传compaction block:</h3>
<p>你必须在后续的request中回传compaction block,才能以缩短后的prompt继续对话
最简单的做法是:把整个响应content追加到你的message中</p>
<p>当API收到compaction block时,之前的所有的content block都会被忽略,你可以:</p>
<ul>
<li>在列表中保留原始message,让API处理移除已经压缩的内容</li>
<li>手动丢弃已经压缩的内容我</li>
</ul>
<p>如果你编写自己的 <code>instructions</code>，需告知模型摘要必须保留什么；见 <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-1#tell-the-model-what-to-preserve-in-compaction-summaries">Tell the model what to preserve in compaction summaries</a>。</p>
<h3 id="流式输出">流式输出:</h3>
<p>compaction的流式传输方式与text block不同:</p>
<ol>
<li>你会先收到一个content_block_start事件</li>
<li>收到一条包含完整摘要内容的content_block_delta(无中间流式片段)</li>
<li>然后时cintent_block_stop事件</li>
</ol>
<h3 id="prompt-caching">Prompt caching:</h3>
<p>你可以在compaction block上添加cache control的breakdown来缓存摘要后的内容</p>
<h3 id="通过system-prompt最大化缓存命中">通过System prompt最大化缓存命中:</h3>
<p>发生压缩时,摘要会称为需要写入缓存的新内容,如果没有额外的缓存断点,会使已经缓存的system prompt失效</p>
<p>为了最大化缓存命中率,会在system prompt的末尾添加一个cache_control的断点,使得system_prompt和对话分开缓存,因此在发生压缩时:</p>
<ul>
<li>system prompt缓存依旧有效,从缓存读取</li>
<li>将摘要作为新的缓存条目读入</li>
</ul>
<h3 id="了解用量">了解用量:</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">{
</span></span><span class="line"><span class="cl">  &#34;usage&#34;: {
</span></span><span class="line"><span class="cl">    &#34;input_tokens&#34;: 23000,
</span></span><span class="line"><span class="cl">    &#34;output_tokens&#34;: 1000,
</span></span><span class="line"><span class="cl">    &#34;iterations&#34;: [
</span></span><span class="line"><span class="cl">      {
</span></span><span class="line"><span class="cl">        &#34;type&#34;: &#34;compaction&#34;,
</span></span><span class="line"><span class="cl">        &#34;input_tokens&#34;: 180000,
</span></span><span class="line"><span class="cl">        &#34;output_tokens&#34;: 3500
</span></span><span class="line"><span class="cl">      },
</span></span><span class="line"><span class="cl">      {
</span></span><span class="line"><span class="cl">        &#34;type&#34;: &#34;message&#34;,
</span></span><span class="line"><span class="cl">        &#34;input_tokens&#34;: 23000,
</span></span><span class="line"><span class="cl">        &#34;output_tokens&#34;: 1000
</span></span><span class="line"><span class="cl">      }
</span></span><span class="line"><span class="cl">    ]
</span></span><span class="line"><span class="cl">  }
</span></span><span class="line"><span class="cl">}
</span></span></code></pre></td></tr></table>
</div>
</div><p>iteration数组显示每次采样的迭代用量
发生压缩时,你会看到一次compaction迭代,随后是主要的message迭代
最顶层的input_tokens和output_tokens不包含压缩迭代的用量,因此在计算总的用量时,请对usage.iteration的每一个迭代进行求和(包括compaction迭代)</p>
<h2 id="与其他功能结合">与其他功能结合:</h2>
<h3 id="服务端工具">服务端工具:</h3>
<p>使用服务端工具（例如 web search）时，会在每次采样迭代开始时检查压缩触发条件。根据触发阈值和生成的输出量，单次请求内可能发生多次压缩。</p>
<h3 id="token计数">Token计数</h3>
<p>token 计数端点（<code>/v1/messages/count_tokens</code>）会应用 prompt 中已有的 <code>compaction</code> block，但不会触发新的压缩。用它来检查先前压缩后的有效 token 数：</p>
<h2 id="当前限制">当前限制:</h2>
<ul>
<li>摘要使用同一模型:</li>
<li>定义了tools时压缩可能失败:当请求包含tools时,模型偶尔会在内部摘要步骤中调用工具,而不是撰写摘要,发生这种情况时,会响应中会返回一个content: null的compaction block
为了防止这种情况,会在instruction中明确告知模型不要调用工具</li>
</ul>
<h1 id="context-editing">Context editing:</h1>
<p>概述:server-side compaction是最常见的上下文管理措施
而本章中的策略适用于需要更加精细控制需要clear哪些内容的特定场景
允许你有选择性地清楚特定地内容,不仅仅是为了优化成本,也是为了主动筛选模型所见地内容
主要由下面三种策略:</p>
<ol>
<li>tool result clear:</li>
<li>think block clear:用于开启了extended thinking时管理think block</li>
<li>客户端SDK压缩(不打算看)</li>
</ol>
<h2 id="服务端策略">服务端策略:</h2>
<p>主要分为两种:tool_result clear和thinking block clear</p>
<h3 id="tool-result-clear">Tool result clear:</h3>
<p>用于清理工具调用地结果(和工具调用:需要配置开启)
激活后,API会清理最旧的工具结果,将其替换为占位文本,表示已经被移除
也可以将clear_tool_inputs设置为true,同时清理tool result和tool call</p>
<h3 id="thinking-block-clear">Thinking block clear:</h3>
<p>对于开启extended thing时启用
现在的大部分模型都默认保留think block,并且作为后续的input</p>
<h3 id="context-editing和prompt-caching">context editing和Prompt Caching:</h3>
<ul>
<li>tool result clear:会使已经缓存的prompt失效,所以应该清理足够多的token使得物有所值,可以使用clear_at_least规定清理token的最少数量</li>
<li>think block clear:同样的,缓存会在清理发生处失效,常见是将thinking block keep</li>
</ul>
<h2 id="tool-result-clear-usage">tool result clear usage:</h2>
<p>最常见:使用仅指定策略(即不清除tool call),其他使用默认值</p>
<h3 id="高级配置其他参数定义清楚行为">高级配置:其他参数定义清楚行为</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">response</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">beta</span><span class="o">.</span><span class="n">messages</span><span class="o">.</span><span class="n">create</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">model</span><span class="o">=</span><span class="s2">&#34;claude-opus-5&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">max_tokens</span><span class="o">=</span><span class="mi">4096</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">messages</span><span class="o">=</span><span class="p">[</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;Create a simple command line calculator app using Python&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">],</span>
</span></span><span class="line"><span class="cl">    <span class="n">tools</span><span class="o">=</span><span class="p">[</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;text_editor_20250728&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;str_replace_based_edit_tool&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;max_characters&#34;</span><span class="p">:</span> <span class="mi">10000</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="p">},</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span><span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;web_search_20250305&#34;</span><span class="p">,</span> <span class="s2">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;web_search&#34;</span><span class="p">,</span> <span class="s2">&#34;max_uses&#34;</span><span class="p">:</span> <span class="mi">3</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">],</span>
</span></span><span class="line"><span class="cl">    <span class="n">betas</span><span class="o">=</span><span class="p">[</span><span class="s2">&#34;context-management-2025-06-27&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">    <span class="n">context_management</span><span class="o">=</span><span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;edits&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">            <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;clear_tool_uses_20250919&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="c1"># Trigger clearing when threshold is exceeded</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;trigger&#34;</span><span class="p">:</span> <span class="p">{</span><span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;input_tokens&#34;</span><span class="p">,</span> <span class="s2">&#34;value&#34;</span><span class="p">:</span> <span class="mi">30000</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">                <span class="c1"># Number of tool uses to keep after clearing</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;keep&#34;</span><span class="p">:</span> <span class="p">{</span><span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;tool_uses&#34;</span><span class="p">,</span> <span class="s2">&#34;value&#34;</span><span class="p">:</span> <span class="mi">3</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">                <span class="c1"># Optional: Clear at least this many tokens</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;clear_at_least&#34;</span><span class="p">:</span> <span class="p">{</span><span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;input_tokens&#34;</span><span class="p">,</span> <span class="s2">&#34;value&#34;</span><span class="p">:</span> <span class="mi">5000</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">                <span class="c1"># Exclude these tools from being cleared</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;exclude_tools&#34;</span><span class="p">:</span> <span class="p">[</span><span class="s2">&#34;web_search&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>可以配置的选项有:</p>
<table>
	<thead>
			<tr>
					<th>配置选项</th>
					<th>默认值</th>
					<th>说明</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>trigger</code></td>
					<td>100,000 输入 token</td>
					<td>定义上下文编辑策略何时激活。一旦 prompt 超过此阈值，便开始清除。你可以用 <code>input_tokens</code> 或 <code>tool_uses</code> 指定此值。</td>
			</tr>
			<tr>
					<td><code>keep</code></td>
					<td>3 次工具使用</td>
					<td>定义清除发生后保留多少对近期的工具使用/结果。API 先移除最旧的工具交互，保留最近的交互。</td>
			</tr>
			<tr>
					<td><code>clear_at_least</code></td>
					<td>无</td>
					<td>确保每次策略激活时至少清除指定数量的 token。如果 API 无法至少清除指定数量，则不会应用该策略。这有助于判断上下文清除是否值得打断你的 prompt 缓存。</td>
			</tr>
			<tr>
					<td><code>exclude_tools</code></td>
					<td>无</td>
					<td>其工具使用和结果永远不应被清除的工具名称列表。适用于保留重要上下文。</td>
			</tr>
			<tr>
					<td><code>clear_tool_inputs</code></td>
					<td><code>false</code></td>
					<td>控制是否连同工具结果一起清除工具调用参数。默认情况下，仅清除工具结果，同时保持 Claude 原始的工具调用可见。</td>
			</tr>
	</tbody>
</table>
<h2 id="think-block-clear">think block clear:</h2>
<h3 id="可配置的选项">可配置的选项:</h3>
<p>keep:
定义要保留的多少个含think block的assistant turn使用{type: &ldquo;thinking_turns&rdquo;, value: N}.(管理上下文)
或者直接使用keep: all来保留所有的think blocks(最大化缓存命中)</p>
<h2 id="组合策略">组合策略:</h2>
<p>限制:当使用组合策略时,clear_thinking_20251015比放在edits数组的第一位</p>
<h2 id="上下文编辑响应">上下文编辑响应</h2>
<p>你可以使用context_management的响应字段来查看哪些上下文编辑已经应用于你的request,已经有关已清楚内容和输入token的有用统计信息
例如:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-mysql" data-lang="mysql"><span class="line"><span class="cl"><span class="err">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="s2">&#34;id&#34;</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;msg_013Zva2CMHLNnXjNJJKqJ2EF&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="s2">&#34;type&#34;</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;message&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="s2">&#34;role&#34;</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;assistant&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="s2">&#34;content&#34;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="o">//</span><span class="w"> </span><span class="p">...</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">],</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="s2">&#34;usage&#34;</span><span class="p">:</span><span class="w"> </span><span class="err">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="o">//</span><span class="w"> </span><span class="p">...</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="err">}</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="s2">&#34;context_management&#34;</span><span class="p">:</span><span class="w"> </span><span class="err">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="s2">&#34;applied_edits&#34;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="o">//</span><span class="w"> </span><span class="k">When</span><span class="w"> </span><span class="k">using</span><span class="w"> </span><span class="o">`</span><span class="n">clear_thinking_20251015</span><span class="o">`</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="err">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="s2">&#34;type&#34;</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;clear_thinking_20251015&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="s2">&#34;cleared_thinking_turns&#34;</span><span class="p">:</span><span class="w"> </span><span class="mi">3</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="s2">&#34;cleared_input_tokens&#34;</span><span class="p">:</span><span class="w"> </span><span class="mi">15000</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="err">}</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="o">//</span><span class="w"> </span><span class="k">When</span><span class="w"> </span><span class="k">using</span><span class="w"> </span><span class="o">`</span><span class="n">clear_tool_uses_20250919</span><span class="o">`</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="err">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="s2">&#34;type&#34;</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;clear_tool_uses_20250919&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="s2">&#34;cleared_tool_uses&#34;</span><span class="p">:</span><span class="w"> </span><span class="mi">8</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="s2">&#34;cleared_input_tokens&#34;</span><span class="p">:</span><span class="w"> </span><span class="mi">50000</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="err">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="err">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="err">}</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>对于stream响应,相关的信息在最终的message_delta</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">{
</span></span><span class="line"><span class="cl">  &#34;type&#34;: &#34;message_delta&#34;,
</span></span><span class="line"><span class="cl">  &#34;delta&#34;: {
</span></span><span class="line"><span class="cl">    &#34;stop_reason&#34;: &#34;end_turn&#34;,
</span></span><span class="line"><span class="cl">    &#34;stop_sequence&#34;: null
</span></span><span class="line"><span class="cl">  },
</span></span><span class="line"><span class="cl">  &#34;usage&#34;: {
</span></span><span class="line"><span class="cl">    &#34;output_tokens&#34;: 1024
</span></span><span class="line"><span class="cl">  },
</span></span><span class="line"><span class="cl">  &#34;context_management&#34;: {
</span></span><span class="line"><span class="cl">    &#34;applied_edits&#34;: [
</span></span><span class="line"><span class="cl">      // ...
</span></span><span class="line"><span class="cl">    ]
</span></span><span class="line"><span class="cl">  }
</span></span><span class="line"><span class="cl">}
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="token-count">Token count:</h2>
<p>用于支持上下文管理,让你预览在context edit后prompt使用多少token</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  print(f&#34;Original tokens: {response.context_management.original_input_tokens}&#34;)
</span></span><span class="line"><span class="cl">  print(f&#34;After clearing: {response.input_tokens}&#34;)
</span></span><span class="line"><span class="cl">  print(
</span></span><span class="line"><span class="cl">      f&#34;Savings: {response.context_management.original_input_tokens - response.input_tokens} tokens&#34;
</span></span><span class="line"><span class="cl">  )
</span></span></code></pre></td></tr></table>
</div>
</div><p>响应显示context editing之后的token和清楚发生之前的original_input_tokens</p>
<h2 id="与memory-tool一起使用">与memory tool一起使用</h2>
<p>当context到达被清除的阈值时,在被清理之前,收到自动警告以保存重要信息,将对话历史和其他信息保存到memory中</p>
<ul>
<li>保留重要上下文</li>
<li>维持长时间的工作流</li>
<li>按需访问信息</li>
</ul>
<h1 id="prompt-caching-1">Prompt Caching</h1>
<p>允许你使用prompt prefix匹配来优化API的token用量</p>
<p>对于重复性任务和包含一致元素的prompt会显著降低处理时间和成本</p>
<p>有两种方法来启用Prompt Caching</p>
<ul>
<li>automatic cache:在请求的顶层添加单个cache_control字段,系统会自动将缓存的断点应用到最后一个可缓存的block</li>
<li>显式缓存断点:将cache_control放在content block上</li>
</ul>
<p>最简单的方式是使用自动缓存:
使用自动缓存时，系统会缓存直到并包括最后一个可缓存块的全部内容</p>
<p>Prompt Caching怎么工作:</p>
<ol>
<li>系统检查prompt prefix,查看是否能够查询到</li>
<li>如果能够找到,就直接复用</li>
<li>否则处理完整的prompt</li>
</ol>
<p>一般来说,缓存的TTL为5min(由模型决定)或1h(需要设置开启,且price更贵)</p>
<p>TTL(生命周期):从写入或者读取该条缓存条目开始而非响应结束的时刻
<strong>Prompt Caching缓存完整的前缀</strong>:
引用整个prompt&mdash;tools,system和messages,知道并包括使用cache_control的block</p>
<h2 id="automatic-caching">Automatic Caching:</h2>
<p>usage:在单个请求体顶层添加 cache_control字段
将缓存断点应用到最后一个可缓存的block</p>
<h3 id="自动缓存在多轮对话中怎么工作">自动缓存在多轮对话中怎么工作?</h3>
<p>随着对话的进行,断点会自动向前移动,到新的请求的最后一个可缓存的block的
而先前的内容通过缓存读取
所以不需要跟随对话去更新cache_control标记</p>
<h3 id="ttl支持">TTL支持:</h3>
<p>默认5min,可开启1h,价格不同</p>
<h3 id="与显式缓存结合">与显式缓存结合:</h3>
<p>两者是可以兼容的,这个时候,自动缓存断点会占用四个可用断点槽位中的一个
常见用法:
用显式缓存断点缓存system prompt;用自动缓存断点处理对话
将stable prompt和variable prompt分开进行缓存</p>
<h3 id="边界情况">边界情况</h3>
<ul>
<li>如果最后一个块已经带有相同 TTL 的显式 <code>cache_control</code>，自动缓存为 no-op。</li>
<li>如果最后一个块带有不同 TTL 的显式 <code>cache_control</code>，API 返回 400 error。</li>
<li>如果已经存在 4 个显式块级断点，API 返回 400 error（没有剩余槽位给自动缓存）。</li>
<li>如果最后一个块不适合作为自动缓存断点目标，系统会静默向后查找最近的合格块。如果找不到，则跳过缓存。</li>
</ul>
<h2 id="显式缓存断点">显式缓存断点</h2>
<p>更加精细地控制缓存
usage:将cache_control放在具体的block上</p>
<h2 id="组织你的prompt">组织你的prompt:</h2>
<p>将stable prompt放在prompt开头,是cache_control参数标记在可复用内容的结尾便于缓存
prompt prefix的顺序:
tools,system,messages</p>
<h2 id="自动前缀检查如何工作">自动前缀检查如何工作:</h2>
<p>三条核心原则:(这个只针对采取这种算法的模型成立)</p>
<ol>
<li>缓存写入只发生在你的断点处</li>
<li>缓存读取会向后查找先前请求写入的条目</li>
<li>回看窗口为20块 注意此处为block而非记录哦,但是不是在20块结束就停止,也是会继续向前读条目</li>
</ol>
<h2 id="缓存策略和注意事项">缓存策略和注意事项</h2>
<h3 id="缓存限制">缓存限制:</h3>
<p>可缓存Prompt的最短长度,小于这个长度,即使有cache_control也不会缓存</p>
<h3 id="哪些内容可以缓存">哪些内容可以缓存:</h3>
<ul>
<li>工具：<code>tools</code> 数组中的工具定义</li>
<li>系统消息：<code>system</code> 数组中的内容块</li>
<li>文本消息：<code>messages.content</code> 数组中的内容块，适用于 user 和 assistant 两轮</li>
<li>图像和文档：<code>messages.content</code> 数组中的内容块，位于 user 轮</li>
<li>工具使用和工具结果：<code>messages.content</code> 数组中的内容块，适用于 user 和 assistant 两轮</li>
</ul>
<h3 id="哪些内容不能缓存">哪些内容不能缓存:</h3>
<ul>
<li>
<p>Thinking 块不能用 <code>cache_control</code> 直接缓存。但是，当 thinking 块出现在先前的 assistant 轮中时，它们可以与其他内容一起被缓存。以这种方式缓存时，从缓存读取时它们会计入输入 token。</p>
</li>
<li>
<p>子内容块（例如 <a href="https://platform.claude.com/docs/en/build-with-claude/citations">citations</a>）本身不能直接缓存。应改为缓存顶层块。</p>
<p>对于 citations，作为 citations 源材料的顶层文档内容块可以缓存。这样你可以通过缓存 citations 将引用的文档，有效地将 Prompt Caching 与 citations 一起使用。</p>
</li>
<li>
<p>空文本块不能缓存。</p>
</li>
</ul>
<h3 id="哪些会使缓存失效">哪些会使缓存失效:</h3>
<table>
	<thead>
			<tr>
					<th>变更内容</th>
					<th>Tools 缓存</th>
					<th>System 缓存</th>
					<th>Messages 缓存</th>
					<th>影响</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><strong>工具定义</strong></td>
					<td>✘</td>
					<td>✘</td>
					<td>✘</td>
					<td>修改工具定义（名称、描述、参数）会使整个缓存失效</td>
			</tr>
			<tr>
					<td><strong>Web search 开关</strong></td>
					<td>✓</td>
					<td>✘</td>
					<td>✘</td>
					<td>启用/禁用 web search 会修改 system prompt</td>
			</tr>
			<tr>
					<td><strong>Citations 开关</strong></td>
					<td>✓</td>
					<td>✘</td>
					<td>✘</td>
					<td>启用/禁用 citations 会修改 system prompt</td>
			</tr>
			<tr>
					<td><strong>速度设置</strong></td>
					<td>✓</td>
					<td>✘</td>
					<td>✘</td>
					<td>在 <a href="https://platform.claude.com/docs/en/build-with-claude/fast-mode"><code>speed: &quot;fast&quot;</code> 与标准速度</a> 之间切换会使 system 和 message 缓存失效</td>
			</tr>
			<tr>
					<td><strong>Tool choice</strong></td>
					<td>✓</td>
					<td>✓</td>
					<td>✘</td>
					<td>对 <code>tool_choice</code> 参数的更改只影响 message 块</td>
			</tr>
			<tr>
					<td><strong>图像</strong></td>
					<td>✓</td>
					<td>✓</td>
					<td>✘</td>
					<td>在 prompt 任意位置添加/移除图像会影响 message 块</td>
			</tr>
			<tr>
					<td><strong>Thinking 参数</strong></td>
					<td>因模型而异</td>
					<td>因模型而异</td>
					<td>✘</td>
					<td>thinking 配置（模式，以及 extended mode 中的 <code>budget_tokens</code>）会被渲染进 prompt，因此更改它总会使 message 块失效；在把该配置渲染在它们之前的模型上，tool 和 system 缓存也会失效。参见 <a href="https://platform.claude.com/docs/en/build-with-claude/thinking#thinking-and-prompt-caching">Thinking and prompt caching</a>。</td>
			</tr>
			<tr>
					<td><strong>Effort 设置</strong></td>
					<td>因模型而异</td>
					<td>因模型而异</td>
					<td>✘</td>
					<td>更改 <a href="https://platform.claude.com/docs/en/build-with-claude/effort"><code>output_config.effort</code></a> 值总会使 message 块失效，对 tool 和 system 缓存的模型相关影响与 thinking 参数相同。将 effort 显式设为模型默认值等价于省略它，不会使缓存失效。在支持<a href="https://platform.claude.com/docs/en/build-with-claude/effort#change-effort-mid-conversation-beta">逐条消息 effort</a> 的模型上，通过 <code>messages</code> 内 <code>role: &quot;system&quot;</code> 消息携带的 effort 变更会保持缓存前缀完好。</td>
			</tr>
			<tr>
					<td><strong>传入 extended thinking 请求的非工具结果</strong></td>
					<td>✓</td>
					<td>✓</td>
					<td>因模型而异</td>
					<td>在 Opus 4.5+ 和 Sonnet 4.6+ 上，thinking 块默认被保留，因此缓存仍然有效（✓）。在更早的 Opus/Sonnet 模型以及所有 Haiku 模型上，所有先前已缓存的 thinking 块会从上下文中剥离，跟随这些 thinking 块的任何消息也会从缓存中移除（✘）。更多详情见 <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#caching-with-thinking-blocks">Caching with thinking blocks</a>。</td>
			</tr>
			<tr>
					<td><strong>被丢弃的 thinking 块</strong></td>
					<td>✓</td>
					<td>✓</td>
					<td>✘</td>
					<td>当 API 丢弃一个在该请求上未被<a href="https://platform.claude.com/docs/en/build-with-claude/thinking#preserved-thinking">保留</a> 的 Claude Fable 5.1 或 Claude Mythos 5.1 thinking 块时（例如，你把它重放到更早的模型），该请求上从该块位置起的缓存前缀会发生变化。接收模型能够读取、且原样传回的块会保持缓存完好。</td>
			</tr>
	</tbody>
</table>
<h3 id="理解token分解">理解token分解</h3>
<p><code>input_tokens</code> 字段只表示请求中<strong>最后一个缓存断点之后</strong>的 token——并非你发送的全部输入 token。</p>
<h3 id="缓存存储和共享">缓存存储和共享</h3>
<p>Prompt Caching使用workspace级别隔离</p>
<h2 id="预热缓存">预热缓存</h2>
<p>在用户的真实请求之前,把system prompt或者tools等加载进prompt cache中
降低TTFT</p>
<h3 id="工作原理-1">工作原理:</h3>
<p>在请求中设置 <code>max_tokens: 0</code>。API 将你的 prompt 读入模型，并在任何 <code>cache_control</code> 断点处写入缓存，然后立即返回而不生成任何输出。响应包含空的 <code>content</code> 数组、<code>stop_reason: &quot;max_tokens&quot;</code>，以及完整填充的 <code>usage</code> 块。
将 <code>cache_control</code> 断点放在与后续请求共享的最后一个块上
这意味着应使用<a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#explicit-cache-breakpoints">显式缓存断点</a>而不是<a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#automatic-caching">自动缓存</a>，因为自动缓存会把断点放在最后一个块上，而这里最后一个块就是占位符。占位用户消息可以是任何含非空白内容的字符串（此处示例使用 <code>&quot;warmup&quot;</code>）</p>
<h1 id="mid-conversation-system-messages-and-tool-changes">Mid-conversation system messages and tool changes</h1>
<h2 id="基础内容">基础内容</h2>
<p>System指令通常放在顶层的System字段当中,非常适合Prompt Caching
Mid-conversation system message可以在不改变顶层System字段的情况下,追加{role: system}指令,且不会将其视为text文本而是视为system指令</p>
<h2 id="mid-conversation-tool-change">Mid-conversation tool change</h2>
<p>tool数组在prefix中的位置比顶层的system字段还要靠前,编辑它会使缓存失效
Mid-conversation tool change机制允许你不需要把工具列表固定为整段对话生命周期内不变,而是可以在turn之间更改向模型提供哪些工具:
预先在tools中声明完整的工具集,然后使用tool_addition和tool_removal块,在对话中提供工具或者撤回工具,而tools数组本身不改变
tool_addition和tool_removal是role: system消息的content block
每个块的tool字段引用一项工具而不是定义工具:{&ldquo;type&rdquo;: &ldquo;tool_reference&rdquo;, &ldquo;name&rdquo;: &ldquo;&hellip;&rdquo;}
tools中生命的某项工具从对话开始就会提供给模型,除非声明时哎呦defer_loading: true,就会被保留直到tool_addition将其呈现出来
此外tool_addition也可以重新提供之前被tool_removal的工具</p>
<h2 id="何时使用mid-conversation-system-message">何时使用mid-conversation system message:</h2>
<p>会话中的mid-conversation把指令加在消息历史的末尾</p>
<h2 id="工作原理-2">工作原理</h2>
<p>指令冲突时,较后的system message优先于较前的,相应的,mid-conversation system message优先级高于顶层system字段
<code>role: &quot;system&quot;</code> 消息还可以携带 <code>output_config.effort</code>，从下一个 <code>user</code> turn 起更改 <a href="https://platform.claude.com/docs/en/build-with-claude/effort">effort</a> 级别(此处的effort为占位符,具体为论文low,high等等)</p>
<h3 id="system-message的位置">system message的位置:</h3>
<p>在user turn(或者是server tool result结尾的assistant)之后,并且必须是messages中的最后一项或者紧接着的一个assistant turn.
放在交付tool result的user之后,下一个turn之前</p>
<h3 id="放在tool-result之后">放在tool result之后</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="p">[</span>
</span></span><span class="line"><span class="cl">  <span class="p">{</span> <span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span> <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;Run the test suite and fix any failures.&#34;</span> <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;assistant&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="p">[{</span> <span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;tool_use&#34;</span><span class="p">,</span> <span class="s2">&#34;id&#34;</span><span class="p">:</span> <span class="s2">&#34;toolu_01&#34;</span><span class="p">,</span> <span class="s2">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;run_tests&#34;</span><span class="p">,</span> <span class="s2">&#34;input&#34;</span><span class="p">:</span> <span class="p">{}</span> <span class="p">}]</span>
</span></span><span class="line"><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">      <span class="p">{</span> <span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;tool_result&#34;</span><span class="p">,</span> <span class="s2">&#34;tool_use_id&#34;</span><span class="p">:</span> <span class="s2">&#34;toolu_01&#34;</span><span class="p">,</span> <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;12 passed, 0 failed&#34;</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">]</span>
</span></span><span class="line"><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;system&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;The user sent the following message while you were working: also update the changelog before you finish.&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">]</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>此模式用于转达来自该对话最终用户本人的输入。不要用它传递工具输出、检索到的文档或其他第三方内容；将这些内容放在 <code>tool_result</code> 块中（参见 <a href="https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages#limitations">限制</a>）。</p>
<h3 id="限定当前turn的system-message">限定当前turn的system message:</h3>
<p>使用clear_at字段,它有两个取值:</p>
<ul>
<li>&ldquo;never&rdquo;:该消息在包含它的每次请求中都会在其位置渲染</li>
<li>&ldquo;next_user_message&rdquo;:限定当前turn的,其文本仅在message中其后灭有role: user消息时渲染
此外,仅携带tool_result的user消息也算用户消息</li>
</ul>
<p>一旦存在更后恶的user_message,该消息就会被清除,仍留在数组中但是不渲染也不占输入</p>
<p>限定当前turn的消息的规则:</p>
<ul>
<li>应该逐字重发已经清除的消息而不是更改clear_at值</li>
<li>type仅限于文本</li>
<li>其block上不能有cache_control</li>
<li>位置规则依然生效,无论是否被清除</li>
<li>assistant turn不会清除它,只有user message会清除它</li>
<li>token count更碎渲染内容,被清除的消息不会增加user.input_token,也不会增加token计数</li>
<li>导出,在被清除之后就不被渲染</li>
</ul>
<h2 id="限制">限制</h2>
<ul>
<li>不能作为第一条消息,毕竟你为什么不放在顶层的system字段中呢?</li>
<li>放置的位置收到约束</li>
<li>限制在当前turn的system的type仅限为文本</li>
<li>不要放置在不受信任的地方</li>
</ul>
<h1 id="build-an-orchestration-mode">Build an orchestration mode</h1>
<p>编排模式是一个会话级别的开关:当开启时,对于每一个任务都是最大级别的effort(agent的思考程度),并将工作默认fan-out给并行的子代理</p>
<p>该模式不是API参数,是由文档中的已有的组件构成的:</p>
<ol>
<li>1.effort级别:最大的effort的取值</li>
<li>a refresher:一条mid-conversation system message告知模式的开启,并且每隔几个对话带一行刷新提醒,并在关闭模式的时候发出通知</li>
<li>工具描述中的持续性授权</li>
</ol>
<p>note:fan-out会成本的增加成本
实际上使用subagent就是很烧钱</p>
<h2 id="设置循环">设置循环</h2>
<p>三个参数:
<code>MAX_CONCURRENT</code> 限制同时运行的子代理数量;
<code>MAX_TOTAL_SUBTASKS</code> 限制模型在单次 Workflow 调用中可以排队的数量;
当设置了环境变量 <code>DOC_TEST_MODE</code> = TRUE 时，该检查会把循环限制为单轮，以便自动化文档 harness 验证文件能够编译并迅速结束，而无需跑完整编排
通过常量来控制effort的等级(实际上就是最高的effort),fan-out的形态和refresher的频率</p>
<h2 id="定义模式refresher和notice包括enter和exit">定义模式refresher和notice(包括ENTER和EXIT)</h2>
<p>这些message都刻意地写的很短,他们切换模式并且指向工具描述(workflow工具)&ndash;重量级的指令就在那
ENTER只在开启模式时发送一次,refresh则每隔几个turns发送一次,exit_notice则只在模式关闭的时候发送一次</p>
<h2 id="在工具描述中授予持续性权限">在工具描述中授予持续性权限</h2>
<p>Workflow工具承载真正的行为契约:
opt-in规则(指的是进入编排模式的规则是需要用户主动同意的),模式开启期间适用的持续性授权,用于确定fan-out规模的粒度指引,还有模式可以采取的质量检测模式如:验证波、完备性批评者、多阶段分步</p>
<p>而子代理则会得到一个report_finging工具,使其结果JSON结构化
bash工具则是Anthropic定义的bash_20250124,在本地运行</p>
<p>Workflow_tool定义非常的长,有兴趣自己去看一看</p>
<h2 id="在本地运行bash工具">在本地运行bash工具</h2>
<p>为什么会强调是本地运行呢?
强调你harness的运行环境,比如Windows,Linux,云服务器等等</p>
<p>Bash处理器运行带有timeout的命令,并且捕获合并后的stdout和stderr并截断结果,防止失控命令淹没上下文
命令的运行环境就是你启动模式对应的文件目录
而当你设置了DOC_TEST_MODE= TRUE时,harness会改为给bash一个小型的一次性目录,在退出时直接删除</p>
<h2 id="运行一个子代理subagent">运行一个子代理Subagent</h2>
<p>每一个workflow的子任务都会变成带bash工具的小型代理循环,并且effort等级于主agent相等
每次API调用都有按请求的超时上限,所以连接中断只会让一个子代理降级,而不会卡住整个运行</p>
<h2 id="将结果写入jouornal方便重跑时continue">将结果写入jouornal,方便重跑时continue</h2>
<p>启动子代理冲头开始的成本很高,一个小型的基于内容寻址的journal使其幂等:
在fan-out subagent之前,现在本地的JSON文件中寻找它的prompt的SHA-256,如果已经有记录了就返回该结果.中断运行后再跑,就只有没有完成的子任务会被重新计算
journal会在多次运行中去重,但是不会在单次fan-out内去重
如果你想从头再来,那你就删掉journal</p>
<h2 id="先fan-out再验证">先fan-out,再验证</h2>
<p>fan-out 最多接受 <code>MAX_TOTAL_SUBTASKS</code> 条 prompt，经 journal 运行，同时进行中的不超过 <code>MAX_CONCURRENT</code> 个,并隔离失败,使得一个损坏的子代理降级为字符串,而不是使得整个运行失败
第一波fan-out完成之后,会复用同一条子代理路径,视图反驳每一条结果</p>
<h2 id="用mid-conversation的system-message切换模式">用Mid-conversation的system message切换模式</h2>
<p>代理先追加用户信息,再追加本轮的system message,这样更适合于prompt caching</p>
<h2 id="迈向生产级harness">迈向生产级Harness</h2>
<ul>
<li>带沙箱的编排脚本</li>
<li>持久journaling</li>
<li>预算强制</li>
</ul>
<h1 id="cache-diagnostics">Cache diagnostics</h1>
<p>在没有Cache diagnostic的情况下,缓存失效的唯一信号是usage.cache_read_input_tokens = 0
Cache diagnostic通过API对比两次请求,告诉你他们在哪处分叉(（model、system prompt、tools 或消息历史）),而你需要做的仅仅是传入上一次响应的ID
解析:通过分析请求的前缀结构,来查看前后两次请求的前缀最开始的不匹配处也就是分叉处</p>
<h2 id="how-to-work">How to work</h2>
<p>当beta header存在,API会给每个request存储一份fingerprint,且将其与id建立起key-value的关系,而在下一次的请求中,将该 <code>id</code> 作为<code>diagnostics.previous_message_id</code> 传入
然后API会给新的request创建一个新的fingerprint,通过id访问前一个请求的fingerprint和当前请求的fingerprint进行对比
对比针对的是请求的结构,与缓存实际命中无关,所以结合起来使用可以帮助你分析为什么缓存失效了
fingerprint的内容包括:
哈希和token数量估计(绝对不包含原始的prompt),保存时间有限且scope为你的workspace</p>
<h2 id="基本用法-1">基本用法:</h2>
<p>每一次turn都发送beta header,第一次传入的id为null,后续每一次请求传入上一次响应中的id</p>
<h2 id="stream">Stream:</h2>
<p>在stream中,diagnostic出现在message_start事件上
message_start事件携带完整的diagnostic字段</p>
<h2 id="在对话循环中贯穿diagnostic">在对话循环中贯穿diagnostic</h2>
<h2 id="响应格式">响应格式:</h2>
<p>响应message上的diagnostic可能有以下四种状态</p>
<table>
	<thead>
			<tr>
					<th>取值</th>
					<th>含义</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>字段缺失</td>
					<td>请求未包含 <code>diagnostics</code>，或缺少 beta header。</td>
			</tr>
			<tr>
					<td><code>null</code></td>
					<td>要么 <code>previous_message_id</code> 为 <code>null</code>（第一 turn，没有可对比的内容），要么对比已完成且未发现分叉。</td>
			</tr>
			<tr>
					<td><code>{&quot;cache_miss_reason&quot;: null}</code></td>
					<td>响应序列化时对比仍在进行。响应启动非常快时可能出现这种情况。将其视为尚无结论，并在下一 turn 再检查。</td>
			</tr>
			<tr>
					<td><code>{&quot;cache_miss_reason&quot;: {...}}</code></td>
					<td>附带了 <code>cache_miss_reason</code>。对于 <code>*_changed</code> 类型，它标识第一个分歧点；<code>previous_message_not_found</code> 和 <code>unavailable</code> 表示未产生对比结果。</td>
			</tr>
	</tbody>
</table>
<p>当cache miss!= null时,形态如下:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">{
</span></span><span class="line"><span class="cl">  &#34;id&#34;: &#34;msg_01Xyz...&#34;,
</span></span><span class="line"><span class="cl">  &#34;type&#34;: &#34;message&#34;,
</span></span><span class="line"><span class="cl">  &#34;role&#34;: &#34;assistant&#34;,
</span></span><span class="line"><span class="cl">  &#34;content&#34;: [{ &#34;type&#34;: &#34;text&#34;, &#34;text&#34;: &#34;...&#34; }],
</span></span><span class="line"><span class="cl">  &#34;usage&#34;: {
</span></span><span class="line"><span class="cl">    &#34;input_tokens&#34;: 42,
</span></span><span class="line"><span class="cl">    &#34;cache_read_input_tokens&#34;: 0,
</span></span><span class="line"><span class="cl">    &#34;cache_creation_input_tokens&#34;: 41850,
</span></span><span class="line"><span class="cl">    &#34;output_tokens&#34;: 210
</span></span><span class="line"><span class="cl">  },
</span></span><span class="line"><span class="cl">  &#34;diagnostics&#34;: {
</span></span><span class="line"><span class="cl">    &#34;cache_miss_reason&#34;: {
</span></span><span class="line"><span class="cl">      &#34;type&#34;: &#34;system_changed&#34;,
</span></span><span class="line"><span class="cl">      &#34;cache_missed_input_tokens&#34;: 41850
</span></span><span class="line"><span class="cl">    }
</span></span><span class="line"><span class="cl">  }
</span></span><span class="line"><span class="cl">}
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="缓存未命中原因类型">缓存未命中原因类型</h2>
<table>
	<thead>
			<tr>
					<th>类型</th>
					<th>含义</th>
					<th>需要改什么</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>model_changed</code></td>
					<td><code>model</code> 与上一次请求不同（例如路由器、A/B 测试或回退选择了不同的 model）。缓存是按 model 隔离的。</td>
					<td>在使用缓存的对话中保持 model 不变。</td>
			</tr>
			<tr>
					<td><code>system_changed</code></td>
					<td><code>system</code> 参数不同。通常是时间戳、request ID 或其他每次请求都会变的值被插入到了 system prompt 中。</td>
					<td>将 system prompt 做成逐字节稳定的常量，并把动态数据移到缓存断点之后的第一条 <code>user</code> 消息中。</td>
			</tr>
			<tr>
					<td><code>tools_changed</code></td>
					<td><code>tools</code> 数组不同：turn 之间添加、删除或重排了 tools，或者 tool 的 <code>input_schema</code> JSON 序列化不稳定。</td>
					<td>每一 turn 以固定顺序发送相同的 tool 列表，并使用确定性序列化的 schema（例如对 key 排序）。</td>
			</tr>
			<tr>
					<td><code>messages_changed</code></td>
					<td>model、system 和 tools 都匹配，但 <code>messages</code> 中更早的某条被改动、重排或删除，而不是追加。通常是对话历史被截断或编辑，或在重发时 assistant turn 和 <code>tool_result</code> 块被以不同方式重新序列化。</td>
					<td>将历史视为只追加；原样回传 assistant <code>content</code> 和 tool 结果。</td>
			</tr>
			<tr>
					<td><code>previous_message_not_found</code></td>
					<td>所提供的 <code>previous_message_id</code> 没有对应的已存储 fingerprint。这并不证明你的请求发生了变化。通常是上一次请求未携带 beta header、来自不同的 workspace，或距离发送已经过了太久。</td>
					<td>每一 turn 都发送 beta header，并让连续 turn 在时间上尽量靠近。</td>
			</tr>
			<tr>
					<td><code>unavailable</code></td>
					<td>本次请求没有可用的 diagnostic 信息。包括 <code>model</code>、<code>system</code> 和 <code>tools</code> 都匹配，但另一个会影响 prompt 的请求参数（<code>tool_choice</code>、<code>thinking</code>、<code>context_management</code>、<code>output_config</code>、<code>output_format</code>，或当前生效的 <code>anthropic-beta</code> header 集合）不同，以及超长对话中分歧点超出对比范围的情况。你的请求已正常处理。</td>
					<td>在使用缓存的对话生命周期内，保持会影响 prompt 的请求参数不变。若问题持续，按提示词缓存页面 <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#troubleshooting-common-issues">排查常见问题</a> 下的手动检查处理。</td>
			</tr>
	</tbody>
</table>
<p>note:</p>
<p>四种 <code>*_changed</code> 类型还会附带一个 <code>cache_missed_input_tokens</code> 整数：估计有多少 input token 落在分歧点之后，让你对损失了多少可缓存前缀有个量级感。该值由 tokenization 之前的字节长度推导，因此应视为量级指标而非计费数字。它可能与 <code>usage.input_tokens</code> 不同（偶尔还会更大）。</p>
<h2 id="结合usage解读diagnostic">结合usage解读diagnostic</h2>
<p><code>diagnostics</code> 回答「我的请求变了吗？
<code>usage.cache_read_input_tokens</code> 回答「缓存命中了吗？」
两者结合可惜分析缓存未命中的原因</p>
<table>
	<thead>
			<tr>
					<th>agnostics 结果</th>
					<th>缓存读取 token</th>
					<th>解读</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>null</code></td>
					<td>高</td>
					<td>符合预期。你的前缀稳定且缓存命中。</td>
			</tr>
			<tr>
					<td><code>null</code></td>
					<td>低或为零</td>
					<td>请求匹配，但缓存条目已不再可用。考虑缩短 turn 之间的间隔，或使用 <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#1-hour-cache-duration">1 小时缓存 TTL</a>。</td>
			</tr>
			<tr>
					<td><code>cache_miss_reason</code> 为 <code>*_changed</code> 类型</td>
					<td>低或为零</td>
					<td>你这边的 bug。请求发生了变化；按 <code>type</code> 所示原因修复。</td>
			</tr>
			<tr>
					<td><code>cache_miss_reason</code> 为 <code>*_changed</code> 类型</td>
					<td>高</td>
					<td>少见。变化发生在 prompt 较后位置，但更早的 <code>cache_control</code> 断点仍然命中。值得修复，但影响较小。</td>
			</tr>
	</tbody>
</table>
<h1 id="token-counting">Token counting</h1>
<p>作用:在你把message发给Claude之前确定其中的token数量</p>
<h2></h2>
<h2 id="如何统计-message-tokens">如何统计 message tokens</h2>
<p><a href="https://platform.claude.com/docs/en/api/messages-count-tokens">token counting</a> endpoint 接受与创建 message 相同的结构化输入列表，包括对 system prompt、<a href="https://platform.claude.com/docs/en/agents-and-tools/tool-use/overview">tools</a>、<a href="https://platform.claude.com/docs/en/build-with-claude/vision">images</a> 和 <a href="https://platform.claude.com/docs/en/build-with-claude/pdf-support">PDFs</a> 的支持。响应中包含输入 tokens 的总数。</p>
<p>对于 Messages API 会接受、但本 endpoint 不接受的少数输入，该 endpoint 会返回 <code>invalid_request_error</code>：例如 web search、web fetch、code execution 和 tool search 等 <a href="https://platform.claude.com/docs/en/agents-and-tools/tool-use/server-tools">server tools</a>（<a href="https://platform.claude.com/docs/en/agents-and-tools/tool-use/advisor-tool">advisor tool</a> 除外的所有 server tool）、<a href="https://platform.claude.com/docs/en/agents-and-tools/mcp-connector">MCP connector</a>，以及 <code>source</code> 为 <code>url</code> 或 <code>file</code> 的 <code>image</code> 或 <code>document</code> blocks。统计图片和 PDF 时请以 base64 发送。对于使用 server tools 或 MCP servers 的请求，Messages API 响应会在其 <code>usage</code> 对象中报告所用 tokens。</p>
<Note>
  Token 计数是一个**估计**。在某些情况下，创建 message 时实际使用的输入 tokens 数量可能有小幅差异。
<p>Token 计数可能包含 Anthropic 为系统优化自动添加的 tokens。<strong>系统添加的 tokens 不会向你计费</strong>。计费只反映你的内容。
</Note></p>
]]></content:encoded>
    </item>
    <item>
      <title>上下文编辑</title>
      <link>https://tuanzi-wow.cn/%E4%B8%8A%E4%B8%8B%E6%96%87%E5%B7%A5%E7%A8%8B/claudecode_context_management_cn/context-editing/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://tuanzi-wow.cn/%E4%B8%8A%E4%B8%8B%E6%96%87%E5%B7%A5%E7%A8%8B/claudecode_context_management_cn/context-editing/</guid>
      <description>随着对话增长，通过上下文编辑自动管理对话上下文。</description>
      <content:encoded><![CDATA[<Note>
  要了解零数据保留（ZDR）如何适用于此功能，请参阅 [API 与数据保留](https://platform.claude.com/docs/en/manage-claude/api-and-data-retention)。
</Note>
<h2 id="概述">概述</h2>
<Note>
  对于大多数用例，[服务端压缩（server-side compaction）](https://platform.claude.com/docs/en/build-with-claude/compaction) 是管理长对话上下文的主要策略。本页中的策略适用于需要更精细控制清除哪些内容的特定场景。
</Note>
<p>上下文编辑（context editing）允许你在对话历史增长时有选择地清除特定内容。这不仅是为了优化成本并保持在限制之内，更是为了主动筛选 Claude 所见的内容：上下文是一种收益递减的有限资源，无关内容会降低模型的专注度。上下文编辑让你在运行时对这些筛选进行精细控制。有关上下文管理背后的更广泛原则，请参阅 <a href="https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents">有效的上下文工程</a>。本页涵盖：</p>
<ul>
<li><strong>工具结果清除</strong> - 最适合大量使用工具、旧工具结果不再需要的智能体工作流</li>
<li><strong>thinking block 清除</strong> - 用于在使用 extended thinking 时管理 thinking block，可选择保留近期 thinking 以维持上下文连续性</li>
<li><strong>客户端 SDK 压缩</strong> - 一种基于 SDK 的摘要式上下文管理替代方案（通常更推荐服务端压缩）</li>
</ul>
<table>
	<thead>
			<tr>
					<th>方法</th>
					<th>运行位置</th>
					<th>策略</th>
					<th>工作原理</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><strong>服务端</strong></td>
					<td>API</td>
					<td>工具结果清除（<code>clear_tool_uses_20250919</code>） thinking block 清除（<code>clear_thinking_20251015</code>）</td>
					<td>在 prompt 到达 Claude 之前应用。从对话历史中清除特定内容。每种策略可独立配置。</td>
			</tr>
			<tr>
					<td><strong>客户端</strong></td>
					<td>SDK</td>
					<td>压缩</td>
					<td>在使用 <a href="https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-runner"><code>tool_runner</code></a> 时，<a href="https://platform.claude.com/docs/en/cli-sdks-libraries/overview">TypeScript 和 Ruby SDK</a> 中可用。生成摘要并替换完整对话历史。参见 <a href="https://platform.claude.com/docs/en/build-with-claude/context-editing#client-side-compaction-sdk">客户端压缩</a>。</td>
			</tr>
	</tbody>
</table>
<h2 id="服务端策略">服务端策略</h2>
<Note>
  上下文编辑目前处于 beta，支持工具结果清除和 thinking block 清除。要启用它，请在 API 请求中使用 beta 标头 `context-management-2025-06-27`。
<p>通过 <a href="https://forms.gle/YXC2EKGMhjN1c4L88">反馈表单</a> 分享对此功能的反馈。
</Note></p>
<h3 id="工具结果清除">工具结果清除</h3>
<p><code>clear_tool_uses_20250919</code> 策略会在对话上下文增长超过你配置的阈值时清除工具结果。这尤其适用于大量使用工具的智能体工作流。较旧的工具结果（如文件内容或搜索结果）在 Claude 处理完后便不再需要。</p>
<p>激活后，API 会按时间顺序自动清除最旧的工具结果。API 会将每个被清除的结果替换为占位文本，向 Claude 表明该结果已被移除。默认情况下，仅清除工具结果。你可以通过将 <code>clear_tool_inputs</code> 设为 true，选择同时清除工具结果和工具调用（工具使用参数）。</p>
<h3 id="thinking-block-清除">thinking block 清除</h3>
<p><code>clear_thinking_20251015</code> 策略在启用 extended thinking 时管理对话中的 <code>thinking</code> block。该策略让你控制 thinking 的保留：你可以选择保留更多 thinking block 以维持推理连续性，或更积极地清除它们以节省上下文空间。</p>
<Tip>
  **默认行为：** 默认值因模型类别而异。
<table>
	<thead>
			<tr>
					<th>模型类别</th>
					<th>保留所有先前 thinking</th>
					<th>仅保留上一轮的 thinking</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Opus</td>
					<td>Claude Opus 4.5 及更高版本</td>
					<td>Claude Opus 4.1 及更早版本</td>
			</tr>
			<tr>
					<td>Sonnet</td>
					<td>Claude Sonnet 4.6 及更高版本</td>
					<td>Claude Sonnet 4.5 及更早版本</td>
			</tr>
			<tr>
					<td>Haiku</td>
					<td>（无）</td>
					<td>直至 Claude Haiku 4.5 的所有模型</td>
			</tr>
			<tr>
					<td>Fable 和 Mythos</td>
					<td>所有模型</td>
					<td>（无）</td>
			</tr>
	</tbody>
</table>
<p>使用此策略可覆盖默认值。如果你的代码会跨多个模型层级运行，请显式设置 <code>keep</code>，而不是依赖各模型的默认值。
</Tip></p>
<p>一个 assistant 对话轮次可能包含多个内容块（例如在使用工具时）以及多个 thinking block（例如使用 <a href="https://platform.claude.com/docs/en/build-with-claude/thinking#interleaved-thinking">interleaved thinking</a> 时）。</p>
<h3 id="上下文编辑发生在服务端">上下文编辑发生在服务端</h3>
<p>上下文编辑在 prompt 到达 Claude 之前于服务端应用。你的客户端应用保持完整、未修改的对话历史。你无需将客户端状态与编辑后的版本同步。继续像往常一样在本地管理完整的对话历史。</p>
<p>在 Claude Fable 5.1 上，服务端上下文管理从不使 thinking block 失效。对更早轮次的客户端编辑会使之后每个 assistant 轮次中的 thinking block 失效。对于 2026 年 8 月 31 日或之后创建的新账户，重放已失效 block 的请求会被拒绝，除非你选择丢弃它。参见 <a href="https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#prefix-check">保持前缀不变</a>。</p>
<h3 id="上下文编辑与-prompt-caching">上下文编辑与 Prompt Caching</h3>
<p>上下文编辑与 <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching">Prompt Caching</a> 的交互因策略而异：</p>
<ul>
<li>
<p><strong>工具结果清除：</strong> 在内容被清除时会使已缓存的 prompt 前缀失效。为此，应清除足够多的 token，使缓存失效物有所值。使用 <code>clear_at_least</code> 参数确保每次至少清除最低数量的 token。每次内容被清除时你会产生缓存写入费用，但后续请求可以复用新缓存的前缀。</p>
</li>
<li>
<p><strong>thinking block 清除：</strong> 当 thinking block <strong>被保留</strong>在上下文中（未被清除）时，prompt 缓存得以保留，从而能够命中缓存并降低输入 token 成本。当 thinking block <strong>被清除</strong>时，缓存会在清除发生处失效。根据你是优先考虑缓存性能还是上下文窗口可用性，配置 <code>keep</code> 参数。</p>
</li>
</ul>
<h2 id="支持的模型">支持的模型</h2>
<p>上下文编辑适用于所有受支持的 Claude 模型。</p>
<h2 id="工具结果清除用法">工具结果清除用法</h2>
<p>启用工具结果清除的最简单方式是仅指定策略类型。所有其他 <a href="https://platform.claude.com/docs/en/build-with-claude/context-editing#configuration-options-for-tool-result-clearing">配置选项</a> 使用其默认值：</p>
<CodeGroup>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">response</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">beta</span><span class="o">.</span><span class="n">messages</span><span class="o">.</span><span class="n">create</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">model</span><span class="o">=</span><span class="s2">&#34;claude-opus-5&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">max_tokens</span><span class="o">=</span><span class="mi">4096</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">messages</span><span class="o">=</span><span class="p">[{</span><span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span> <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;Search for recent developments in AI&#34;</span><span class="p">}],</span>
</span></span><span class="line"><span class="cl">    <span class="n">tools</span><span class="o">=</span><span class="p">[{</span><span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;web_search_20250305&#34;</span><span class="p">,</span> <span class="s2">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;web_search&#34;</span><span class="p">}],</span>
</span></span><span class="line"><span class="cl">    <span class="n">betas</span><span class="o">=</span><span class="p">[</span><span class="s2">&#34;context-management-2025-06-27&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">    <span class="n">context_management</span><span class="o">=</span><span class="p">{</span><span class="s2">&#34;edits&#34;</span><span class="p">:</span> <span class="p">[{</span><span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;clear_tool_uses_20250919&#34;</span><span class="p">}]},</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span></code></pre></td></tr></table>
</div>
</div></CodeGroup>
<h3 id="高级配置">高级配置</h3>
<p>你可以使用其他参数自定义工具结果清除行为：</p>
<CodeGroup>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">response</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">beta</span><span class="o">.</span><span class="n">messages</span><span class="o">.</span><span class="n">create</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">model</span><span class="o">=</span><span class="s2">&#34;claude-opus-5&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">max_tokens</span><span class="o">=</span><span class="mi">4096</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">messages</span><span class="o">=</span><span class="p">[</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;Create a simple command line calculator app using Python&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">],</span>
</span></span><span class="line"><span class="cl">    <span class="n">tools</span><span class="o">=</span><span class="p">[</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;text_editor_20250728&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;str_replace_based_edit_tool&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;max_characters&#34;</span><span class="p">:</span> <span class="mi">10000</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="p">},</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span><span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;web_search_20250305&#34;</span><span class="p">,</span> <span class="s2">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;web_search&#34;</span><span class="p">,</span> <span class="s2">&#34;max_uses&#34;</span><span class="p">:</span> <span class="mi">3</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">],</span>
</span></span><span class="line"><span class="cl">    <span class="n">betas</span><span class="o">=</span><span class="p">[</span><span class="s2">&#34;context-management-2025-06-27&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">    <span class="n">context_management</span><span class="o">=</span><span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;edits&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">            <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;clear_tool_uses_20250919&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="c1"># Trigger clearing when threshold is exceeded</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;trigger&#34;</span><span class="p">:</span> <span class="p">{</span><span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;input_tokens&#34;</span><span class="p">,</span> <span class="s2">&#34;value&#34;</span><span class="p">:</span> <span class="mi">30000</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">                <span class="c1"># Number of tool uses to keep after clearing</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;keep&#34;</span><span class="p">:</span> <span class="p">{</span><span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;tool_uses&#34;</span><span class="p">,</span> <span class="s2">&#34;value&#34;</span><span class="p">:</span> <span class="mi">3</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">                <span class="c1"># Optional: Clear at least this many tokens</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;clear_at_least&#34;</span><span class="p">:</span> <span class="p">{</span><span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;input_tokens&#34;</span><span class="p">,</span> <span class="s2">&#34;value&#34;</span><span class="p">:</span> <span class="mi">5000</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">                <span class="c1"># Exclude these tools from being cleared</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;exclude_tools&#34;</span><span class="p">:</span> <span class="p">[</span><span class="s2">&#34;web_search&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span></code></pre></td></tr></table>
</div>
</div></CodeGroup>
<h2 id="thinking-block-清除用法">thinking block 清除用法</h2>
<p>启用 thinking block 清除，以便在启用 extended thinking 时有效管理上下文和 Prompt Caching：</p>
<CodeGroup>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">response</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">beta</span><span class="o">.</span><span class="n">messages</span><span class="o">.</span><span class="n">create</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">model</span><span class="o">=</span><span class="s2">&#34;claude-opus-5&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">max_tokens</span><span class="o">=</span><span class="mi">16000</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">messages</span><span class="o">=</span><span class="p">[{</span><span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span> <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;Hello&#34;</span><span class="p">}],</span>
</span></span><span class="line"><span class="cl">    <span class="n">betas</span><span class="o">=</span><span class="p">[</span><span class="s2">&#34;context-management-2025-06-27&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">    <span class="n">context_management</span><span class="o">=</span><span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;edits&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">            <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;clear_thinking_20251015&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;keep&#34;</span><span class="p">:</span> <span class="p">{</span><span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;thinking_turns&#34;</span><span class="p">,</span> <span class="s2">&#34;value&#34;</span><span class="p">:</span> <span class="mi">2</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span></code></pre></td></tr></table>
</div>
</div></CodeGroup>
<h3 id="thinking-block-清除的配置选项">thinking block 清除的配置选项</h3>
<p><code>clear_thinking_20251015</code> 策略支持以下配置：</p>
<table>
	<thead>
			<tr>
					<th>配置选项</th>
					<th>默认值</th>
					<th>说明</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>keep</code></td>
					<td>因模型而异</td>
					<td>定义要保留多少个包含 thinking block 的近期 assistant 轮次。使用 <code>{type: &quot;thinking_turns&quot;, value: N}</code>（N 必须 &gt; 0）以保留最近 N 轮，或使用 <code>&quot;all&quot;</code> 以保留所有 thinking block。Opus 4.5+ 和 Sonnet 4.6+：所有轮次。Fable 和 Mythos 模型：所有轮次。更早的 Opus/Sonnet 以及所有 Haiku：仅上一轮。</td>
			</tr>
	</tbody>
</table>
<p><strong>配置示例：</strong></p>
<p>保留最近 3 个 assistant 轮次的 thinking block：</p>
<CodeGroup>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">response</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">beta</span><span class="o">.</span><span class="n">messages</span><span class="o">.</span><span class="n">create</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">model</span><span class="o">=</span><span class="s2">&#34;claude-opus-5&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">max_tokens</span><span class="o">=</span><span class="mi">16000</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">messages</span><span class="o">=</span><span class="p">[{</span><span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span> <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;Hello&#34;</span><span class="p">}],</span>
</span></span><span class="line"><span class="cl">    <span class="n">betas</span><span class="o">=</span><span class="p">[</span><span class="s2">&#34;context-management-2025-06-27&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">    <span class="n">context_management</span><span class="o">=</span><span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;edits&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">            <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;clear_thinking_20251015&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;keep&#34;</span><span class="p">:</span> <span class="p">{</span><span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;thinking_turns&#34;</span><span class="p">,</span> <span class="s2">&#34;value&#34;</span><span class="p">:</span> <span class="mi">3</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span></code></pre></td></tr></table>
</div>
</div></CodeGroup>
<p>保留所有 thinking block（最大化缓存命中）：</p>
<CodeGroup>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">response</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">beta</span><span class="o">.</span><span class="n">messages</span><span class="o">.</span><span class="n">create</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">model</span><span class="o">=</span><span class="s2">&#34;claude-opus-5&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">max_tokens</span><span class="o">=</span><span class="mi">16000</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">messages</span><span class="o">=</span><span class="p">[{</span><span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span> <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;Hello&#34;</span><span class="p">}],</span>
</span></span><span class="line"><span class="cl">    <span class="n">betas</span><span class="o">=</span><span class="p">[</span><span class="s2">&#34;context-management-2025-06-27&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">    <span class="n">context_management</span><span class="o">=</span><span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;edits&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">            <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;clear_thinking_20251015&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;keep&#34;</span><span class="p">:</span> <span class="s2">&#34;all&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span></code></pre></td></tr></table>
</div>
</div></CodeGroup>
<h3 id="组合策略">组合策略</h3>
<p>你可以同时使用 thinking block 清除和工具结果清除：</p>
<Note>
  使用多种策略时，`clear_thinking_20251015` 策略必须列在 `edits` 数组的第一位。
</Note>
<CodeGroup>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">response</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">beta</span><span class="o">.</span><span class="n">messages</span><span class="o">.</span><span class="n">create</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">model</span><span class="o">=</span><span class="s2">&#34;claude-opus-5&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">max_tokens</span><span class="o">=</span><span class="mi">16000</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">messages</span><span class="o">=</span><span class="p">[</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;Search for the latest developments in quantum error correction and summarize the key breakthroughs.&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">],</span>
</span></span><span class="line"><span class="cl">    <span class="n">tools</span><span class="o">=</span><span class="p">[</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;web_search_20250305&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;web_search&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;max_uses&#34;</span><span class="p">:</span> <span class="mi">5</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">],</span>
</span></span><span class="line"><span class="cl">    <span class="n">betas</span><span class="o">=</span><span class="p">[</span><span class="s2">&#34;context-management-2025-06-27&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">    <span class="n">context_management</span><span class="o">=</span><span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;edits&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">            <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;clear_thinking_20251015&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;keep&#34;</span><span class="p">:</span> <span class="p">{</span><span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;thinking_turns&#34;</span><span class="p">,</span> <span class="s2">&#34;value&#34;</span><span class="p">:</span> <span class="mi">2</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">            <span class="p">},</span>
</span></span><span class="line"><span class="cl">            <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;clear_tool_uses_20250919&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;trigger&#34;</span><span class="p">:</span> <span class="p">{</span><span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;input_tokens&#34;</span><span class="p">,</span> <span class="s2">&#34;value&#34;</span><span class="p">:</span> <span class="mi">50000</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;keep&#34;</span><span class="p">:</span> <span class="p">{</span><span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;tool_uses&#34;</span><span class="p">,</span> <span class="s2">&#34;value&#34;</span><span class="p">:</span> <span class="mi">5</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">            <span class="p">},</span>
</span></span><span class="line"><span class="cl">        <span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">response</span><span class="p">)</span>
</span></span></code></pre></td></tr></table>
</div>
</div></CodeGroup>
<h2 id="工具结果清除的配置选项">工具结果清除的配置选项</h2>
<table>
	<thead>
			<tr>
					<th>配置选项</th>
					<th>默认值</th>
					<th>说明</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>trigger</code></td>
					<td>100,000 输入 token</td>
					<td>定义上下文编辑策略何时激活。一旦 prompt 超过此阈值，便开始清除。你可以用 <code>input_tokens</code> 或 <code>tool_uses</code> 指定此值。</td>
			</tr>
			<tr>
					<td><code>keep</code></td>
					<td>3 次工具使用</td>
					<td>定义清除发生后保留多少对近期的工具使用/结果。API 先移除最旧的工具交互，保留最近的交互。</td>
			</tr>
			<tr>
					<td><code>clear_at_least</code></td>
					<td>无</td>
					<td>确保每次策略激活时至少清除指定数量的 token。如果 API 无法至少清除指定数量，则不会应用该策略。这有助于判断上下文清除是否值得打断你的 prompt 缓存。</td>
			</tr>
			<tr>
					<td><code>exclude_tools</code></td>
					<td>无</td>
					<td>其工具使用和结果永远不应被清除的工具名称列表。适用于保留重要上下文。</td>
			</tr>
			<tr>
					<td><code>clear_tool_inputs</code></td>
					<td><code>false</code></td>
					<td>控制是否连同工具结果一起清除工具调用参数。默认情况下，仅清除工具结果，同时保持 Claude 原始的工具调用可见。</td>
			</tr>
	</tbody>
</table>
<h2 id="上下文编辑响应">上下文编辑响应</h2>
<p>你可以使用 <code>context_management</code> 响应字段查看哪些上下文编辑已应用于你的请求，以及有关已清除内容和输入 token 的有用统计信息。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;id&#34;</span><span class="p">:</span> <span class="s2">&#34;msg_013Zva2CMHLNnXjNJJKqJ2EF&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;message&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;assistant&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;content&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// ...
</span></span></span><span class="line"><span class="cl">  <span class="p">],</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;usage&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// ...
</span></span></span><span class="line"><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;context_management&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;applied_edits&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// When using `clear_thinking_20251015`
</span></span></span><span class="line"><span class="cl">      <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;clear_thinking_20251015&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;cleared_thinking_turns&#34;</span><span class="p">:</span> <span class="mi">3</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;cleared_input_tokens&#34;</span><span class="p">:</span> <span class="mi">15000</span>
</span></span><span class="line"><span class="cl">      <span class="p">},</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// When using `clear_tool_uses_20250919`
</span></span></span><span class="line"><span class="cl">      <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;clear_tool_uses_20250919&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;cleared_tool_uses&#34;</span><span class="p">:</span> <span class="mi">8</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;cleared_input_tokens&#34;</span><span class="p">:</span> <span class="mi">50000</span>
</span></span><span class="line"><span class="cl">      <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">]</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>对于流式响应，上下文编辑包含在最终的 <code>message_delta</code> 事件中：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;message_delta&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;delta&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;stop_reason&#34;</span><span class="p">:</span> <span class="s2">&#34;end_turn&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;stop_sequence&#34;</span><span class="p">:</span> <span class="kc">null</span>
</span></span><span class="line"><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;usage&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;output_tokens&#34;</span><span class="p">:</span> <span class="mi">1024</span>
</span></span><span class="line"><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;context_management&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;applied_edits&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// ...
</span></span></span><span class="line"><span class="cl">    <span class="p">]</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="token-计数">Token 计数</h2>
<p><a href="https://platform.claude.com/docs/en/build-with-claude/token-counting">Token 计数</a> 端点支持上下文管理，让你可以预览在应用上下文编辑后 prompt 将使用多少 token。</p>
<CodeGroup>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">response</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">beta</span><span class="o">.</span><span class="n">messages</span><span class="o">.</span><span class="n">count_tokens</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">model</span><span class="o">=</span><span class="s2">&#34;claude-opus-5&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">messages</span><span class="o">=</span><span class="p">[{</span><span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span> <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;Continue our conversation...&#34;</span><span class="p">}],</span>
</span></span><span class="line"><span class="cl">    <span class="n">betas</span><span class="o">=</span><span class="p">[</span><span class="s2">&#34;context-management-2025-06-27&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">    <span class="n">context_management</span><span class="o">=</span><span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;edits&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">            <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;clear_tool_uses_20250919&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;trigger&#34;</span><span class="p">:</span> <span class="p">{</span><span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;input_tokens&#34;</span><span class="p">,</span> <span class="s2">&#34;value&#34;</span><span class="p">:</span> <span class="mi">30000</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;keep&#34;</span><span class="p">:</span> <span class="p">{</span><span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;tool_uses&#34;</span><span class="p">,</span> <span class="s2">&#34;value&#34;</span><span class="p">:</span> <span class="mi">5</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Original tokens: </span><span class="si">{</span><span class="n">response</span><span class="o">.</span><span class="n">context_management</span><span class="o">.</span><span class="n">original_input_tokens</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;After clearing: </span><span class="si">{</span><span class="n">response</span><span class="o">.</span><span class="n">input_tokens</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="sa">f</span><span class="s2">&#34;Savings: </span><span class="si">{</span><span class="n">response</span><span class="o">.</span><span class="n">context_management</span><span class="o">.</span><span class="n">original_input_tokens</span> <span class="o">-</span> <span class="n">response</span><span class="o">.</span><span class="n">input_tokens</span><span class="si">}</span><span class="s2"> tokens&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span></code></pre></td></tr></table>
</div>
</div></CodeGroup>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;input_tokens&#34;</span><span class="p">:</span> <span class="mi">25000</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;context_management&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;original_input_tokens&#34;</span><span class="p">:</span> <span class="mi">70000</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>响应同时显示应用上下文管理后的最终 token 数（<code>input_tokens</code>）以及清除发生前的原始 token 数（<code>original_input_tokens</code>）。</p>
<h2 id="与-memory-tool-一起使用">与 memory tool 一起使用</h2>
<p>上下文编辑可以与 <a href="https://platform.claude.com/docs/en/agents-and-tools/tool-use/memory-tool">memory tool</a> 结合使用。当对话上下文接近配置的清除阈值时，Claude 会收到自动警告以保留重要信息。这使 Claude 能够在工具结果或上下文从对话历史中被清除之前，将其保存到 memory 文件中。</p>
<p>这种组合让你可以：</p>
<ul>
<li><strong>保留重要上下文：</strong> Claude 可以在工具结果被清除之前，将其中的必要信息写入 memory 文件</li>
<li><strong>维持长时间运行的工作流：</strong> 通过将信息卸载到持久存储，使原本会超出上下文限制的智能体工作流得以进行</li>
<li><strong>按需访问信息：</strong> Claude 可以在需要时从 memory 文件中查找先前已清除的信息，而不必将所有内容保留在活动的上下文窗口中</li>
</ul>
<p>例如，在 Claude 执行大量操作的文件编辑工作流中，随着上下文增长，Claude 可以将已完成的更改摘要写入 memory 文件。当工具结果被清除时，Claude 通过其 memory 系统仍能访问这些信息，并继续有效工作。</p>
<p>要同时使用这两项功能，请在 API 请求中启用它们：</p>
<CodeGroup>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">response</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">beta</span><span class="o">.</span><span class="n">messages</span><span class="o">.</span><span class="n">create</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">model</span><span class="o">=</span><span class="s2">&#34;claude-opus-5&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">max_tokens</span><span class="o">=</span><span class="mi">4096</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">messages</span><span class="o">=</span><span class="p">[{</span><span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span> <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;Hello&#34;</span><span class="p">}],</span>
</span></span><span class="line"><span class="cl">    <span class="n">tools</span><span class="o">=</span><span class="p">[{</span><span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;memory_20250818&#34;</span><span class="p">,</span> <span class="s2">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;memory&#34;</span><span class="p">}],</span>
</span></span><span class="line"><span class="cl">    <span class="n">betas</span><span class="o">=</span><span class="p">[</span><span class="s2">&#34;context-management-2025-06-27&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">    <span class="n">context_management</span><span class="o">=</span><span class="p">{</span><span class="s2">&#34;edits&#34;</span><span class="p">:</span> <span class="p">[{</span><span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;clear_tool_uses_20250919&#34;</span><span class="p">}]},</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span></code></pre></td></tr></table>
</div>
</div></CodeGroup>
<p>有关包括命令和示例在内的完整 memory tool 参考，请参阅 <a href="https://platform.claude.com/docs/en/agents-and-tools/tool-use/memory-tool">Memory tool</a>。</p>
<h2 id="客户端压缩sdk">客户端压缩（SDK）</h2>
<Warning>
  **Anthropic 建议使用服务端压缩，而非 SDK 压缩。** [服务端压缩](https://platform.claude.com/docs/en/build-with-claude/compaction) 能以更低的集成复杂度自动处理上下文管理，提供更好的 token 用量计算，且没有客户端限制。仅当你特别需要在客户端控制摘要过程时，才使用 SDK 压缩。
<p>TypeScript 和 Ruby SDK 中的 <code>compaction_control</code> 参数已弃用，并将在未来版本中移除。启用时 SDK 会发出弃用警告。Python SDK 已在 v1.0 中移除该参数。要在 tool runner 中使用服务端压缩，请在请求的 <code>context_management</code> 参数中传入 <code>compact_20260112</code> edit。
</Warning></p>
<Note>
  压缩在使用 [`tool_runner` 方法](https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-runner) 时，可在 [TypeScript 和 Ruby SDK](https://platform.claude.com/docs/en/cli-sdks-libraries/overview) 中使用。
</Note>
<p>压缩是一项 SDK 功能，当 token 用量变得过大时，通过生成摘要来自动管理对话上下文。与清除内容的服务端上下文编辑策略不同，压缩指示 Claude 对对话历史进行摘要，然后用该摘要替换完整历史。这使 Claude 能够继续处理原本会超出 <a href="https://platform.claude.com/docs/en/build-with-claude/context-windows">上下文窗口</a> 的长时间运行任务。</p>
<h3 id="压缩的工作原理">压缩的工作原理</h3>
<p>启用压缩后，SDK 会在每次模型响应后监控 token 用量：</p>
<ol>
<li><strong>阈值检查：</strong> SDK 将总 token 计算为 <code>input_tokens + cache_creation_input_tokens + cache_read_input_tokens + output_tokens</code>（缓存 token 字段参见 <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching">Prompt Caching</a>）。</li>
<li><strong>摘要生成：</strong> 当超过阈值时，会将摘要 prompt 作为 user 轮次注入，Claude 生成包裹在 <code>&lt;summary&gt;&lt;/summary&gt;</code> 标签中的结构化摘要。</li>
<li><strong>上下文替换：</strong> SDK 提取摘要并用它替换整个消息历史。</li>
<li><strong>继续：</strong> 对话从摘要处恢复，Claude 从中断处继续。</li>
</ol>
<h3 id="使用压缩">使用压缩</h3>
<p>在 <code>tool_runner</code> 调用中添加 <code>compaction_control</code>，以在 token 用量超过阈值时启用自动摘要。</p>
<Tabs>
  <Tab title="cURL">
    <Note>
      压缩在 SDK 的 `tool_runner` 辅助方法中于客户端运行，因此没有直接的 HTTP 等价物。请改用 [服务端压缩](https://platform.claude.com/docs/en/build-with-claude/compaction)，由 Anthropic 的服务器处理压缩。
    </Note>
  </Tab>
  <Tab title="CLI">
    <Note>
      CLI 不包含 `tool_runner` 辅助方法。请改用 [服务端压缩](https://platform.claude.com/docs/en/build-with-claude/compaction)，由 Anthropic 的服务器处理压缩，无需 SDK 侧集成。
    </Note>
  </Tab>
  <Tab title="Python">
    <Note>
      在 v1.0 及更高版本中，Python SDK 的 tool runner 不支持客户端 `compaction_control`。请改用 [服务端压缩](https://platform.claude.com/docs/en/build-with-claude/compaction)：通过在请求的 `context_management` 参数中传入 `compact_20260112` edit，即可与 tool runner 配合使用。
    </Note>
  </Tab>
  <Tab title="TypeScript">
  </Tab>
  <Tab title="C#">
    <Note>
      C# SDK 包含 tool runner，但不支持客户端 `compaction_control`。请改用 [服务端压缩](https://platform.claude.com/docs/en/build-with-claude/compaction)：通过在请求的 `context_management` 参数中传入 `compact_20260112` edit，即可与 tool runner 配合使用。
    </Note>
  </Tab>
  <Tab title="Go">
    <Note>
      Go SDK 包含 tool runner，但不支持客户端 `compaction_control`。请改用 [服务端压缩](https://platform.claude.com/docs/en/build-with-claude/compaction)：通过在请求的 `context_management` 参数中传入 `compact_20260112` edit，即可与 tool runner 配合使用。
    </Note>
  </Tab>
  <Tab title="Java">
    <Note>
      Java SDK 包含 tool runner，但不支持客户端 `compaction_control`。请改用 [服务端压缩](https://platform.claude.com/docs/en/build-with-claude/compaction)：通过在请求的 `context_management` 参数中传入 `compact_20260112` edit，即可与 tool runner 配合使用。
    </Note>
  </Tab>
  <Tab title="PHP">
    <Note>
      PHP SDK 包含 tool runner，但不支持客户端 `compaction_control`。请改用 [服务端压缩](https://platform.claude.com/docs/en/build-with-claude/compaction)：通过在请求的 `context_management` 参数中传入 `compact_20260112` edit，即可与 tool runner 配合使用。
    </Note>
  </Tab>
  <Tab title="Ruby">
  </Tab>
</Tabs>
<h4 id="压缩过程中发生的事情">压缩过程中发生的事情</h4>
<p>随着对话增长，消息历史会不断累积：</p>
<p><strong>压缩前（接近 100k token）：</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">[</span>
</span></span><span class="line"><span class="cl">  <span class="p">{</span> <span class="nt">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span> <span class="nt">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;Analyze all files and write a report...&#34;</span> <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="p">{</span> <span class="nt">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;assistant&#34;</span><span class="p">,</span> <span class="nt">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;I&#39;ll help. Let me start by reading...&#34;</span> <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;content&#34;</span><span class="p">:</span> <span class="p">[{</span> <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;tool_result&#34;</span><span class="p">,</span> <span class="nt">&#34;tool_use_id&#34;</span><span class="p">:</span> <span class="s2">&#34;...&#34;</span><span class="p">,</span> <span class="nt">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;...&#34;</span> <span class="p">}]</span>
</span></span><span class="line"><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="p">{</span> <span class="nt">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;assistant&#34;</span><span class="p">,</span> <span class="nt">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;Based on file1.txt, I see...&#34;</span> <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;content&#34;</span><span class="p">:</span> <span class="p">[{</span> <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;tool_result&#34;</span><span class="p">,</span> <span class="nt">&#34;tool_use_id&#34;</span><span class="p">:</span> <span class="s2">&#34;...&#34;</span><span class="p">,</span> <span class="nt">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;...&#34;</span> <span class="p">}]</span>
</span></span><span class="line"><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="p">{</span> <span class="nt">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;assistant&#34;</span><span class="p">,</span> <span class="nt">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;After analyzing file2.txt...&#34;</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="c1">// ... 50 more exchanges like this ...
</span></span></span><span class="line"><span class="cl"><span class="p">]</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>当 token 超过阈值时，SDK 会注入摘要请求，Claude 生成摘要。然后整个历史被替换：</p>
<p><strong>压缩后（回到约 2–3k token）：</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">[</span>
</span></span><span class="line"><span class="cl">  <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;assistant&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;# Task Overview\nThe user requested analysis of directory files to produce a summary report...\n\n# Current State\nAnalyzed 52 files across 3 subdirectories. Key findings documented in report.md...\n\n# Important Discoveries\n- Configuration files use YAML format\n- Found 3 deprecated dependencies\n- Test coverage at 67%\n\n# Next Steps\n1. Analyze remaining files in /src/legacy\n2. Complete final report sections...\n\n# Context to Preserve\nUser prefers markdown format with executive summary first...&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">]</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>Claude 会从这个摘要继续工作，就像它就是原始对话历史一样。</p>
<h3 id="配置选项">配置选项</h3>
<table>
	<thead>
			<tr>
					<th>参数</th>
					<th>类型</th>
					<th>必填</th>
					<th>默认值</th>
					<th>说明</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>enabled</code></td>
					<td>boolean</td>
					<td>是</td>
					<td>-</td>
					<td>是否启用自动压缩</td>
			</tr>
			<tr>
					<td><code>context_token_threshold</code></td>
					<td>number</td>
					<td>否</td>
					<td>100,000</td>
					<td>触发压缩的 token 数量</td>
			</tr>
			<tr>
					<td><code>model</code></td>
					<td>string</td>
					<td>否</td>
					<td>与主模型相同</td>
					<td>用于生成摘要的模型</td>
			</tr>
			<tr>
					<td><code>summary_prompt</code></td>
					<td>string</td>
					<td>否</td>
					<td>参见 <a href="https://platform.claude.com/docs/en/build-with-claude/context-editing#default-summary-prompt">默认摘要 prompt</a></td>
					<td>用于摘要生成的自定义 prompt</td>
			</tr>
	</tbody>
</table>
<h4 id="选择-token-阈值">选择 token 阈值</h4>
<p>该阈值决定何时进行压缩。阈值越低，压缩越频繁，上下文窗口越小。阈值越高，允许的上下文越多，但有触及限制的风险。</p>
<Tabs>
  <Tab title="cURL">
    <Note>
      压缩在 SDK 的 `tool_runner` 辅助方法中于客户端运行，因此没有直接的 HTTP 等价物。请改用 [服务端压缩](https://platform.claude.com/docs/en/build-with-claude/compaction)，由 Anthropic 的服务器处理压缩。
    </Note>
  </Tab>
  <Tab title="CLI">
    <Note>
      CLI 不包含 `tool_runner` 辅助方法。请改用 [服务端压缩](https://platform.claude.com/docs/en/build-with-claude/compaction)，由 Anthropic 的服务器处理压缩，无需 SDK 侧集成。
    </Note>
  </Tab>
  <Tab title="Python">
    <Note>
      在 v1.0 及更高版本中，Python SDK 的 tool runner 不支持客户端 `compaction_control`。请改用 [服务端压缩](https://platform.claude.com/docs/en/build-with-claude/compaction)：通过在请求的 `context_management` 参数中传入 `compact_20260112` edit，即可与 tool runner 配合使用。
    </Note>
  </Tab>
  <Tab title="TypeScript">
  </Tab>
  <Tab title="C#">
    <Note>
      C# SDK 包含 tool runner，但不支持客户端 `compaction_control`。请改用 [服务端压缩](https://platform.claude.com/docs/en/build-with-claude/compaction)：通过在请求的 `context_management` 参数中传入 `compact_20260112` edit，即可与 tool runner 配合使用。
    </Note>
  </Tab>
  <Tab title="Go">
    <Note>
      Go SDK 包含 tool runner，但不支持客户端 `compaction_control`。请改用 [服务端压缩](https://platform.claude.com/docs/en/build-with-claude/compaction)：通过在请求的 `context_management` 参数中传入 `compact_20260112` edit，即可与 tool runner 配合使用。
    </Note>
  </Tab>
  <Tab title="Java">
    <Note>
      Java SDK 包含 tool runner，但不支持客户端 `compaction_control`。请改用 [服务端压缩](https://platform.claude.com/docs/en/build-with-claude/compaction)：通过在请求的 `context_management` 参数中传入 `compact_20260112` edit，即可与 tool runner 配合使用。
    </Note>
  </Tab>
  <Tab title="PHP">
    <Note>
      PHP SDK 包含 tool runner，但不支持客户端 `compaction_control`。请改用 [服务端压缩](https://platform.claude.com/docs/en/build-with-claude/compaction)：通过在请求的 `context_management` 参数中传入 `compact_20260112` edit，即可与 tool runner 配合使用。
    </Note>
  </Tab>
  <Tab title="Ruby">
  </Tab>
</Tabs>
<h4 id="使用不同的模型生成摘要">使用不同的模型生成摘要</h4>
<p>你可以使用更快或更便宜的模型来生成摘要：</p>
<Tabs>
  <Tab title="cURL">
    <Note>
      压缩在 SDK 的 `tool_runner` 辅助方法中于客户端运行，因此没有直接的 HTTP 等价物。请改用 [服务端压缩](https://platform.claude.com/docs/en/build-with-claude/compaction)，由 Anthropic 的服务器处理压缩。
    </Note>
  </Tab>
  <Tab title="CLI">
    <Note>
      CLI 不包含 `tool_runner` 辅助方法。请改用 [服务端压缩](https://platform.claude.com/docs/en/build-with-claude/compaction)，由 Anthropic 的服务器处理压缩，无需 SDK 侧集成。
    </Note>
  </Tab>
  <Tab title="Python">
    <Note>
      在 v1.0 及更高版本中，Python SDK 的 tool runner 不支持客户端 `compaction_control`。请改用 [服务端压缩](https://platform.claude.com/docs/en/build-with-claude/compaction)：通过在请求的 `context_management` 参数中传入 `compact_20260112` edit，即可与 tool runner 配合使用。
    </Note>
  </Tab>
  <Tab title="TypeScript">
  </Tab>
  <Tab title="C#">
    <Note>
      C# SDK 包含 tool runner，但不支持客户端 `compaction_control`。请改用 [服务端压缩](https://platform.claude.com/docs/en/build-with-claude/compaction)：通过在请求的 `context_management` 参数中传入 `compact_20260112` edit，即可与 tool runner 配合使用。
    </Note>
  </Tab>
  <Tab title="Go">
    <Note>
      Go SDK 包含 tool runner，但不支持客户端 `compaction_control`。请改用 [服务端压缩](https://platform.claude.com/docs/en/build-with-claude/compaction)：通过在请求的 `context_management` 参数中传入 `compact_20260112` edit，即可与 tool runner 配合使用。
    </Note>
  </Tab>
  <Tab title="Java">
    <Note>
      Java SDK 包含 tool runner，但不支持客户端 `compaction_control`。请改用 [服务端压缩](https://platform.claude.com/docs/en/build-with-claude/compaction)：通过在请求的 `context_management` 参数中传入 `compact_20260112` edit，即可与 tool runner 配合使用。
    </Note>
  </Tab>
  <Tab title="PHP">
    <Note>
      PHP SDK 包含 tool runner，但不支持客户端 `compaction_control`。请改用 [服务端压缩](https://platform.claude.com/docs/en/build-with-claude/compaction)：通过在请求的 `context_management` 参数中传入 `compact_20260112` edit，即可与 tool runner 配合使用。
    </Note>
  </Tab>
  <Tab title="Ruby">
  </Tab>
</Tabs>
<h4 id="自定义摘要-prompt">自定义摘要 prompt</h4>
<p>你可以为特定领域需求提供自定义 prompt。你的 prompt 应指示 Claude 将其摘要包裹在 <code>&lt;summary&gt;&lt;/summary&gt;</code> 标签中。</p>
<Tabs>
  <Tab title="cURL">
    <Note>
      压缩在 SDK 的 `tool_runner` 辅助方法中于客户端运行，因此没有直接的 HTTP 等价物。请改用 [服务端压缩](https://platform.claude.com/docs/en/build-with-claude/compaction)，由 Anthropic 的服务器处理压缩。
    </Note>
  </Tab>
  <Tab title="CLI">
    <Note>
      CLI 不包含 `tool_runner` 辅助方法。请改用 [服务端压缩](https://platform.claude.com/docs/en/build-with-claude/compaction)，由 Anthropic 的服务器处理压缩，无需 SDK 侧集成。
    </Note>
  </Tab>
  <Tab title="Python">
    <Note>
      在 v1.0 及更高版本中，Python SDK 的 tool runner 不支持客户端 `compaction_control`。请改用 [服务端压缩](https://platform.claude.com/docs/en/build-with-claude/compaction)：通过在请求的 `context_management` 参数中传入 `compact_20260112` edit，即可与 tool runner 配合使用。
    </Note>
  </Tab>
  <Tab title="TypeScript">
  </Tab>
  <Tab title="C#">
    <Note>
      C# SDK 包含 tool runner，但不支持客户端 `compaction_control`。请改用 [服务端压缩](https://platform.claude.com/docs/en/build-with-claude/compaction)：通过在请求的 `context_management` 参数中传入 `compact_20260112` edit，即可与 tool runner 配合使用。
    </Note>
  </Tab>
  <Tab title="Go">
    <Note>
      Go SDK 包含 tool runner，但不支持客户端 `compaction_control`。请改用 [服务端压缩](https://platform.claude.com/docs/en/build-with-claude/compaction)：通过在请求的 `context_management` 参数中传入 `compact_20260112` edit，即可与 tool runner 配合使用。
    </Note>
  </Tab>
  <Tab title="Java">
    <Note>
      Java SDK 包含 tool runner，但不支持客户端 `compaction_control`。请改用 [服务端压缩](https://platform.claude.com/docs/en/build-with-claude/compaction)：通过在请求的 `context_management` 参数中传入 `compact_20260112` edit，即可与 tool runner 配合使用。
    </Note>
  </Tab>
  <Tab title="PHP">
    <Note>
      PHP SDK 包含 tool runner，但不支持客户端 `compaction_control`。请改用 [服务端压缩](https://platform.claude.com/docs/en/build-with-claude/compaction)：通过在请求的 `context_management` 参数中传入 `compact_20260112` edit，即可与 tool runner 配合使用。
    </Note>
  </Tab>
  <Tab title="Ruby">
  </Tab>
</Tabs>
<h3 id="默认摘要-prompt">默认摘要 prompt</h3>
<p>内置摘要 prompt 指示 Claude 创建结构化的续写摘要，包括：</p>
<ol>
<li><strong>任务概述：</strong> 用户的核心请求、成功标准和约束。</li>
<li><strong>当前状态：</strong> 已完成的内容、已修改的文件以及已生成的产物。</li>
<li><strong>重要发现：</strong> 技术约束、已做出的决策、已解决的错误以及失败的方法。</li>
<li><strong>后续步骤：</strong> 所需的具体操作、阻塞项和优先级顺序。</li>
<li><strong>需保留的上下文：</strong> 用户偏好、领域特定细节以及已做出的承诺。</li>
</ol>
<p>这种结构使 Claude 能够高效恢复工作，而不会丢失重要上下文或重复错误。</p>
<Accordion title="查看完整默认 prompt">
  ```text wrap
  You have been working on the task described above but have not yet completed it. Write a continuation summary that will allow you (or another instance of yourself) to resume work efficiently in a future context window where the conversation history will be replaced with this summary. Your summary should be structured, concise, and actionable. Include:
<ol>
<li>
<p>Task Overview
The user&rsquo;s core request and success criteria
Any clarifications or constraints they specified</p>
</li>
<li>
<p>Current State
What has been completed so far
Files created, modified, or analyzed (with paths if relevant)
Key outputs or artifacts produced</p>
</li>
<li>
<p>Important Discoveries
Technical constraints or requirements uncovered
Decisions made and their rationale
Errors encountered and how they were resolved
What approaches were tried that didn&rsquo;t work (and why)</p>
</li>
<li>
<p>Next Steps
Specific actions needed to complete the task
Any blockers or open questions to resolve
Priority order if multiple steps remain</p>
</li>
<li>
<p>Context to Preserve
User preferences or style requirements
Domain-specific details that aren&rsquo;t obvious
Any promises made to the user</p>
</li>
</ol>
<p>Be concise but complete—err on the side of including information that would prevent duplicate work or repeated mistakes. Write in a way that enables immediate resumption of the task.</p>
<p>Wrap your summary in <summary></summary> tags.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="o">&lt;/</span><span class="n">Accordion</span><span class="o">&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">### 限制</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">#### 服务端工具</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="o">&lt;</span><span class="n">Warning</span><span class="o">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="err">在使用</span> <span class="p">[</span><span class="n">web</span> <span class="n">search</span><span class="p">](</span><span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="n">platform</span><span class="o">.</span><span class="n">claude</span><span class="o">.</span><span class="n">com</span><span class="o">/</span><span class="n">docs</span><span class="o">/</span><span class="n">en</span><span class="o">/</span><span class="n">agents</span><span class="o">-</span><span class="ow">and</span><span class="o">-</span><span class="n">tools</span><span class="o">/</span><span class="k">tool</span><span class="o">-</span><span class="n">use</span><span class="o">/</span><span class="n">web</span><span class="o">-</span><span class="n">search</span><span class="o">-</span><span class="k">tool</span><span class="p">)</span> <span class="err">或</span> <span class="p">[</span><span class="n">web</span> <span class="n">fetch</span><span class="p">](</span><span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="n">platform</span><span class="o">.</span><span class="n">claude</span><span class="o">.</span><span class="n">com</span><span class="o">/</span><span class="n">docs</span><span class="o">/</span><span class="n">en</span><span class="o">/</span><span class="n">agents</span><span class="o">-</span><span class="ow">and</span><span class="o">-</span><span class="n">tools</span><span class="o">/</span><span class="k">tool</span><span class="o">-</span><span class="n">use</span><span class="o">/</span><span class="n">web</span><span class="o">-</span><span class="n">fetch</span><span class="o">-</span><span class="k">tool</span><span class="p">)</span> <span class="err">等服务端工具时，压缩需要特别考虑。</span>
</span></span><span class="line"><span class="cl"><span class="o">&lt;/</span><span class="n">Warning</span><span class="o">&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">使用服务端工具时，</span><span class="n">SDK</span> <span class="err">可能错误计算</span> <span class="n">token</span> <span class="err">用量，导致压缩在错误的时间触发。</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">例如，在</span> <span class="n">web</span> <span class="n">search</span> <span class="err">操作之后，</span><span class="n">API</span> <span class="err">响应可能显示：</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">```</span><span class="n">json</span> <span class="n">Output</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl"><span class="s2">&#34;usage&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="s2">&#34;input_tokens&#34;</span><span class="p">:</span> <span class="mi">63000</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="s2">&#34;cache_creation_input_tokens&#34;</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="s2">&#34;cache_read_input_tokens&#34;</span><span class="p">:</span> <span class="mi">270000</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="s2">&#34;output_tokens&#34;</span><span class="p">:</span> <span class="mi">1400</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>SDK 将总用量计算为 63,000 + 0 + 270,000 + 1,400 = 334,400 token。然而，<code>cache_read_input_tokens</code> 值包含服务端工具进行的多次内部 API 调用的累计读取，而非你的实际对话上下文。你的真实上下文长度可能仅为 63,000 的 <code>input_tokens</code>，但 SDK 看到的是 334k，从而过早触发压缩。</p>
<p><strong>变通方法：</strong></p>
<ul>
<li>使用 <a href="https://platform.claude.com/docs/en/build-with-claude/token-counting">token 计数</a> 端点获取准确的上下文长度</li>
<li>在大量使用服务端工具时避免压缩</li>
</ul>
<h4 id="工具使用边界情况">工具使用边界情况</h4>
<p>当 SDK 在工具使用响应待处理时触发压缩，它会在生成摘要之前从消息历史中移除该 tool use block。如果仍需要，Claude 会在从摘要恢复后重新发出该工具调用。</p>
<h3 id="监控压缩">监控压缩</h3>
<p>了解压缩何时触发有助于你调整阈值并验证预期行为。</p>
<Tabs>
  <Tab title="cURL">
    <Note>
      压缩在 SDK 的 `tool_runner` 辅助方法中于客户端运行，因此没有直接的 HTTP 等价物。请改用 [服务端压缩](https://platform.claude.com/docs/en/build-with-claude/compaction)，由 Anthropic 的服务器处理压缩。
    </Note>
  </Tab>
  <Tab title="CLI">
    <Note>
      CLI 不包含 `tool_runner` 辅助方法。请改用 [服务端压缩](https://platform.claude.com/docs/en/build-with-claude/compaction)，由 Anthropic 的服务器处理压缩，无需 SDK 侧集成。
    </Note>
  </Tab>
  <Tab title="Python">
    <Note>
      在 v1.0 及更高版本中，Python SDK 的 tool runner 不支持 `compaction_control`。请改用 [服务端压缩](https://platform.claude.com/docs/en/build-with-claude/compaction)。
    </Note>
  </Tab>
  <Tab title="TypeScript">
    TypeScript SDK 的 `toolRunner` 支持压缩，但不记录事件。通过观察各轮之间 `runner.params.messages.length` 缩小来检测压缩：
  </Tab>
  <Tab title="C#">
    <Note>
      C# SDK 的 tool runner 不支持 `compaction_control`。请改用 [服务端压缩](https://platform.claude.com/docs/en/build-with-claude/compaction)。
    </Note>
  </Tab>
  <Tab title="Go">
    <Note>
      Go SDK 的 tool runner 不支持 `compaction_control`。请改用 [服务端压缩](https://platform.claude.com/docs/en/build-with-claude/compaction)。
    </Note>
  </Tab>
  <Tab title="Java">
    <Note>
      Java SDK 的 tool runner 不支持 `compaction_control`。请改用 [服务端压缩](https://platform.claude.com/docs/en/build-with-claude/compaction)。
    </Note>
  </Tab>
  <Tab title="PHP">
    <Note>
      PHP SDK 的 tool runner 不支持 `compaction_control`。请改用 [服务端压缩](https://platform.claude.com/docs/en/build-with-claude/compaction)。
    </Note>
  </Tab>
  <Tab title="Ruby">
    Ruby SDK 支持在压缩发生时触发的 `on_compact:` 回调。将其添加到你的 `compaction_control` 配置中：
  </Tab>
</Tabs>
<h3 id="何时使用压缩">何时使用压缩</h3>
<p><strong>适合的用例：</strong></p>
<ul>
<li>处理大量文件或数据源的长时间运行智能体任务</li>
<li>积累大量信息的研究工作流</li>
<li>具有清晰、可衡量进度的多步骤任务</li>
<li>生成在对话之外持久存在的产物（文件、报告）的任务</li>
</ul>
<p><strong>不太理想的用例：</strong></p>
<ul>
<li>需要精确回忆早期对话细节的任务</li>
<li>大量使用服务端工具的工作流</li>
<li>需要在许多变量之间维持精确状态的任务</li>
</ul>
<h2 id="后续步骤">后续步骤</h2>
<CardGroup cols={2}>
  <Card title="压缩" icon="arrows-clockwise" href="https://platform.claude.com/docs/en/build-with-claude/compaction">
    使用服务端压缩管理长对话，这是大多数用例的推荐策略。
  </Card>
  <Card title="Prompt Caching" icon="database" href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching">
    通过缓存 prompt 前缀降低成本和延迟，并了解上下文编辑如何与缓存交互。
  </Card>
</CardGroup>]]></content:encoded>
    </item>
    <item>
      <title>上下文窗口</title>
      <link>https://tuanzi-wow.cn/%E4%B8%8A%E4%B8%8B%E6%96%87%E5%B7%A5%E7%A8%8B/claudecode_context_management_cn/context-windows/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://tuanzi-wow.cn/%E4%B8%8A%E4%B8%8B%E6%96%87%E5%B7%A5%E7%A8%8B/claudecode_context_management_cn/context-windows/</guid>
      <description>了解上下文窗口如何工作、extended thinking 和工具调用如何计入其中，以及如何在对话增长时管理上下文。</description>
      <content:encoded><![CDATA[<p>随着对话增长，你最终会接近上下文窗口限制。对于长时间运行的对话和 agentic 工作流，<a href="https://platform.claude.com/docs/en/build-with-claude/compaction">服务端压缩（server-side compaction）</a> 是上下文管理的主要策略。</p>
<h2 id="上下文窗口如何工作">上下文窗口如何工作</h2>
<p>“上下文窗口”（context window）指语言模型在生成回复时可参考的全部文本，包括回复本身。这不同于语言模型训练所用的大规模语料，而是模型的“工作记忆”。更大的上下文窗口让模型能够处理更复杂、更长的 prompt，但更多上下文并不自动意味着更好。随着 token 数量增长，准确性和召回会下降，这一现象称为 <em>context rot</em>。因此，策选上下文中有什么，与可用空间有多大同样重要。</p>
<Tip>
  关于长上下文为何会退化以及如何围绕它进行工程设计，见 [Effective context engineering](https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents)。
</Tip>
<p>下图说明了 API 请求的标准上下文窗口行为1：</p>
<p><img alt="Diagram of turns accumulating in the context window until the conversation approaches the token limit" loading="lazy" src="https://platform.claude.com/docs/images/context-window.svg"></p>
<p><em>1 诸如 <a href="https://claude.ai/">claude.ai</a> 之类的聊天界面也可以按滚动的“先进先出”方式管理上下文窗口。</em></p>
<ul>
<li>
<p><strong>token 逐步累积：</strong> 随着对话按 turn 推进，每条 user message 和 assistant 回复都会在上下文窗口中累积，且先前的 turn 会被完整保留。</p>
</li>
<li>
<p><strong>上下文窗口容量：</strong> 上下文窗口（<a href="https://platform.claude.com/docs/en/build-with-claude/context-windows#context-window-sizes-by-model">最多 1M tokens，取决于模型</a>）保存对话历史，加上 Claude 新生成的输出。</p>
</li>
<li>
<p><strong>输入-输出流程：</strong> 每个 turn 包括：</p>
<ul>
<li><strong>输入阶段：</strong> 包含全部先前对话历史加上当前 user message</li>
<li><strong>输出阶段：</strong> 生成一段文本回复，该回复会成为下一 turn 输入的一部分</li>
</ul>
</li>
</ul>
<p>请求中的所有内容都计入上下文窗口：system prompt、<code>messages</code> 中的每条消息（包括工具结果、图片和文档），以及你的工具定义。Claude 为本 turn 生成的输出（包括其 extended thinking）也计入。每次响应都会在 <code>usage</code> 字段中报告该请求消耗了什么。如果你使用 <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching">Prompt Caching</a>，输入计数会拆分到 <code>input_tokens</code>、<code>cache_read_input_tokens</code> 和 <code>cache_creation_input_tokens</code>，这三项都计入窗口。要在发送前估算请求，使用 <a href="https://platform.claude.com/docs/en/build-with-claude/token-counting">token counting API</a>。</p>
<h2 id="各模型的上下文窗口大小">各模型的上下文窗口大小</h2>
<p>Claude Fable 5.1、Claude Mythos 5.1、Claude Fable 5、Claude Mythos 5、Claude Opus 5、Claude Opus 4.8、Claude Opus 4.7、Claude Opus 4.6、Claude Sonnet 5、Claude Sonnet 4.6 和 <a href="https://anthropic.com/glasswing">Claude Mythos Preview</a> 具有 1M-token 上下文窗口。对其中任一模型的单次请求最多可生成 128k 输出 tokens（<code>max_tokens</code>）。其他 Claude 模型，包括 Claude Sonnet 4.5，具有 200k-token 上下文窗口。</p>
<p>对每个具有 1M-token 上下文窗口的模型，1M 是默认值：你不需要 beta header，长上下文请求按 <a href="https://platform.claude.com/docs/en/about-claude/pricing#long-context-pricing">标准定价</a> 计费。</p>
<p>单次请求最多可包含 600 张图片或 PDF 页（对具有 200k-token 上下文窗口的模型为 100）。如果你发送大量图片或大型文档，可能会在达到 token 限制之前先达到 <a href="https://platform.claude.com/docs/en/api/overview#request-size-limits">请求大小限制</a>。</p>
<p>各模型上下文窗口大小列表见 <a href="https://platform.claude.com/docs/en/models/overview#latest-models-comparison">模型对比</a> 表。</p>
<h2 id="带-thinking-的上下文窗口">带 thinking 的上下文窗口</h2>
<p>使用 <a href="https://platform.claude.com/docs/en/build-with-claude/thinking">thinking</a> 时，所有输入和输出 tokens（包括 thinking tokens）都计入上下文窗口限制，在多 turn 情况下有一些细微差别。</p>
<p>thinking tokens 是你的 <code>max_tokens</code> 参数的子集，按输出 tokens 计费，并计入速率限制。使用 <a href="https://platform.claude.com/docs/en/build-with-claude/thinking">adaptive thinking</a> 时，Claude 会动态决定其 thinking 分配，因此 thinking token 用量会因请求而异。</p>
<p>先前 assistant turn 中的 thinking blocks 是否留在上下文窗口中取决于模型。在 Claude Opus 4.5 及之后的 Opus 模型、Claude Sonnet 4.6 及之后的 Sonnet 模型、Claude Fable 5.1、Claude Mythos 5.1、Claude Fable 5、Claude Mythos 5 和 Claude Mythos Preview 上，API 默认保留先前的 thinking blocks，它们像其他输入 tokens 一样计入上下文窗口。在更早的 Opus 和 Sonnet 模型以及所有 Haiku 模型上，当你把先前的 thinking blocks 传回时，API 会自动从对话历史中剥离它们，从而为对话内容保留 token 容量。各模型默认值见 <a href="https://platform.claude.com/docs/en/build-with-claude/thinking#thinking-block-preservation-by-model">thinking block 按模型的保留策略</a>。要向任一方向覆盖默认值，使用 <a href="https://platform.claude.com/docs/en/build-with-claude/context-editing#thinking-block-clearing">thinking block 清除</a>。</p>
<p>下图展示了在会剥离先前 thinking blocks 的模型上启用 thinking 时如何管理 tokens：</p>
<p><img alt="Diagram of thinking on a model that strips previous thinking blocks: each turn&rsquo;s thinking block is generated in the output and not carried into later turns&rsquo; input" loading="lazy" src="https://platform.claude.com/docs/images/context-window-thinking.svg"></p>
<ul>
<li><strong>剥离 thinking blocks：</strong> 在会剥离先前 thinking blocks 的模型上，thinking blocks（深灰色所示）在每个 turn 的输出阶段生成，但不会作为后续 turn 的输入 tokens 向前携带。你不需要自己剥离 thinking blocks：如果你把它们传回，Claude API 会自动剥离。</li>
<li><strong>计费：</strong> thinking tokens 在生成时作为输出 tokens 计费一次。在会保留先前 thinking blocks 的模型上，被保留的 blocks 随后会成为后续请求输入的一部分，并像对话历史的其余部分一样作为输入 tokens 计费。</li>
</ul>
<Note>
  你可以在 [Thinking](https://platform.claude.com/docs/en/build-with-claude/thinking) 指南中阅读更多关于上下文窗口与 thinking 的内容。
</Note>
<h2 id="带-thinking-和工具调用的上下文窗口">带 thinking 和工具调用的上下文窗口</h2>
<p>下图说明了在会剥离先前 thinking blocks 的模型上，将 thinking 与工具调用结合时如何管理 tokens：</p>
<p><img alt="Diagram of thinking with tool use: thinking is kept with its tool result, then dropped on the next user turn on models that strip previous thinking blocks" loading="lazy" src="https://platform.claude.com/docs/images/context-window-thinking-tools.svg"></p>
<Steps>
  <Step title="第一 turn 的结构">
    * **输入组成部分：** 工具配置和 user message
    * **输出组成部分：** Thinking + 文本回复 + 工具调用请求
    * **token 计算：** 所有输入和输出组成部分都计入上下文窗口，所有输出组成部分都作为输出 tokens 计费。
  </Step>
  <Step title="工具结果处理（turn 2）">
    * **输入组成部分：** 第一 turn 中的每个 block 以及 `tool_result`。你必须把 thinking block 与对应的工具结果一起返回。这是你必须返回 thinking blocks 的唯一情况。
    * **输出组成部分：** 工具结果传回 Claude 之后，Claude 只以文本回复（在下一条 `user` message 之前不会有额外的 thinking，除非启用了 [interleaved thinking](https://platform.claude.com/docs/en/build-with-claude/thinking#interleaved-thinking)）。
    * **token 计算：** 所有输入和输出组成部分都计入上下文窗口，所有输出组成部分都作为输出 tokens 计费。
  </Step>
  <Step title="新的 user turn（turn 3）">
    * **输入组成部分：** 上一 turn 的所有输入和输出都会向前携带。已完成的工具调用周期中的 thinking block 不再必须留在上下文中：在会剥离先前 thinking blocks 的模型上，当你把它传回时 API 会自动丢弃它；在会保留先前 thinking blocks 的模型上，它会保留，除非你用 [thinking block 清除](https://platform.claude.com/docs/en/build-with-claude/context-editing#thinking-block-clearing) 将其清除。这也是你加入下一个 `user` turn 的位置。
    * **输出组成部分：** 因为在工具调用周期之外有一个新的 `user` turn，Claude 会生成一个新的 thinking block 并从那里继续。
    * **token 计算：** 在会剥离先前 thinking blocks 的模型上，先前的 thinking tokens 不再计入上下文窗口。所有其他先前的 blocks 仍计入上下文窗口，当前 `assistant` turn 中的 thinking block 也计入。
  </Step>
</Steps>
<ul>
<li>
<p><strong>将 thinking 与工具调用一起使用时的注意事项：</strong></p>
<ul>
<li>当你提交工具结果时，必须包含伴随该工具请求的整个未经修改的 thinking block，包括其 signature。</li>
<li>API 使用加密签名来验证 thinking block 的真实性。如果你修改了 thinking block，API 会返回错误。</li>
</ul>
</li>
</ul>
<Note>
  大多数当前 Claude 模型支持 [interleaved thinking](https://platform.claude.com/docs/en/build-with-claude/thinking#interleaved-thinking)，它让 Claude 可以在工具调用之间思考，包括在收到工具结果之后。在具有 adaptive thinking 的模型上它是自动的；Claude Opus 4.5、Claude Sonnet 4.5 以及更早的 Claude 4 模型需要 `interleaved-thinking-2025-05-14` beta header，Claude Haiku 4.5 不支持它。
<p>关于将工具与 thinking 一起使用的更多信息，见 <a href="https://platform.claude.com/docs/en/build-with-claude/thinking#thinking-with-tool-use">Thinking with tool use</a>。
</Note></p>
<p>要减少工具定义本身消耗的上下文，见 <a href="https://platform.claude.com/docs/en/agents-and-tools/tool-use/manage-tool-context">Manage tool context</a>，或用 <a href="https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-search-tool">tool search tool</a> 延迟加载工具定义。</p>
<h2 id="上下文感知">上下文感知</h2>
<p>Claude Sonnet 5、Claude Sonnet 4.6、Claude Sonnet 4.5 和 Claude Haiku 4.5 具有<strong>上下文感知（context awareness）</strong>：这些模型会在整个对话中跟踪其剩余上下文窗口（它们的“token budget”）。这让模型可以对照剩余空间来管理长时间运行的任务，而不是猜测还剩多少 tokens。上下文感知是自动的：你无需启用任何东西，也永远不要自己发送本节所示的标签。API 会注入它们。</p>
<h3 id="工作原理">工作原理</h3>
<p>在每个请求的 system prompt 中，API 会告诉 Claude 其总上下文窗口：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-xml" data-lang="xml"><span class="line"><span class="cl"><span class="nt">&lt;budget:token_budget&gt;</span>200000<span class="nt">&lt;/budget:token_budget&gt;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>该预算与你的请求可用的上下文窗口匹配：Claude Sonnet 5 和 Claude Sonnet 4.6 为 1M tokens，Claude Sonnet 4.5 和 Claude Haiku 4.5 为 200k tokens。本节示例展示的是具有 200k-token 上下文窗口的模型。</p>
<p>每次工具调用之后，API 会向 Claude 提供剩余容量的更新：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-xml" data-lang="xml"><span class="line"><span class="cl"><span class="nt">&lt;system_warning&gt;</span>Token usage: 35000/200000; 165000 remaining<span class="nt">&lt;/system_warning&gt;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>图片 tokens 包含在这些预算中。</p>
<p>Claude Opus 4.7 及之后的 Opus 模型、Claude Fable 5.1、Claude Mythos 5.1、Claude Fable 5 和 Claude Mythos 5 不会收到这些注入的标签。在这些模型上，你可以用 <a href="https://platform.claude.com/docs/en/build-with-claude/task-budgets">task budgets</a> 给模型一个显式预算，该功能处于 beta。</p>
<Tip>
  对于跨越多个会话的 agents，设计你的状态制品，使得新会话开始时上下文恢复很快。[memory tool 的多会话模式](https://platform.claude.com/docs/en/agents-and-tools/tool-use/memory-tool#multisession-software-development-pattern) 给出了一种具体做法。另见 [Effective harnesses for long-running agents](https://www.anthropic.com/engineering/effective-harnesses-for-long-running-agents)。
</Tip>
<p>关于使用上下文感知的 prompting 指导，见 <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/claude-prompting-best-practices#context-awareness-and-multiwindow-workflows">Prompting best practices</a>。</p>
<h2 id="用压缩管理上下文">用压缩管理上下文</h2>
<p>如果你的对话经常接近上下文窗口限制，使用 <a href="https://platform.claude.com/docs/en/build-with-claude/compaction">服务端压缩</a>。压缩会在服务端自动摘要对话的较早部分，使对话可以越过上下文窗口限制继续。它对 Claude 4.6 及之后的模型和 <a href="https://anthropic.com/glasswing">Claude Mythos Preview</a> 以 beta 提供。</p>
<p>对于更专门的需求，<a href="https://platform.claude.com/docs/en/build-with-claude/context-editing">上下文编辑（context editing）</a> 提供额外策略：</p>
<ul>
<li><strong>工具结果清除：</strong> 在 agentic 工作流中清除旧的工具结果</li>
<li><strong>thinking block 清除：</strong> 在使用 extended thinking 时管理 thinking blocks</li>
</ul>
<p>已缓存的 prompt 前缀仍然占用上下文窗口：<a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching">Prompt Caching</a> 改变的是你为这些 tokens 支付的费用，而不是它们是否计入。</p>
<h2 id="上下文窗口溢出行为">上下文窗口溢出行为</h2>
<p>如果仅输入就已经超过模型的上下文窗口，API 在每个模型上都会返回 400 <code>invalid_request_error</code>（&ldquo;prompt is too long&rdquo;）。</p>
<p>在 Claude 4.5 模型及更新模型上，如果输入 tokens 加上 <code>max_tokens</code> 超过上下文窗口大小，API 会接受该请求。如果随后生成到达上下文窗口限制，它会以 <code>stop_reason: &quot;model_context_window_exceeded&quot;</code> 停止。在更早的模型上，API 会改为返回 <a href="https://platform.claude.com/docs/en/api/errors">校验错误</a>。要在那些模型上选择启用 <code>model_context_window_exceeded</code> 行为，使用 <code>model-context-window-exceeded-2025-08-26</code> beta header。细节见 <a href="https://platform.claude.com/docs/en/build-with-claude/handling-stop-reasons">Stop reasons and fallback</a>。</p>
<p>要保持在上下文窗口限制之内，在向 Claude 发送消息之前使用 <a href="https://platform.claude.com/docs/en/build-with-claude/token-counting">token counting API</a> 估算 token 用量。</p>
<h2 id="后续步骤">后续步骤</h2>
<CardGroup cols={2}>
  <Card title="压缩" icon="stack" href="https://platform.claude.com/docs/en/build-with-claude/compaction">
    用于管理接近上下文窗口限制的长对话的服务端上下文压缩。
  </Card>
  <Card title="上下文编辑" icon="edit" href="https://platform.claude.com/docs/en/build-with-claude/context-editing">
    随着对话增长，用上下文编辑自动管理对话上下文。
  </Card>
  <Card title="模型对比表" icon="scales" href="https://platform.claude.com/docs/en/models/overview#latest-models-comparison">
    查看模型对比表，了解各模型的上下文窗口大小以及输入/输出 token 定价。
  </Card>
  <Card title="Thinking" icon="settings" href="https://platform.claude.com/docs/en/build-with-claude/thinking">
    为复杂任务为 Claude 提供增强推理，并控制 thinking 内容如何返回。
  </Card>
</CardGroup>
]]></content:encoded>
    </item>
    <item>
      <title>压缩（compaction）</title>
      <link>https://tuanzi-wow.cn/%E4%B8%8A%E4%B8%8B%E6%96%87%E5%B7%A5%E7%A8%8B/claudecode_context_management_cn/compaction/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://tuanzi-wow.cn/%E4%B8%8A%E4%B8%8B%E6%96%87%E5%B7%A5%E7%A8%8B/claudecode_context_management_cn/compaction/</guid>
      <description>服务端上下文压缩，用于管理接近上下文窗口上限的长对话。</description>
      <content:encoded><![CDATA[<h2 id="兼容性">兼容性</h2>
<ul>
<li>状态: Beta</li>
<li><a href="https://platform.claude.com/docs/en/api/beta-headers">Beta header</a>: <code>compact-2026-01-12</code></li>
<li><a href="https://platform.claude.com/docs/en/manage-claude/api-and-data-retention">ZDR</a>: 符合条件（不含 <a href="https://platform.claude.com/docs/en/manage-claude/api-and-data-retention#model-specific-data-retention-requirements">Covered Models</a>）</li>
<li>支持的模型: <code>claude-fable-5-1</code>, <code>claude-mythos-5-1</code>, <code>claude-fable-5</code>, <code>claude-mythos-5</code>, <code>claude-mythos-preview</code>, <code>claude-opus-5</code>, <code>claude-opus-4-8</code>, <code>claude-opus-4-7</code>, <code>claude-opus-4-6</code>, <code>claude-sonnet-5</code>, <code>claude-sonnet-4-6</code></li>
<li>平台: Claude API (beta), Claude Platform on AWS (beta), Amazon Bedrock (beta), Google Cloud (beta), Microsoft Foundry (beta)</li>
</ul>
<Tip>
  服务端压缩是管理长时间运行对话和 agentic 工作流中上下文的推荐策略。它会自动处理上下文管理，无需客户端摘要代码。
</Tip>
<p>压缩通过在接近上下文窗口上限时自动摘要较旧的上下文，来延长长时间运行对话和任务的有效上下文长度。它也会保持活动上下文较小：随着对话增长，回复质量会下降，因此压缩会用简洁摘要替换较旧内容。</p>
<Tip>
  关于长上下文为何会退化以及压缩如何提供帮助的更深入讨论，见 [Effective context engineering](https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents)。
</Tip>
<p>适用于：</p>
<ul>
<li>基于聊天的多轮对话，希望用户长时间使用同一会话</li>
<li>需要大量后续工作（通常是工具调用）且可能超出上下文窗口的面向任务的 prompt</li>
</ul>
<h2 id="压缩如何工作">压缩如何工作</h2>
<p>启用压缩后，当对话达到所配置的 token 阈值时，Claude 会自动对对话进行摘要。API 会：</p>
<ol>
<li>检测输入 tokens 何时达到你指定的触发阈值。</li>
<li>生成当前对话的摘要。</li>
<li>创建包含该摘要的 <code>compaction</code> block。</li>
<li>使用压缩后的上下文继续回复。</li>
</ol>
<p>在后续请求中，将响应追加到你的 messages。API 会自动丢弃 <code>compaction</code> block 之前的所有 content block，并从摘要处继续对话。</p>
<p><img alt="压缩流程：当输入 tokens 达到触发条件时，Claude 将摘要写入 <code>compaction</code> block 并继续" loading="lazy" src="https://platform.claude.com/docs/images/compaction-flow.svg"></p>
<h2 id="基本用法">基本用法</h2>
<p>通过在 Messages API 请求的 <code>context_management.edits</code> 中添加 <code>compact_20260112</code> 策略来启用压缩。</p>
<CodeGroup>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">client</span> <span class="o">=</span> <span class="n">anthropic</span><span class="o">.</span><span class="n">Anthropic</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">messages</span> <span class="o">=</span> <span class="p">[{</span><span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span> <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;Help me build a website&#34;</span><span class="p">}]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">response</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">beta</span><span class="o">.</span><span class="n">messages</span><span class="o">.</span><span class="n">create</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">betas</span><span class="o">=</span><span class="p">[</span><span class="s2">&#34;compact-2026-01-12&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">    <span class="n">model</span><span class="o">=</span><span class="s2">&#34;claude-opus-5&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">max_tokens</span><span class="o">=</span><span class="mi">4096</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">messages</span><span class="o">=</span><span class="n">messages</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">context_management</span><span class="o">=</span><span class="p">{</span><span class="s2">&#34;edits&#34;</span><span class="p">:</span> <span class="p">[{</span><span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;compact_20260112&#34;</span><span class="p">}]},</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Append the response (including any compaction block) to continue the conversation</span>
</span></span><span class="line"><span class="cl"><span class="n">messages</span><span class="o">.</span><span class="n">append</span><span class="p">({</span><span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;assistant&#34;</span><span class="p">,</span> <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="n">response</span><span class="o">.</span><span class="n">content</span><span class="p">})</span>
</span></span></code></pre></td></tr></table>
</div>
</div></CodeGroup>
<h2 id="参数">参数</h2>
<table>
	<thead>
			<tr>
					<th>参数</th>
					<th>类型</th>
					<th>默认值</th>
					<th>说明</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>type</code></td>
					<td>string</td>
					<td>Required</td>
					<td>必须为 <code>&quot;compact_20260112&quot;</code></td>
			</tr>
			<tr>
					<td><code>trigger</code></td>
					<td>object</td>
					<td><code>{&quot;type&quot;: &quot;input_tokens&quot;, &quot;value&quot;: 150000}</code></td>
					<td>何时触发压缩。<code>input_tokens</code> 是唯一支持的触发类型。<code>value</code> 必须至少为 50,000 tokens。</td>
			</tr>
			<tr>
					<td><code>pause_after_compaction</code></td>
					<td>boolean</td>
					<td><code>false</code></td>
					<td>生成压缩摘要后是否暂停</td>
			</tr>
			<tr>
					<td><code>instructions</code></td>
					<td>string</td>
					<td><code>null</code></td>
					<td>自定义摘要 prompt。提供后会完全替换默认 prompt。</td>
			</tr>
	</tbody>
</table>
<h3 id="触发配置">触发配置</h3>
<p>使用 <code>trigger</code> 参数配置何时触发压缩：</p>
<CodeGroup>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">client</span> <span class="o">=</span> <span class="n">anthropic</span><span class="o">.</span><span class="n">Anthropic</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">messages</span> <span class="o">=</span> <span class="p">[{</span><span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span> <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;Hello, Claude&#34;</span><span class="p">}]</span>
</span></span><span class="line"><span class="cl"><span class="n">response</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">beta</span><span class="o">.</span><span class="n">messages</span><span class="o">.</span><span class="n">create</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">betas</span><span class="o">=</span><span class="p">[</span><span class="s2">&#34;compact-2026-01-12&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">    <span class="n">model</span><span class="o">=</span><span class="s2">&#34;claude-opus-5&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">max_tokens</span><span class="o">=</span><span class="mi">4096</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">messages</span><span class="o">=</span><span class="n">messages</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">context_management</span><span class="o">=</span><span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;edits&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">            <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;compact_20260112&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;trigger&#34;</span><span class="p">:</span> <span class="p">{</span><span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;input_tokens&#34;</span><span class="p">,</span> <span class="s2">&#34;value&#34;</span><span class="p">:</span> <span class="mi">150000</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span></code></pre></td></tr></table>
</div>
</div></CodeGroup>
<h3 id="自定义摘要指令">自定义摘要指令</h3>
<p>默认摘要 prompt 因模型而异。各默认 prompt 都指示 Claude 在 <code>&lt;summary&gt;&lt;/summary&gt;</code> 标签内撰写摘要，并包含在未来上下文窗口中继续任务所需的信息。例如，部分模型使用以下 prompt：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">You have written a partial transcript for the initial task above. Please write a summary of the transcript. The purpose of this summary is to provide continuity so you can continue to make progress towards solving the task in a future context, where the raw history above may not be accessible and will be replaced with this summary. Write down anything that would be helpful, including the state, next steps, learnings etc. You must wrap your summary in a &lt;summary&gt;&lt;/summary&gt; block.
</span></span></code></pre></td></tr></table>
</div>
</div><p>可通过 <code>instructions</code> 参数提供自定义指令。自定义指令不会补充默认 prompt，而是完全替换它：</p>
<CodeGroup>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">client</span> <span class="o">=</span> <span class="n">anthropic</span><span class="o">.</span><span class="n">Anthropic</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">messages</span> <span class="o">=</span> <span class="p">[{</span><span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span> <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;Hello, Claude&#34;</span><span class="p">}]</span>
</span></span><span class="line"><span class="cl"><span class="n">response</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">beta</span><span class="o">.</span><span class="n">messages</span><span class="o">.</span><span class="n">create</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">betas</span><span class="o">=</span><span class="p">[</span><span class="s2">&#34;compact-2026-01-12&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">    <span class="n">model</span><span class="o">=</span><span class="s2">&#34;claude-opus-5&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">max_tokens</span><span class="o">=</span><span class="mi">4096</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">messages</span><span class="o">=</span><span class="n">messages</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">context_management</span><span class="o">=</span><span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;edits&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">            <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;compact_20260112&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;instructions&#34;</span><span class="p">:</span> <span class="s2">&#34;Focus on preserving code snippets, variable names, and technical decisions.&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span></code></pre></td></tr></table>
</div>
</div></CodeGroup>
<p>在 Claude Fable 5.1 和 Claude Mythos 5.1 上，带自定义 <code>instructions</code> 的请求仅从可见对话进行摘要：更早的 thinking block 不在摘要器的输入中。</p>
<h3 id="压缩后暂停">压缩后暂停</h3>
<p>使用 <code>pause_after_compaction</code> 在生成压缩摘要后暂停 API。这使你可以在 API 继续生成回复之前添加额外的 content block（例如保留最近的消息或特定的指令导向消息）。</p>
<p>启用后，API 在生成 <code>compaction</code> block 后会返回带 <code>compaction</code> stop reason 的消息：</p>
<CodeGroup>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">client</span> <span class="o">=</span> <span class="n">anthropic</span><span class="o">.</span><span class="n">Anthropic</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">messages</span> <span class="o">=</span> <span class="p">[{</span><span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span> <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;Hello, Claude&#34;</span><span class="p">}]</span>
</span></span><span class="line"><span class="cl"><span class="n">response</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">beta</span><span class="o">.</span><span class="n">messages</span><span class="o">.</span><span class="n">create</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">betas</span><span class="o">=</span><span class="p">[</span><span class="s2">&#34;compact-2026-01-12&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">    <span class="n">model</span><span class="o">=</span><span class="s2">&#34;claude-opus-5&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">max_tokens</span><span class="o">=</span><span class="mi">4096</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">messages</span><span class="o">=</span><span class="n">messages</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">context_management</span><span class="o">=</span><span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;edits&#34;</span><span class="p">:</span> <span class="p">[{</span><span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;compact_20260112&#34;</span><span class="p">,</span> <span class="s2">&#34;pause_after_compaction&#34;</span><span class="p">:</span> <span class="kc">True</span><span class="p">}]</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Check if compaction triggered a pause</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="n">response</span><span class="o">.</span><span class="n">stop_reason</span> <span class="o">==</span> <span class="s2">&#34;compaction&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># Response contains only the compaction block</span>
</span></span><span class="line"><span class="cl">    <span class="n">messages</span><span class="o">.</span><span class="n">append</span><span class="p">({</span><span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;assistant&#34;</span><span class="p">,</span> <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="n">response</span><span class="o">.</span><span class="n">content</span><span class="p">})</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># Continue the request</span>
</span></span><span class="line"><span class="cl">    <span class="n">response</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">beta</span><span class="o">.</span><span class="n">messages</span><span class="o">.</span><span class="n">create</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="n">betas</span><span class="o">=</span><span class="p">[</span><span class="s2">&#34;compact-2026-01-12&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">        <span class="n">model</span><span class="o">=</span><span class="s2">&#34;claude-opus-5&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="n">max_tokens</span><span class="o">=</span><span class="mi">4096</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="n">messages</span><span class="o">=</span><span class="n">messages</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="n">context_management</span><span class="o">=</span><span class="p">{</span><span class="s2">&#34;edits&#34;</span><span class="p">:</span> <span class="p">[{</span><span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;compact_20260112&#34;</span><span class="p">}]},</span>
</span></span><span class="line"><span class="cl">    <span class="p">)</span>
</span></span></code></pre></td></tr></table>
</div>
</div></CodeGroup>
<h4 id="强制执行总-token-预算">强制执行总 token 预算</h4>
<p>当模型处理带有多次工具调用迭代的长任务时，总 token 消耗可能显著增长。你可以将 <code>pause_after_compaction</code> 与压缩计数器结合，以估算累计用量，并在达到预算后优雅地收尾任务。</p>
<p>此示例仅出现在 SDK 语言中：其价值在于请求周围的预算跟踪逻辑。原始请求将 <a href="https://platform.claude.com/docs/en/build-with-claude/compaction#trigger-configuration">触发配置</a> 中的 <code>trigger</code> 与 <a href="https://platform.claude.com/docs/en/build-with-claude/compaction#pausing-after-compaction">压缩后暂停</a> 中的 <code>pause_after_compaction</code> 结合。</p>
<CodeGroup exclude="shell">
  ```python Python
  client = anthropic.Anthropic()
  messages = [{"role": "user", "content": "Hello, Claude"}]
  TRIGGER_THRESHOLD = 100_000
  TOTAL_TOKEN_BUDGET = 3_000_000
  n_compactions = 0
<p>response = client.beta.messages.create(
betas=[&ldquo;compact-2026-01-12&rdquo;],
model=&ldquo;claude-opus-5&rdquo;,
max_tokens=4096,
messages=messages,
context_management={
&ldquo;edits&rdquo;: [
{
&ldquo;type&rdquo;: &ldquo;compact_20260112&rdquo;,
&ldquo;trigger&rdquo;: {&ldquo;type&rdquo;: &ldquo;input_tokens&rdquo;, &ldquo;value&rdquo;: TRIGGER_THRESHOLD},
&ldquo;pause_after_compaction&rdquo;: True,
}
]
},
)</p>
<p>if response.stop_reason == &ldquo;compaction&rdquo;:
n_compactions += 1
messages.append({&ldquo;role&rdquo;: &ldquo;assistant&rdquo;, &ldquo;content&rdquo;: response.content})</p>
<pre><code>  # Estimate total tokens consumed; prompt wrap-up if over budget
  if n_compactions * TRIGGER_THRESHOLD &gt;= TOTAL_TOKEN_BUDGET:
      messages.append(
          {
              &quot;role&quot;: &quot;user&quot;,
              &quot;content&quot;: &quot;Please wrap up your current work and summarize the final state.&quot;,
          }
      )
</code></pre>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-mysql" data-lang="mysql"><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="o">&lt;/</span><span class="n">CodeGroup</span><span class="o">&gt;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="c1">## 处理 `compaction` block
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="err">触发压缩时，</span><span class="n">API</span><span class="w"> </span><span class="err">会在</span><span class="w"> </span><span class="n">assistant</span><span class="w"> </span><span class="err">回复的开头返回一个</span><span class="w"> </span><span class="o">`</span><span class="n">compaction</span><span class="o">`</span><span class="w"> </span><span class="n">block</span><span class="err">。</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="err">长时间运行的对话可能发生多次压缩。最后一个</span><span class="w"> </span><span class="o">`</span><span class="n">compaction</span><span class="o">`</span><span class="w"> </span><span class="n">block</span><span class="w"> </span><span class="err">反映</span><span class="w"> </span><span class="n">prompt</span><span class="w"> </span><span class="err">的最终状态，用生成的摘要替换其之前的内容。</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="o">```</span><span class="n">json</span><span class="w"> </span><span class="n">Output</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="err">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="s2">&#34;content&#34;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="err">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="s2">&#34;type&#34;</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;compaction&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="s2">&#34;content&#34;</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Summary of the conversation: The user requested help building a web scraper...&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="err">}</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="err">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="s2">&#34;type&#34;</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;text&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="s2">&#34;text&#34;</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Based on our conversation so far...&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="err">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="err">}</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><h3 id="回传-compaction-block">回传 <code>compaction</code> block</h3>
<p>你必须在后续请求中将 <code>compaction</code> block 传回 API，才能以缩短后的 prompt 继续对话。最简单的做法是将整个响应 content 追加到你的 messages：</p>
<CodeGroup>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">client</span> <span class="o">=</span> <span class="n">anthropic</span><span class="o">.</span><span class="n">Anthropic</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">messages</span> <span class="o">=</span> <span class="p">[{</span><span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span> <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;Hello, Claude&#34;</span><span class="p">}]</span>
</span></span><span class="line"><span class="cl"><span class="n">response</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">beta</span><span class="o">.</span><span class="n">messages</span><span class="o">.</span><span class="n">create</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">betas</span><span class="o">=</span><span class="p">[</span><span class="s2">&#34;compact-2026-01-12&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">    <span class="n">model</span><span class="o">=</span><span class="s2">&#34;claude-opus-5&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">max_tokens</span><span class="o">=</span><span class="mi">4096</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">messages</span><span class="o">=</span><span class="n">messages</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">context_management</span><span class="o">=</span><span class="p">{</span><span class="s2">&#34;edits&#34;</span><span class="p">:</span> <span class="p">[{</span><span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;compact_20260112&#34;</span><span class="p">}]},</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="c1"># After receiving a response with a compaction block</span>
</span></span><span class="line"><span class="cl"><span class="n">messages</span><span class="o">.</span><span class="n">append</span><span class="p">({</span><span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;assistant&#34;</span><span class="p">,</span> <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="n">response</span><span class="o">.</span><span class="n">content</span><span class="p">})</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Continue the conversation</span>
</span></span><span class="line"><span class="cl"><span class="n">messages</span><span class="o">.</span><span class="n">append</span><span class="p">({</span><span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span> <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;Now add error handling&#34;</span><span class="p">})</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">response</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">beta</span><span class="o">.</span><span class="n">messages</span><span class="o">.</span><span class="n">create</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">betas</span><span class="o">=</span><span class="p">[</span><span class="s2">&#34;compact-2026-01-12&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">    <span class="n">model</span><span class="o">=</span><span class="s2">&#34;claude-opus-5&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">max_tokens</span><span class="o">=</span><span class="mi">4096</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">messages</span><span class="o">=</span><span class="n">messages</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">context_management</span><span class="o">=</span><span class="p">{</span><span class="s2">&#34;edits&#34;</span><span class="p">:</span> <span class="p">[{</span><span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;compact_20260112&#34;</span><span class="p">}]},</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span></code></pre></td></tr></table>
</div>
</div></CodeGroup>
<p>当 API 收到 <code>compaction</code> block 时，其之前的所有 content block 都会被忽略。你可以：</p>
<ul>
<li>在列表中保留原始 messages，让 API 处理移除已压缩的内容</li>
<li>手动丢弃已压缩的消息，只保留从 <code>compaction</code> block 起的内容</li>
</ul>
<p>在 Claude Fable 5.1 和 Claude Mythos 5.1 上，<code>compaction</code> block 之前的 thinking block 不会被带入后续上下文，因此摘要是模型对那部分早期工作的全部依据。如果你编写自己的 <code>instructions</code>，需告知模型摘要必须保留什么；见 <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-1#tell-the-model-what-to-preserve-in-compaction-summaries">Tell the model what to preserve in compaction summaries</a>。</p>
<h3 id="流式输出">流式输出</h3>
<p><code>compaction</code> block 的流式传输方式与 text block 不同。你会收到一个 <code>content_block_start</code> 事件，随后是一条包含完整摘要内容的 <code>content_block_delta</code>（无中间流式片段），然后是 <code>content_block_stop</code> 事件。</p>
<CodeGroup>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">client</span> <span class="o">=</span> <span class="n">anthropic</span><span class="o">.</span><span class="n">Anthropic</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">messages</span> <span class="o">=</span> <span class="p">[{</span><span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span> <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;Hello, Claude&#34;</span><span class="p">}]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">with</span> <span class="n">client</span><span class="o">.</span><span class="n">beta</span><span class="o">.</span><span class="n">messages</span><span class="o">.</span><span class="n">stream</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">betas</span><span class="o">=</span><span class="p">[</span><span class="s2">&#34;compact-2026-01-12&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">    <span class="n">model</span><span class="o">=</span><span class="s2">&#34;claude-opus-5&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">max_tokens</span><span class="o">=</span><span class="mi">4096</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">messages</span><span class="o">=</span><span class="n">messages</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">context_management</span><span class="o">=</span><span class="p">{</span><span class="s2">&#34;edits&#34;</span><span class="p">:</span> <span class="p">[{</span><span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;compact_20260112&#34;</span><span class="p">}]},</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span> <span class="k">as</span> <span class="n">stream</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">event</span> <span class="ow">in</span> <span class="n">stream</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="s2">&#34;content_block_start&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">content_block</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="s2">&#34;compaction&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">                <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Compaction started...&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="k">elif</span> <span class="n">event</span><span class="o">.</span><span class="n">content_block</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="s2">&#34;text&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">                <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Text response started...&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="k">elif</span> <span class="n">event</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="s2">&#34;content_block_delta&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">delta</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="s2">&#34;compaction_delta&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">                <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Compaction complete: </span><span class="si">{</span><span class="nb">len</span><span class="p">(</span><span class="n">event</span><span class="o">.</span><span class="n">delta</span><span class="o">.</span><span class="n">content</span> <span class="ow">or</span> <span class="s1">&#39;&#39;</span><span class="p">)</span><span class="si">}</span><span class="s2"> chars&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="k">elif</span> <span class="n">event</span><span class="o">.</span><span class="n">delta</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="s2">&#34;text_delta&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">                <span class="nb">print</span><span class="p">(</span><span class="n">event</span><span class="o">.</span><span class="n">delta</span><span class="o">.</span><span class="n">text</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s2">&#34;&#34;</span><span class="p">,</span> <span class="n">flush</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># Get the final accumulated message</span>
</span></span><span class="line"><span class="cl">    <span class="n">message</span> <span class="o">=</span> <span class="n">stream</span><span class="o">.</span><span class="n">get_final_message</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    <span class="n">messages</span><span class="o">.</span><span class="n">append</span><span class="p">({</span><span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;assistant&#34;</span><span class="p">,</span> <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="n">message</span><span class="o">.</span><span class="n">content</span><span class="p">})</span>
</span></span></code></pre></td></tr></table>
</div>
</div></CodeGroup>
<h3 id="提示缓存">提示缓存</h3>
<p>压缩与 <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching">提示缓存</a> 配合良好。你可以在 <code>compaction</code> block 上添加 <code>cache_control</code> 断点，以缓存摘要后的内容。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;assistant&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;content&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;compaction&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;[summary text]&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;cache_control&#34;</span><span class="p">:</span> <span class="p">{</span> <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;ephemeral&#34;</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;text&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;text&#34;</span><span class="p">:</span> <span class="s2">&#34;Based on our conversation...&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h4 id="通过-system-prompt-最大化缓存命中">通过 system prompt 最大化缓存命中</h4>
<p>发生压缩时，摘要会成为需要写入缓存的新内容。如果没有额外的缓存断点，这还会使任何已缓存的 system prompt 失效，从而需要将其与压缩摘要一起重新缓存。</p>
<p>为最大化缓存命中率，在 system prompt 末尾添加一个 <code>cache_control</code> 断点。这会使 system prompt 与对话分开缓存，因此发生压缩时：</p>
<ul>
<li>system prompt 缓存仍然有效，并从缓存读取</li>
<li>只需将压缩摘要作为新的缓存条目写入</li>
</ul>
<CodeGroup>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">client</span> <span class="o">=</span> <span class="n">anthropic</span><span class="o">.</span><span class="n">Anthropic</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">messages</span> <span class="o">=</span> <span class="p">[{</span><span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span> <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;Hello, Claude&#34;</span><span class="p">}]</span>
</span></span><span class="line"><span class="cl"><span class="n">response</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">beta</span><span class="o">.</span><span class="n">messages</span><span class="o">.</span><span class="n">create</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">betas</span><span class="o">=</span><span class="p">[</span><span class="s2">&#34;compact-2026-01-12&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">    <span class="n">model</span><span class="o">=</span><span class="s2">&#34;claude-opus-5&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">max_tokens</span><span class="o">=</span><span class="mi">4096</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">system</span><span class="o">=</span><span class="p">[</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;text&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;text&#34;</span><span class="p">:</span> <span class="s2">&#34;You are a helpful coding assistant...&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;cache_control&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;ephemeral&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="p">},</span>  <span class="c1"># Cache the system prompt separately</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">],</span>
</span></span><span class="line"><span class="cl">    <span class="n">messages</span><span class="o">=</span><span class="n">messages</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">context_management</span><span class="o">=</span><span class="p">{</span><span class="s2">&#34;edits&#34;</span><span class="p">:</span> <span class="p">[{</span><span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;compact_20260112&#34;</span><span class="p">}]},</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span></code></pre></td></tr></table>
</div>
</div></CodeGroup>
<p>这使较长的 system prompt 在整个对话的多次压缩事件中保持缓存。</p>
<h2 id="了解用量">了解用量</h2>
<p>压缩需要额外的采样步骤，该步骤计入速率限制和计费。API 会在响应中返回详细的用量信息：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;usage&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;input_tokens&#34;</span><span class="p">:</span> <span class="mi">23000</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;output_tokens&#34;</span><span class="p">:</span> <span class="mi">1000</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;iterations&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">      <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;compaction&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;input_tokens&#34;</span><span class="p">:</span> <span class="mi">180000</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;output_tokens&#34;</span><span class="p">:</span> <span class="mi">3500</span>
</span></span><span class="line"><span class="cl">      <span class="p">},</span>
</span></span><span class="line"><span class="cl">      <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;message&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;input_tokens&#34;</span><span class="p">:</span> <span class="mi">23000</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;output_tokens&#34;</span><span class="p">:</span> <span class="mi">1000</span>
</span></span><span class="line"><span class="cl">      <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">]</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p><code>iterations</code> 数组显示每次采样迭代的用量。发生压缩时，你会看到一次 <code>compaction</code> 迭代，随后是主要的 <code>message</code> 迭代。在此示例中，顶层的 <code>input_tokens</code> 和 <code>output_tokens</code> 与 <code>message</code> 迭代完全一致，因为只有一次非压缩迭代。最后一次迭代的 token 计数反映压缩后的有效上下文大小。</p>
<Note>
  顶层的 `input_tokens` 和 `output_tokens` 不包含压缩迭代的用量。它们反映所有非压缩迭代的总和。要计算一次请求消耗并计费的总 tokens，请对 `usage.iterations` 数组中的所有条目求和。
<p>如果你此前依赖 <code>usage.input_tokens</code> 和 <code>usage.output_tokens</code> 进行成本跟踪或审计，在启用压缩后需要更新跟踪逻辑，改为对 <code>usage.iterations</code> 进行汇总。启用压缩 beta 后，每个响应都包含 <code>usage.iterations</code>，即使未发生压缩。仅当请求期间触发了新的压缩时，才会出现 <code>compaction</code> 条目。重新应用先前的 <code>compaction</code> block 不会产生额外的压缩费用，此时顶层用量字段仍然准确。
</Note></p>
<h2 id="与其他功能结合">与其他功能结合</h2>
<h3 id="服务端工具">服务端工具</h3>
<p>使用服务端工具（例如 web search）时，会在每次采样迭代开始时检查压缩触发条件。根据触发阈值和生成的输出量，单次请求内可能发生多次压缩。</p>
<h3 id="token-计数">Token 计数</h3>
<p>token 计数端点（<code>/v1/messages/count_tokens</code>）会应用 prompt 中已有的 <code>compaction</code> block，但不会触发新的压缩。用它来检查先前压缩后的有效 token 数：</p>
<CodeGroup>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">client</span> <span class="o">=</span> <span class="n">anthropic</span><span class="o">.</span><span class="n">Anthropic</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">messages</span> <span class="o">=</span> <span class="p">[{</span><span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span> <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;Hello, Claude&#34;</span><span class="p">}]</span>
</span></span><span class="line"><span class="cl"><span class="n">count_response</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">beta</span><span class="o">.</span><span class="n">messages</span><span class="o">.</span><span class="n">count_tokens</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">betas</span><span class="o">=</span><span class="p">[</span><span class="s2">&#34;compact-2026-01-12&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">    <span class="n">model</span><span class="o">=</span><span class="s2">&#34;claude-opus-5&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">messages</span><span class="o">=</span><span class="n">messages</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">context_management</span><span class="o">=</span><span class="p">{</span><span class="s2">&#34;edits&#34;</span><span class="p">:</span> <span class="p">[{</span><span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;compact_20260112&#34;</span><span class="p">}]},</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Current tokens: </span><span class="si">{</span><span class="n">count_response</span><span class="o">.</span><span class="n">input_tokens</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Original tokens: </span><span class="si">{</span><span class="n">count_response</span><span class="o">.</span><span class="n">context_management</span><span class="o">.</span><span class="n">original_input_tokens</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span></code></pre></td></tr></table>
</div>
</div></CodeGroup>
<h2 id="示例">示例</h2>
<p>以下是一个带压缩的长时间运行对话的完整示例：</p>
<CodeGroup>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">client</span> <span class="o">=</span> <span class="n">anthropic</span><span class="o">.</span><span class="n">Anthropic</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">messages</span><span class="p">:</span> <span class="nb">list</span><span class="p">[</span><span class="nb">dict</span><span class="p">]</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">chat</span><span class="p">(</span><span class="n">user_message</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">messages</span><span class="o">.</span><span class="n">append</span><span class="p">({</span><span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span> <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="n">user_message</span><span class="p">})</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">response</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">beta</span><span class="o">.</span><span class="n">messages</span><span class="o">.</span><span class="n">create</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="n">betas</span><span class="o">=</span><span class="p">[</span><span class="s2">&#34;compact-2026-01-12&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">        <span class="n">model</span><span class="o">=</span><span class="s2">&#34;claude-opus-5&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="n">max_tokens</span><span class="o">=</span><span class="mi">4096</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="n">messages</span><span class="o">=</span><span class="n">messages</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="n">context_management</span><span class="o">=</span><span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;edits&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">                <span class="p">{</span>
</span></span><span class="line"><span class="cl">                    <span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;compact_20260112&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                    <span class="s2">&#34;trigger&#34;</span><span class="p">:</span> <span class="p">{</span><span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;input_tokens&#34;</span><span class="p">,</span> <span class="s2">&#34;value&#34;</span><span class="p">:</span> <span class="mi">100000</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">                <span class="p">}</span>
</span></span><span class="line"><span class="cl">            <span class="p">]</span>
</span></span><span class="line"><span class="cl">        <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># Append response (compaction blocks are automatically included)</span>
</span></span><span class="line"><span class="cl">    <span class="n">messages</span><span class="o">.</span><span class="n">append</span><span class="p">({</span><span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;assistant&#34;</span><span class="p">,</span> <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="n">response</span><span class="o">.</span><span class="n">content</span><span class="p">})</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># Return the text content</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="nb">next</span><span class="p">(</span><span class="n">block</span><span class="o">.</span><span class="n">text</span> <span class="k">for</span> <span class="n">block</span> <span class="ow">in</span> <span class="n">response</span><span class="o">.</span><span class="n">content</span> <span class="k">if</span> <span class="n">block</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="s2">&#34;text&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Run a long conversation</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">chat</span><span class="p">(</span><span class="s2">&#34;Help me build a Python web scraper&#34;</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">chat</span><span class="p">(</span><span class="s2">&#34;Add support for JavaScript-rendered pages&#34;</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">chat</span><span class="p">(</span><span class="s2">&#34;Now add rate limiting and error handling&#34;</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Continue calling chat() for as long as the conversation needs</span>
</span></span></code></pre></td></tr></table>
</div>
</div></CodeGroup>
<p>在 Claude Fable 5.1 上，从你在 <code>compaction</code> block 之后重新插入的任何 assistant turn 中移除 <code>thinking</code> 和 <code>redacted_thinking</code> block，或随 <code>thinking-binding-controls-2026-08-01</code> <a href="https://platform.claude.com/docs/en/api/beta-headers">beta header</a> 发送 <code>thinking.block_binding.prefix_mismatch_behavior: &quot;drop_block&quot;</code>。这些 block 是在完整历史存在时生成的，因此不再通过 <a href="https://platform.claude.com/docs/en/build-with-claude/thinking#preserved-in-conversation">conversation check</a>。在强制执行该检查的地方，继续请求会以 400 错误被拒绝。保留的 text 和 tool block 可以保持原样。让 API 摘要全部内容、而不重新插入更早的 turn，可避免此问题。</p>
<p>以下示例使用 <code>pause_after_compaction</code> 原样保留上一轮往来和当前 user message（共三条消息），而不是对它们进行摘要：</p>
<CodeGroup>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span><span class="lnt">45
</span><span class="lnt">46
</span><span class="lnt">47
</span><span class="lnt">48
</span><span class="lnt">49
</span><span class="lnt">50
</span><span class="lnt">51
</span><span class="lnt">52
</span><span class="lnt">53
</span><span class="lnt">54
</span><span class="lnt">55
</span><span class="lnt">56
</span><span class="lnt">57
</span><span class="lnt">58
</span><span class="lnt">59
</span><span class="lnt">60
</span><span class="lnt">61
</span><span class="lnt">62
</span><span class="lnt">63
</span><span class="lnt">64
</span><span class="lnt">65
</span><span class="lnt">66
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Any</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">client</span> <span class="o">=</span> <span class="n">anthropic</span><span class="o">.</span><span class="n">Anthropic</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">messages</span><span class="p">:</span> <span class="nb">list</span><span class="p">[</span><span class="nb">dict</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n">Any</span><span class="p">]]</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">chat</span><span class="p">(</span><span class="n">user_message</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">messages</span><span class="o">.</span><span class="n">append</span><span class="p">({</span><span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span> <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="n">user_message</span><span class="p">})</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">response</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">beta</span><span class="o">.</span><span class="n">messages</span><span class="o">.</span><span class="n">create</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="n">betas</span><span class="o">=</span><span class="p">[</span><span class="s2">&#34;compact-2026-01-12&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">        <span class="n">model</span><span class="o">=</span><span class="s2">&#34;claude-opus-5&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="n">max_tokens</span><span class="o">=</span><span class="mi">4096</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="n">messages</span><span class="o">=</span><span class="n">messages</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="n">context_management</span><span class="o">=</span><span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;edits&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">                <span class="p">{</span>
</span></span><span class="line"><span class="cl">                    <span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;compact_20260112&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                    <span class="s2">&#34;trigger&#34;</span><span class="p">:</span> <span class="p">{</span><span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;input_tokens&#34;</span><span class="p">,</span> <span class="s2">&#34;value&#34;</span><span class="p">:</span> <span class="mi">100000</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">                    <span class="s2">&#34;pause_after_compaction&#34;</span><span class="p">:</span> <span class="kc">True</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="p">}</span>
</span></span><span class="line"><span class="cl">            <span class="p">]</span>
</span></span><span class="line"><span class="cl">        <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># Check if compaction occurred and paused</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="n">response</span><span class="o">.</span><span class="n">stop_reason</span> <span class="o">==</span> <span class="s2">&#34;compaction&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="c1"># Get the compaction block from the response</span>
</span></span><span class="line"><span class="cl">        <span class="n">compaction_block</span> <span class="o">=</span> <span class="n">response</span><span class="o">.</span><span class="n">content</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="c1"># Preserve the prior exchange + current user message (3 messages)</span>
</span></span><span class="line"><span class="cl">        <span class="c1"># by including them after the compaction block</span>
</span></span><span class="line"><span class="cl">        <span class="n">preserved_messages</span> <span class="o">=</span> <span class="n">messages</span><span class="p">[</span><span class="o">-</span><span class="mi">3</span><span class="p">:]</span> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">messages</span><span class="p">)</span> <span class="o">&gt;=</span> <span class="mi">3</span> <span class="k">else</span> <span class="n">messages</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="c1"># Build new message list: compaction + preserved messages</span>
</span></span><span class="line"><span class="cl">        <span class="n">new_assistant_content</span> <span class="o">=</span> <span class="p">[</span><span class="n">compaction_block</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">        <span class="n">messages_after_compaction</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">            <span class="p">{</span><span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;assistant&#34;</span><span class="p">,</span> <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="n">new_assistant_content</span><span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">]</span> <span class="o">+</span> <span class="n">preserved_messages</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="c1"># Continue the request with the compacted context + preserved messages</span>
</span></span><span class="line"><span class="cl">        <span class="n">response</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">beta</span><span class="o">.</span><span class="n">messages</span><span class="o">.</span><span class="n">create</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">            <span class="n">betas</span><span class="o">=</span><span class="p">[</span><span class="s2">&#34;compact-2026-01-12&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">            <span class="n">model</span><span class="o">=</span><span class="s2">&#34;claude-opus-5&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">max_tokens</span><span class="o">=</span><span class="mi">4096</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">messages</span><span class="o">=</span><span class="n">messages_after_compaction</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">context_management</span><span class="o">=</span><span class="p">{</span><span class="s2">&#34;edits&#34;</span><span class="p">:</span> <span class="p">[{</span><span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;compact_20260112&#34;</span><span class="p">}]},</span>
</span></span><span class="line"><span class="cl">        <span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="c1"># Update the message list to reflect the compaction</span>
</span></span><span class="line"><span class="cl">        <span class="n">messages</span><span class="o">.</span><span class="n">clear</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">        <span class="n">messages</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">messages_after_compaction</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># Append the final response</span>
</span></span><span class="line"><span class="cl">    <span class="n">messages</span><span class="o">.</span><span class="n">append</span><span class="p">({</span><span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;assistant&#34;</span><span class="p">,</span> <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="n">response</span><span class="o">.</span><span class="n">content</span><span class="p">})</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># Return the text content</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="nb">next</span><span class="p">(</span><span class="n">block</span><span class="o">.</span><span class="n">text</span> <span class="k">for</span> <span class="n">block</span> <span class="ow">in</span> <span class="n">response</span><span class="o">.</span><span class="n">content</span> <span class="k">if</span> <span class="n">block</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="s2">&#34;text&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Run a long conversation</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">chat</span><span class="p">(</span><span class="s2">&#34;Help me build a Python web scraper&#34;</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">chat</span><span class="p">(</span><span class="s2">&#34;Add support for JavaScript-rendered pages&#34;</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">chat</span><span class="p">(</span><span class="s2">&#34;Now add rate limiting and error handling&#34;</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Continue calling chat() for as long as the conversation needs</span>
</span></span></code></pre></td></tr></table>
</div>
</div></CodeGroup>
<h2 id="当前限制">当前限制</h2>
<ul>
<li>
<p><strong>摘要使用同一模型：</strong> 请求中指定的模型会用于摘要。无法选择用另一个（例如更便宜的）模型来生成摘要。</p>
</li>
<li>
<p><strong>定义了 tools 时压缩可能失败：</strong> 当请求包含 <code>tools</code> 时，模型偶尔会在内部摘要步骤中调用工具，而不是撰写摘要。发生这种情况时，响应会包含一个 <code>content: null</code> 的 <code>compaction</code> block。为防止此问题，将 <a href="https://platform.claude.com/docs/en/build-with-claude/compaction#custom-summarization-instructions"><code>instructions</code></a> 设为明确告知模型不要调用工具的 prompt，例如：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">Summarize the transcript inside &lt;summary&gt;&lt;/summary&gt; tags. Include relevant information in the summary for continuing the task in the next context window. Do not call any tools while writing this summary; respond with text only.
</span></span></code></pre></td></tr></table>
</div>
</div></li>
</ul>
<h2 id="后续步骤">后续步骤</h2>
<CardGroup cols={3}>
  <Card title="上下文编辑" icon="edit" href="https://platform.claude.com/docs/en/build-with-claude/context-editing">
    随着对话增长，使用上下文编辑自动管理对话上下文。
  </Card>
  <Card title="上下文窗口" icon="arrows-left-right" href="https://platform.claude.com/docs/en/build-with-claude/context-windows">
    了解上下文窗口大小和管理策略。
  </Card>
  <Card title="Session memory 压缩 cookbook" icon="book" href="https://platform.claude.com/cookbook/misc-session-memory-compaction">
    探索一个实用实现：使用后台线程和提示缓存，通过即时 session memory 压缩管理长时间运行的对话。
  </Card>
</CardGroup>]]></content:encoded>
    </item>
    <item>
      <title>会话中途的 system messages 与工具变更</title>
      <link>https://tuanzi-wow.cn/%E4%B8%8A%E4%B8%8B%E6%96%87%E5%B7%A5%E7%A8%8B/claudecode_context_management_cn/mid-conversation-system-messages/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://tuanzi-wow.cn/%E4%B8%8A%E4%B8%8B%E6%96%87%E5%B7%A5%E7%A8%8B/claudecode_context_management_cn/mid-conversation-system-messages/</guid>
      <description>在对话进行到一半时更改 system 指令或工具可用性，而不使此前已缓存的前缀失效。</description>
      <content:encoded><![CDATA[<Note>
  要了解零数据保留（ZDR）如何适用于此功能，请参阅 [API and data retention](https://platform.claude.com/docs/en/manage-claude/api-and-data-retention)。
</Note>
<p>system 指令通常放在顶层 <code>system</code> 字段中，位于对话中每条消息之前。这个位置非常适合 <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching">Prompt Caching</a>：system prompt 是稳定前缀的一部分，因此后续 turn 会命中缓存。但对于你在会话进行到一半才发现需要的指令，这个位置就不合适了，因为编辑顶层 <code>system</code> 字段会改变 prompt 的最开头，并使之后所有内容的缓存失效。</p>
<p>会话中途的 system messages 填补了这一缺口。你可以在新指令变得相关的对话位置追加一条 <code>{&quot;role&quot;: &quot;system&quot;}</code> 消息，而不是编辑顶层 <code>system</code> 字段。已缓存的前缀保持不变，因此下一次请求仍会从缓存中读取它，而新指令仍会作为 system 指令应用，而不是作为普通的 user 文本。</p>
<Note>
  会话中途的 system messages 可在 Claude API、[Amazon Bedrock 上的 Claude](https://platform.claude.com/docs/en/build-with-claude/claude-in-amazon-bedrock) 和 [Google Cloud](https://platform.claude.com/docs/en/build-with-claude/claude-on-vertex-ai) 上使用。
<p>此功能适用于 Claude Fable 5.1、<a href="https://anthropic.com/glasswing">Claude Mythos 5.1</a>、Claude Fable 5、<a href="https://anthropic.com/glasswing">Claude Mythos 5</a>、Claude Opus 4.8 和 Claude Opus 5。会话中途的 system messages 不需要 beta header。此功能在 Claude Sonnet 5 上不可用。在该模型上请改用顶层 <code>system</code> 字段。</p>
<p><a href="https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages#mid-conversation-tool-changes">会话中途的工具变更</a> 处于 beta 阶段，需要 <code>mid-conversation-tool-changes-2026-07-01</code> beta header。它们在相同的模型上可用，覆盖 Claude API、Amazon Bedrock 和 Google Cloud。</p>
<p><a href="https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages#turn-scoped-system-messages">限定当前 turn 的 system messages</a>（<code>clear_at</code>）处于 beta 阶段，需要 <code>mid-conversation-system-clear-at-2026-08-21</code> beta header，适用的模型和平台与会话中途的 system messages 相同。
</Note></p>
<h2 id="会话中途的工具变更">会话中途的工具变更</h2>
<p><code>tools</code> 数组在经过哈希的请求前缀中的位置甚至比顶层 <code>system</code> 字段更靠前，因此编辑它会使整段对话的 <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching">提示词缓存</a> 失效。会话中途的工具变更是会话中途的 system messages 在工具方面的对应机制。你不必把工具列表固定为整段对话生命周期内不变，而是可以在 turn 之间更改向模型提供哪些工具：预先在 <code>tools</code> 中声明完整工具集，然后使用 <code>tool_addition</code> 和 <code>tool_removal</code> 块，从对话中的某个特定点起向模型提供某项工具，或将其撤回。<code>tools</code> 数组本身从不改变，因此已缓存的前缀保持完整。</p>
<p><code>tool_addition</code> 和 <code>tool_removal</code> 是 <code>role: &quot;system&quot;</code> 消息的 <code>content</code> 数组中的内容块，并且可以与同一条消息中的 <code>text</code> 块混合使用。该消息遵循与任何会话中途的 system message 相同的放置规则（参见 <a href="https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages#limitations">限制</a>），变更从对话中的该点起生效。每个块的 <code>tool</code> 字段引用一项工具，而不是定义工具：<code>{&quot;type&quot;: &quot;tool_reference&quot;, &quot;name&quot;: &quot;...&quot;}</code> 指名请求的 <code>tools</code> 数组中已声明的工具；<a href="https://platform.claude.com/docs/en/agents-and-tools/mcp-connector">MCP connector</a> 工具可以用 <code>mcp_tool_reference</code>（<code>server_name</code> 和 <code>name</code>）单独引用，或用 <code>mcp_toolset_reference</code>（<code>server_name</code>）作为整个工具集引用。引用未在 <code>tools</code> 中声明的名称会返回 400 错误。</p>
<p><code>tools</code> 中声明的每项工具从对话开始就会提供给模型，除非声明时带有 <code>defer_loading: true</code>，这会将其保留，直到某个 <code>tool_addition</code> 块将其呈现出来。<code>tool_addition</code> 也可以重新提供此前被 <code>tool_removal</code> 撤回的工具。</p>
<CodeGroup>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">client</span> <span class="o">=</span> <span class="n">anthropic</span><span class="o">.</span><span class="n">Anthropic</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">response</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">beta</span><span class="o">.</span><span class="n">messages</span><span class="o">.</span><span class="n">create</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">model</span><span class="o">=</span><span class="s2">&#34;claude-opus-5&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">max_tokens</span><span class="o">=</span><span class="mi">1024</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">betas</span><span class="o">=</span><span class="p">[</span><span class="s2">&#34;mid-conversation-tool-changes-2026-07-01&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># The full tool set is declared up front and never changes, so the</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># cached prefix stays intact.</span>
</span></span><span class="line"><span class="cl">    <span class="n">tools</span><span class="o">=</span><span class="p">[</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;get_weather&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;description&#34;</span><span class="p">:</span> <span class="s2">&#34;Get the current weather for a location.&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;input_schema&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;object&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;properties&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                    <span class="s2">&#34;location&#34;</span><span class="p">:</span> <span class="p">{</span><span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;string&#34;</span><span class="p">,</span> <span class="s2">&#34;description&#34;</span><span class="p">:</span> <span class="s2">&#34;City name&#34;</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">                <span class="p">},</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;required&#34;</span><span class="p">:</span> <span class="p">[</span><span class="s2">&#34;location&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">            <span class="p">},</span>
</span></span><span class="line"><span class="cl">        <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">],</span>
</span></span><span class="line"><span class="cl">    <span class="n">messages</span><span class="o">=</span><span class="p">[</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;Say OK.&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="p">},</span>
</span></span><span class="line"><span class="cl">        <span class="c1"># Withdraw get_weather from this point onward. The block references</span>
</span></span><span class="line"><span class="cl">        <span class="c1"># the tool by name instead of editing `tools`, so earlier turns stay</span>
</span></span><span class="line"><span class="cl">        <span class="c1"># byte-identical and the cache still hits.</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;system&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">                <span class="p">{</span>
</span></span><span class="line"><span class="cl">                    <span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;tool_removal&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                    <span class="s2">&#34;tool&#34;</span><span class="p">:</span> <span class="p">{</span><span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;tool_reference&#34;</span><span class="p">,</span> <span class="s2">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;get_weather&#34;</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">                <span class="p">},</span>
</span></span><span class="line"><span class="cl">            <span class="p">],</span>
</span></span><span class="line"><span class="cl">        <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">],</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">block</span> <span class="ow">in</span> <span class="n">response</span><span class="o">.</span><span class="n">content</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="n">block</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="s2">&#34;text&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="n">block</span><span class="o">.</span><span class="n">text</span><span class="p">)</span>
</span></span></code></pre></td></tr></table>
</div>
</div></CodeGroup>
<p>会话中途的工具变更处于 beta 阶段。要使用它们，请在请求中包含 beta header <code>mid-conversation-tool-changes-2026-07-01</code>。</p>
<h2 id="何时使用会话中途的-system-message">何时使用会话中途的 system message</h2>
<p><a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching">Prompt Caching</a> 按以下顺序对请求前缀进行哈希：<code>tools</code>，然后是 <code>system</code>，然后是 <code>messages</code>。缓存命中要求前缀与近期请求精确匹配，逐字节相同，直到缓存断点。</p>
<p>这一顺序意味着顶层 <code>system</code> 字段位于经过哈希的前缀的最开头附近。对它的任何更改，哪怕只是追加一句话，都会产生不同的哈希，请求会对 system prompt 及其后每条已缓存消息发生缓存未命中。</p>
<p>会话中途的 system messages 让你改为把指令加在消息历史的<strong>末尾</strong>。新指令之前的所有内容保持不变，因此现有缓存条目仍然匹配，只有新消息会作为新输入处理。</p>
<p>在以下几种情况下这很重要：</p>
<ul>
<li><strong>会话中途的策略或人设变更。</strong> 一段很长的 agentic 会话在数十个已缓存 turn 之后需要一条新约束（「从现在起，所有 SQL 都写成参数化查询」）。把它加到顶层 <code>system</code> 字段会重新处理整段历史。</li>
<li><strong>必须具有权威性的按 turn 上下文。</strong> 你想以 system 级别的权重注入新鲜度说明、会话截止时间或工具可用性变更，而这些内容变化太频繁，不适合放在已缓存的前缀中。</li>
<li><strong>不应堆积的按 turn 提醒。</strong> harness 在每批工具结果之后轻推模型（「把互不依赖的读取放在一起请求」、「用户已经有一段时间没听到你的消息了」），并希望模型只看到最新的一份。一条 <a href="https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages#turn-scoped-system-messages">限定当前 turn 的 system message</a> 渲染一个 turn，之后不再产生费用，同时不会从历史中删除任何内容。</li>
<li><strong>应用观察到的状态变更。</strong> 你的应用注意到某些 Claude 应视为操作者级别事实的情况：磁盘上的文件发生了变化、用户切换了自动批准设置、可用工具发生了变化，或剩余 token 预算降到了阈值以下。</li>
<li><strong>不应打断 agentic loop 的用户输入。</strong> 用户在 Claude 仍在为上一个请求执行工具时输入了后续内容。在下一条工具结果之后将其作为 system message 转达，可以让 Claude 把新输入并入它已经在做的工作中，而不是将其视为一个需要切换过去的全新请求。参见 <a href="https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages#placement-after-tool-results">放在工具结果之后</a>。</li>
<li><strong>授予持续性权限的模式切换。</strong> 会话级模式可以使用会话中途的 system message，为一项昂贵能力授予持续性授权，例如自动启动多智能体工作流，每隔若干 turn 给出简短提醒，并在模式关闭时给出退出通知。完整示例参见 <a href="https://platform.claude.com/docs/en/build-with-claude/mid-conversation-effort-example">构建编排模式</a>。</li>
</ul>
<p>在所有这些情况下，你都可以把指令放在普通的 <code>user</code> 消息中，而且 Claude 确实会遵循出现在 user turn 中的指令。差别在于优先级：<code>user</code> 消息被视为来自最终用户，而 <code>system</code> 消息被视为来自你——应用操作者。当两者冲突时，system 指令优先，因此对即使最终用户提出不同要求也应成立的操作者级别事实和约束，请使用 <code>system</code> 角色。会话中途的 system message 可以保持这种操作者级别的优先级，而无需承担因编辑顶层 <code>system</code> 字段而产生的缓存未命中成本。</p>
<h2 id="工作原理">工作原理</h2>
<p>向 <code>messages</code> 数组添加一条 <code>&quot;role&quot;: &quot;system&quot;</code> 的消息。<code>content</code> 可以使用纯字符串或内容块，与 <code>user</code> 或 <code>assistant</code> turn 相同。该指令从对话中的该点起生效。当指令冲突时，较后的 system messages 优先于较前的，并且对于其后的 turn，会话中途的 system messages 优先于顶层 <code>system</code> 字段。</p>
<p>对于应适用于整段对话的指令，你仍然可以设置顶层 <code>system</code> 字段。将会话中途的 system messages 留给那些稍后才变得相关的指令，或你希望在不使已缓存的前缀失效的情况下添加的指令。</p>
<p><code>role: &quot;system&quot;</code> 消息还可以携带 <code>output_config.effort</code>，从下一个 <code>user</code> turn 起更改 <a href="https://platform.claude.com/docs/en/build-with-claude/effort">effort</a> 级别。此功能在 Claude API 和 Google Cloud 上的 Claude Fable 5.1、Claude Mythos 5.1 和 Claude Opus 5 处于 beta 阶段，需要 <code>mid-conversation-output-config-2026-07-01</code> beta header。参见 <a href="https://platform.claude.com/docs/en/build-with-claude/effort#change-effort-mid-conversation-beta">按消息设置 effort</a>。</p>
<CodeGroup>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">client</span> <span class="o">=</span> <span class="n">anthropic</span><span class="o">.</span><span class="n">Anthropic</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">response</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">messages</span><span class="o">.</span><span class="n">create</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">model</span><span class="o">=</span><span class="s2">&#34;claude-opus-5&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">max_tokens</span><span class="o">=</span><span class="mi">1024</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># Automatic prompt caching: each request caches the conversation so far,</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># and the next request reads the unchanged prefix from cache.</span>
</span></span><span class="line"><span class="cl">    <span class="n">cache_control</span><span class="o">=</span><span class="p">{</span><span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;ephemeral&#34;</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="n">system</span><span class="o">=</span><span class="s2">&#34;You are a code review assistant. Be concise.&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">messages</span><span class="o">=</span><span class="p">[</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;Review process() in utils.py for performance issues.&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="p">},</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;assistant&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;The list comprehension is fine for small inputs. For large inputs, consider a generator to avoid materializing the full list.&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="p">},</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;Now review the calling code that invokes process().&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="p">},</span>
</span></span><span class="line"><span class="cl">        <span class="c1"># The reviewer realizes mid-session that all suggestions must</span>
</span></span><span class="line"><span class="cl">        <span class="c1"># also pass the team&#39;s strict typing policy. Appending the</span>
</span></span><span class="line"><span class="cl">        <span class="c1"># instruction here keeps earlier turns byte-identical, so the</span>
</span></span><span class="line"><span class="cl">        <span class="c1"># prefix cached by the previous request is still read from cache.</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;system&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;From now on, every suggestion must include explicit type annotations.&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">],</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">block</span> <span class="ow">in</span> <span class="n">response</span><span class="o">.</span><span class="n">content</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="n">block</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="s2">&#34;text&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="n">block</span><span class="o">.</span><span class="n">text</span><span class="p">)</span>
</span></span></code></pre></td></tr></table>
</div>
</div></CodeGroup>
<p>此示例通过顶层 <code>cache_control</code> 字段启用 <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#automatic-caching">自动缓存</a>。Prompt Caching 是选择加入的：如果请求没有 <code>cache_control</code> 字段（自动或 <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#explicit-cache-breakpoints">显式断点</a>），则不会缓存任何内容，每次请求都按完整对话支付常规输入 token 价格。启用缓存后，追加 system message 不会改变已经缓存的 turn，因此携带新指令的请求仍会从缓存中读取它们，而不是再次处理。缓存还要求对话满足 <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#cache-limitations">可缓存 prompt 的最小长度</a>；像本例这样短的示例低于该长度，因此 <code>cache_creation_input_tokens</code> 和 <code>cache_read_input_tokens</code> 会保持为 0，直到对话变长。</p>
<p>会话中途的 system message 必须紧跟在 <code>user</code> turn（或以 server tool result 结尾的 <code>assistant</code> turn）之后，并且必须是 <code>messages</code> 中的最后一项，或紧接着是一个 <code>assistant</code> turn。携带 <code>tool_result</code> 块的 <code>user</code> 消息也算：在 agentic loop 中，你可以把 system message 放在工具结果之后、Claude 的下一个 turn 之前。任何其他位置，包括在 <code>assistant</code> 的 <code>tool_use</code> 块与回答它的 <code>tool_result</code> 之间，都会返回 400 错误。</p>
<h3 id="放在工具结果之后">放在工具结果之后</h3>
<p>在 <a href="https://platform.claude.com/docs/en/agents-and-tools/tool-use/overview">agentic loop</a> 中，system message 放在交付工具结果的 <code>user</code> 消息之后。这也是你的应用可以转达用户在 Claude 工作期间输入的内容的位置，从而在不重启 turn 的情况下吸收新上下文：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">[</span>
</span></span><span class="line"><span class="cl">  <span class="p">{</span> <span class="nt">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span> <span class="nt">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;Run the test suite and fix any failures.&#34;</span> <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;assistant&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;content&#34;</span><span class="p">:</span> <span class="p">[{</span> <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;tool_use&#34;</span><span class="p">,</span> <span class="nt">&#34;id&#34;</span><span class="p">:</span> <span class="s2">&#34;toolu_01&#34;</span><span class="p">,</span> <span class="nt">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;run_tests&#34;</span><span class="p">,</span> <span class="nt">&#34;input&#34;</span><span class="p">:</span> <span class="p">{}</span> <span class="p">}]</span>
</span></span><span class="line"><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;content&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">      <span class="p">{</span> <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;tool_result&#34;</span><span class="p">,</span> <span class="nt">&#34;tool_use_id&#34;</span><span class="p">:</span> <span class="s2">&#34;toolu_01&#34;</span><span class="p">,</span> <span class="nt">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;12 passed, 0 failed&#34;</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">]</span>
</span></span><span class="line"><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;system&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;The user sent the following message while you were working: also update the changelog before you finish.&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">]</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>将 system 内容表述为上下文，而不是覆盖用户的命令。陈述事实（「用户发来了新输入：X」、「剩余 token 预算现在是 Y」），让 Claude 据此行动。Claude 经过训练会抵制看起来与用户作对的指令，这一保护同样适用于 system 角色，因此诸如「忽略用户所说的内容」这样的措辞，不如陈述发生了什么变化有效。</p>
<p>此模式用于转达来自该对话最终用户本人的输入。不要用它传递工具输出、检索到的文档或其他第三方内容；将这些内容放在 <code>tool_result</code> 块中（参见 <a href="https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages#limitations">限制</a>）。</p>
<h3 id="限定当前-turn-的-system-messages">限定当前 turn 的 system messages</h3>
<p>要将一条 <code>role: &quot;system&quot;</code> 消息限定到当前 turn，请设置其 <code>clear_at</code> 字段。它取以下两个值之一：</p>
<ul>
<li><code>&quot;never&quot;</code>（默认值）：该消息在包含它的每次请求中都会在其位置渲染。省略该字段效果相同。</li>
<li><code>&quot;next_user_message&quot;</code>：该消息是<strong>限定当前 turn 的</strong>。其文本仅在 <code>messages</code> 中其后没有 <code>role: &quot;user&quot;</code> 消息时渲染。此处，仅携带 <code>tool_result</code> 块的 user 消息也算作用户消息。一旦存在更后的 user 消息，该消息即为<strong>已清除</strong>：它仍留在数组中，但不渲染任何内容，也不消耗输入 token，对该请求及之后的每一次请求都是如此。</li>
</ul>
<p>限定当前 turn 的 system messages 处于 beta 阶段。请包含 <a href="https://platform.claude.com/docs/en/api/beta-headers">beta header</a> <code>mid-conversation-system-clear-at-2026-08-21</code>。没有它时，<code>clear_at</code> 会作为未知字段被拒绝。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;system&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;clear_at&#34;</span><span class="p">:</span> <span class="s2">&#34;next_user_message&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;First privately list what you need next; then request every item that doesn&#39;t depend on another&#39;s result in this one response.&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>主要用途是工具循环中的按 turn 提醒。每次希望模型看到该提醒时，将其追加在 <code>tool_result</code> 消息之后，并让更早的每一份副本留在原处。模型只看到最后一条 user 消息之后的副本，因此提醒不会堆积。<code>messages</code> 中更早的内容没有任何变化，因此 <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching">提示词缓存</a> 持续匹配。在 Claude Fable 5.1 上，这还能让后续的 <a href="https://platform.claude.com/docs/en/build-with-claude/thinking#preserved-in-conversation">thinking 块保持有效</a>：删除更早的提醒会改变那些块之前的对话，并使对话检查失败；而已清除的消息仍留在数组中，使该对话保持不变。</p>
<p>以下请求是 agent loop 的后续步骤。<code>messages[3]</code> 在更早的请求中被渲染，当时它是数组中的最后一条消息。一旦存在 <code>messages[5]</code>（更后的 user 消息），<code>messages[3]</code> 即被清除：已清除的消息仍留在数组中，因此 <code>messages[4]</code> 中 thinking 块之前的对话不变，但模型不再看到其文本。<code>messages[6]</code> 和 <code>messages[7]</code> 都会按顺序渲染。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span><span class="lnt">45
</span><span class="lnt">46
</span><span class="lnt">47
</span><span class="lnt">48
</span><span class="lnt">49
</span><span class="lnt">50
</span><span class="lnt">51
</span><span class="lnt">52
</span><span class="lnt">53
</span><span class="lnt">54
</span><span class="lnt">55
</span><span class="lnt">56
</span><span class="lnt">57
</span><span class="lnt">58
</span><span class="lnt">59
</span><span class="lnt">60
</span><span class="lnt">61
</span><span class="lnt">62
</span><span class="lnt">63
</span><span class="lnt">64
</span><span class="lnt">65
</span><span class="lnt">66
</span><span class="lnt">67
</span><span class="lnt">68
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;model&#34;</span><span class="p">:</span> <span class="s2">&#34;claude-fable-5-1&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;max_tokens&#34;</span><span class="p">:</span> <span class="mi">16000</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;messages&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span> <span class="nt">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span> <span class="nt">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;Fix the failing test.&#34;</span> <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;assistant&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;content&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span> <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;thinking&#34;</span><span class="p">,</span> <span class="nt">&#34;thinking&#34;</span><span class="p">:</span> <span class="s2">&#34;&#34;</span><span class="p">,</span> <span class="nt">&#34;signature&#34;</span><span class="p">:</span> <span class="s2">&#34;...&#34;</span> <span class="p">},</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;tool_use&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;id&#34;</span><span class="p">:</span> <span class="s2">&#34;toolu_01&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;read_file&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;input&#34;</span><span class="p">:</span> <span class="p">{</span> <span class="nt">&#34;path&#34;</span><span class="p">:</span> <span class="s2">&#34;test_auth.py&#34;</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">      <span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;content&#34;</span><span class="p">:</span> <span class="p">[{</span> <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;tool_result&#34;</span><span class="p">,</span> <span class="nt">&#34;tool_use_id&#34;</span><span class="p">:</span> <span class="s2">&#34;toolu_01&#34;</span><span class="p">,</span> <span class="nt">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;...&#34;</span> <span class="p">}]</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;system&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;clear_at&#34;</span><span class="p">:</span> <span class="s2">&#34;next_user_message&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;Request independent reads in one turn.&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;assistant&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;content&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span> <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;thinking&#34;</span><span class="p">,</span> <span class="nt">&#34;thinking&#34;</span><span class="p">:</span> <span class="s2">&#34;&#34;</span><span class="p">,</span> <span class="nt">&#34;signature&#34;</span><span class="p">:</span> <span class="s2">&#34;...&#34;</span> <span class="p">},</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;tool_use&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;id&#34;</span><span class="p">:</span> <span class="s2">&#34;toolu_02&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;read_file&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;input&#34;</span><span class="p">:</span> <span class="p">{</span> <span class="nt">&#34;path&#34;</span><span class="p">:</span> <span class="s2">&#34;auth.py&#34;</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">},</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;tool_use&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;id&#34;</span><span class="p">:</span> <span class="s2">&#34;toolu_03&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;read_file&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;input&#34;</span><span class="p">:</span> <span class="p">{</span> <span class="nt">&#34;path&#34;</span><span class="p">:</span> <span class="s2">&#34;tokens.py&#34;</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">      <span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;content&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span> <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;tool_result&#34;</span><span class="p">,</span> <span class="nt">&#34;tool_use_id&#34;</span><span class="p">:</span> <span class="s2">&#34;toolu_02&#34;</span><span class="p">,</span> <span class="nt">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;...&#34;</span> <span class="p">},</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;tool_result&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;tool_use_id&#34;</span><span class="p">:</span> <span class="s2">&#34;toolu_03&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;...&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;cache_control&#34;</span><span class="p">:</span> <span class="p">{</span> <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;ephemeral&#34;</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">      <span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;system&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;clear_at&#34;</span><span class="p">:</span> <span class="s2">&#34;next_user_message&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;Request independent reads in one turn.&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;system&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;clear_at&#34;</span><span class="p">:</span> <span class="s2">&#34;next_user_message&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;The shell exited with status 137.&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>限定当前 turn 的消息的规则：</p>
<ul>
<li><strong>逐字原样重新发送已清除的消息。</strong> 已清除的消息仍是对话历史的一部分。根据当前状态重建它（新的 token 计数、时间戳）、因冗余而丢弃它，或更改其 <code>clear_at</code> 值，都是对更早消息的编辑。提示词缓存会从该点起未命中，并且在 Claude Fable 5.1 上，其后产生的每个 thinking 块都会使 <a href="https://platform.claude.com/docs/en/build-with-claude/thinking#preserved-in-conversation">对话检查</a> 失败。</li>
<li><strong>仅限文本。</strong> <code>content</code> 是一个或多个 <code>text</code> 块（或字符串）。在限定当前 turn 的消息上，<code>tool_addition</code> 和 <code>tool_removal</code> 块会返回 400 错误，<code>output_config</code> 也是如此。对这些用途，请使用不带 <code>clear_at</code> 的单独 <code>role: &quot;system&quot;</code> 消息。</li>
<li><strong>其块上不得有 <code>cache_control</code>。</strong> 已清除的消息永远不会成为缓存键的一部分，因此其上的断点永远无法匹配。请像示例那样，把断点放在前一个 user turn 的最后一个块上。顶层 <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#automatic-caching">自动缓存</a> 字段在选取断点时会跳过限定当前 turn 的消息。在清除某条消息的那次请求上，可复用的已缓存前缀结束于它之前的 user turn，因此只有该消息与新 user 消息之间的那一个 assistant turn 会被重新处理。</li>
<li><strong>放置规则仍然适用</strong>，无论是否已清除。限定当前 turn 的消息必须跟在 <code>user</code> turn（或以 server tool result 结尾的 <code>assistant</code> turn）之后，并位于 <code>assistant</code> turn 之前或作为数组的结尾，与任何会话中途的 system message 一样。作为数组结尾的那条始终会渲染。直接后跟另一条 <code>user</code> 消息的则是 400 错误，而不是已清除的消息：把一轮工具的所有结果放在一条 user 消息中，提醒放在其后。</li>
<li><strong>Assistant turn 不会清除它。</strong> 该消息之后的预填充或 <a href="https://platform.claude.com/docs/en/build-with-claude/handling-stop-reasons#pause-turn">paused</a> assistant turn，或服务端工具循环，都不会添加 user 消息，因此该消息在那次续写上仍会渲染。要在客户端工具循环中让提醒保持可见，请在每条 <code>tool_result</code> 消息之后再次追加它。</li>
<li><strong>Token 计数跟随渲染内容。</strong> 已清除的消息不会增加 <code>usage.input_tokens</code>，也不会增加 <a href="https://platform.claude.com/docs/en/build-with-claude/token-counting">token 计数</a>。</li>
<li><strong>导入的历史。</strong> 在你一次性构建的转录中（few-shot 示例、迁移过来的对话），一条其后已经有 assistant turn 和 user 消息的限定当前 turn 的消息，会从第一次请求起就被清除，并且从不渲染。这对你要沿用的按 turn 提醒来说是正确状态。仅在模型应在每次请求中都看到的消息上不设置 <code>clear_at</code>。</li>
</ul>
<p>校验错误如下：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">messages.3.clear_at: Extra inputs are not permitted
</span></span><span class="line"><span class="cl">messages.3.clear_at: clear_at is only permitted on role &#39;system&#39; messages
</span></span><span class="line"><span class="cl">messages.3.clear_at: Input should be &#39;next_user_message&#39; or &#39;never&#39;
</span></span><span class="line"><span class="cl">messages.3: a turn-scoped system message supports text blocks only (clear_at: &#39;next_user_message&#39;)
</span></span><span class="line"><span class="cl">messages.3: output_config is not permitted on a turn-scoped system message (clear_at: &#39;next_user_message&#39;)
</span></span><span class="line"><span class="cl">messages.3.content.0: cache_control is not permitted on a turn-scoped system message (clear_at: &#39;next_user_message&#39;)
</span></span></code></pre></td></tr></table>
</div>
</div><p>第一条是未带 beta header 时返回的错误。在 Amazon Bedrock 和 Google Cloud 上，按 <a href="https://platform.claude.com/docs/en/api/beta-headers">Beta headers</a> 中的说明传递 beta 值。</p>
<p>通过 SDK，在 <code>messages</code> 中的 <code>role: &quot;system&quot;</code> 条目上设置 <code>clear_at</code> 并发送 beta header。以下示例在 user turn 之后追加一条限定当前 turn 的提醒；在下一次请求中，一旦存在更后的 user 消息，该提醒仍留在数组中但不再渲染：</p>
<CodeGroup>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">client</span> <span class="o">=</span> <span class="n">anthropic</span><span class="o">.</span><span class="n">Anthropic</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">response</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">beta</span><span class="o">.</span><span class="n">messages</span><span class="o">.</span><span class="n">create</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">model</span><span class="o">=</span><span class="s2">&#34;claude-fable-5-1&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">max_tokens</span><span class="p">:</span> <span class="mi">4096</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">messages</span><span class="o">=</span><span class="p">[</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;Draft a short status update on the database migration for the team channel.&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="p">},</span>
</span></span><span class="line"><span class="cl">        <span class="c1"># Turn-scoped reminder: renders for this turn, then clears once a later user message exists.</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;system&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;clear_at&#34;</span><span class="p">:</span> <span class="s2">&#34;next_user_message&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;The reader is on call: keep this reply under 50 words.&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">],</span>
</span></span><span class="line"><span class="cl">    <span class="n">betas</span><span class="o">=</span><span class="p">[</span><span class="s2">&#34;mid-conversation-system-clear-at-2026-08-21&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">block</span> <span class="ow">in</span> <span class="n">response</span><span class="o">.</span><span class="n">content</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="n">block</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="s2">&#34;text&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="n">block</span><span class="o">.</span><span class="n">text</span><span class="p">)</span>
</span></span></code></pre></td></tr></table>
</div>
</div></CodeGroup>
<h2 id="与-prompt-caching-结合使用">与 Prompt Caching 结合使用</h2>
<p>会话中途的 system messages 与 <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching">Prompt Caching</a> 被设计为一起使用：</p>
<ul>
<li><strong>显式启用缓存。</strong> 仅当请求包含 <code>cache_control</code> 时才会发生缓存，可以是顶层 <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#automatic-caching">自动缓存</a> 字段，或内容块上的 <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#explicit-cache-breakpoints">显式断点</a>。会话中途的 system message 本身不会创建缓存条目，未启用缓存时也就没有可保留的节省。</li>
<li><strong>照常缓存稳定前缀。</strong> 将 <code>cache_control</code> 放在跨请求保持不变的最后一个块上，无论那是顶层 <code>system</code> 字段的末尾、工具定义的末尾，还是消息历史中的某个稳定点。</li>
<li><strong>在断点之后追加 system message。</strong> 因为它位于已缓存的前缀之后，不会改变前缀哈希，缓存仍然命中。</li>
<li><strong>会话中途的 system message 本身也可缓存。</strong> 一旦它进入对话，就成为稳定历史的一部分。在下一个 turn，你可以把缓存断点移到它之后（或依赖 <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#automatic-caching">自动缓存</a> 来完成），该 system message 就会像任何其他 turn 一样从缓存中读取。</li>
</ul>
<p>避免编辑或删除已经发送的会话中途的 system message。与对更早消息的任何其他更改一样，这会使缓存从该点起失效。在 Claude Fable 5.1 上，它还会使之后每个 assistant turn 中的 <a href="https://platform.claude.com/docs/en/build-with-claude/thinking#preserved-in-conversation">thinking 块</a> 失效。对于只应适用于一个 turn 的指引，请使用 <a href="https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages#turn-scoped-system-messages">限定当前 turn 的 system message</a> 并保持其原位。如果指令需要演进，请追加一条新的 system message，而不是改写旧的。连续的 system messages 会被接受并视为单个 system 区段，该区段作为整体遵循相同的放置规则。</p>
<h2 id="限制">限制</h2>
<ul>
<li><strong>不能作为第一条消息。</strong> 携带内容的 <code>system</code> 消息不能是 <code>messages</code> 中的第一项。对于从一开始就适用的指令，请使用顶层 <code>system</code> 字段。</li>
<li><strong>放置位置受约束。</strong> 携带内容（<code>text</code>、<code>tool_addition</code> 或 <code>tool_removal</code> 块）的 <code>system</code> 消息必须紧跟在 <code>user</code> turn（包括携带 <code>tool_result</code> 块的 <code>user</code> turn）或以 server tool result 结尾的 <code>assistant</code> turn 之后，并且必须位于 <code>assistant</code> turn 之前或作为数组的结尾。它不能位于 <code>tool_use</code> 块与其 <code>tool_result</code> 之间。放在其他位置会返回 400 错误。有一个例外：<code>tool_addition</code> 和 <code>tool_removal</code> 块不被接受紧跟在 <a href="https://platform.claude.com/docs/en/build-with-claude/handling-stop-reasons#pause-turn">paused</a> 的 <code>assistant</code> turn（以 server tool result 结尾的 turn）之后，但 <code>text</code> 块可以；请先恢复 paused 的 turn，然后在下一条 <code>system</code> 消息中发送工具变更。<code>content</code> 为空、仅设置 <a href="https://platform.claude.com/docs/en/build-with-claude/effort#change-effort-mid-conversation-beta"><code>output_config.effort</code></a> 的消息在其位置不渲染任何内容，并且可被接受在 <code>messages</code> 中的任何位置，包括第一条，或位于 <code>assistant</code> turn 与 <code>user</code> turn 之间。连续的 <code>system</code> 消息会被一起判断，因此在仅含 effort 的消息旁边添加一条携带文本的消息，会使整组遵循内容规则。</li>
<li><strong>限定当前 turn 的消息仅限文本，并逐字原样重新发送。</strong> <code>clear_at: &quot;next_user_message&quot;</code> 消息不携带 <code>tool_addition</code>、<code>tool_removal</code>、<code>output_config</code> 或 <code>cache_control</code>，一旦已清除，它必须在后续请求中逐字节相同地留在 <code>messages</code> 中。参见 <a href="https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages#turn-scoped-system-messages">限定当前 turn 的 system messages</a>。</li>
<li><strong>不是放置不受信任内容的地方。</strong> Claude 将 system 内容视为操作者指令并遵循它。不要将来自对话之外的文本（例如原始工具输出、检索到的文档或网页内容）直接放在 system message 中；这样做会赋予该文本操作者级别的权限。将这些数据放在 <code>tool_result</code> 块中，并继续遵循 <a href="https://platform.claude.com/docs/en/test-and-evaluate/strengthen-guardrails/mitigate-jailbreaks">缓解 jailbreak 与 prompt injection</a>。</li>
</ul>
<h2 id="相关内容">相关内容</h2>
<CardGroup cols={2}>
  <Card title="Prompt Caching" icon="bolt" href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching">
    缓存如何工作、断点放在哪里，以及如何读取缓存用量字段。
  </Card>
  <Card title="缓存诊断" icon="magnifying-glass" href="https://platform.claude.com/docs/en/build-with-claude/cache-diagnostics">
    当预期的缓存命中未发生时，查明两条请求究竟在何处分叉。
  </Card>
  <Card title="使用 Messages API" icon="message" href="https://platform.claude.com/docs/en/build-with-claude/working-with-messages">
    消息结构、多轮对话以及 `system` 字段。
  </Card>
  <Card title="Prompt 最佳实践" icon="text" href="https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/claude-prompting-best-practices">
    编写有效的 prompt 和 system 指令。
  </Card>
  <Card title="在 Claude 中使用工具" icon="wrench" href="https://platform.claude.com/docs/en/agents-and-tools/tool-use/overview">
    `tool_use` 和 `tool_result` 块在 `messages` 数组中的结构。
  </Card>
</CardGroup>
]]></content:encoded>
    </item>
    <item>
      <title>Prompt Caching</title>
      <link>https://tuanzi-wow.cn/%E4%B8%8A%E4%B8%8B%E6%96%87%E5%B7%A5%E7%A8%8B/claudecode_context_management_cn/prompt-caching/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://tuanzi-wow.cn/%E4%B8%8A%E4%B8%8B%E6%96%87%E5%B7%A5%E7%A8%8B/claudecode_context_management_cn/prompt-caching/</guid>
      <description>使用 `cache_control` 缓存 prompt 前缀，以降低成本和延迟；可采用自动缓存或显式缓存断点，TTL 为 5 分钟或 1 小时。</description>
      <content:encoded><![CDATA[<p>Prompt Caching 通过允许从 prompt 中的特定前缀恢复来优化 API 用量。对于重复性任务或包含一致元素的 prompt，这会显著降低处理时间和成本。</p>
<Note>
  要了解零数据保留（ZDR）如何适用于此功能，请参阅 [API and data retention](https://platform.claude.com/docs/en/manage-claude/api-and-data-retention)。
</Note>
<p>有两种方式启用 Prompt Caching：</p>
<ul>
<li><strong><a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#automatic-caching">自动缓存</a></strong>：在请求的顶层添加单个 <code>cache_control</code> 字段。系统会自动将缓存断点应用到最后一个可缓存块，并随对话增长向前移动。最适合多轮对话，其中不断增长的消息历史应被自动缓存。</li>
<li><strong><a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#explicit-cache-breakpoints">显式缓存断点</a></strong>：将 <code>cache_control</code> 直接放在各个内容块上，以精细控制究竟缓存哪些内容。</li>
</ul>
<p>最简单的起步方式是使用自动缓存：</p>
<CodeGroup>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">client</span> <span class="o">=</span> <span class="n">anthropic</span><span class="o">.</span><span class="n">Anthropic</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">response</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">messages</span><span class="o">.</span><span class="n">create</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">model</span><span class="o">=</span><span class="s2">&#34;claude-opus-5&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">max_tokens</span><span class="o">=</span><span class="mi">1024</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">cache_control</span><span class="o">=</span><span class="p">{</span><span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;ephemeral&#34;</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="n">system</span><span class="o">=</span><span class="s2">&#34;You are an AI assistant tasked with analyzing literary works. Your goal is to provide insightful commentary on themes, characters, and writing style.&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">messages</span><span class="o">=</span><span class="p">[</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;Analyze the major themes in &#39;Pride and Prejudice&#39;.&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">],</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">response</span><span class="o">.</span><span class="n">usage</span><span class="o">.</span><span class="n">model_dump_json</span><span class="p">())</span>
</span></span></code></pre></td></tr></table>
</div>
</div></CodeGroup>
<p>使用自动缓存时，系统会缓存直到并包括最后一个可缓存块的全部内容。在后续具有相同前缀的请求中，缓存内容会自动复用。</p>
<hr>
<h2 id="prompt-caching-如何工作">Prompt Caching 如何工作</h2>
<p>当你发送启用了 Prompt Caching 的请求时：</p>
<ol>
<li>系统检查某个 prompt 前缀（直到指定的缓存断点）是否已从近期查询中缓存。</li>
<li>如果找到，则使用缓存版本，从而降低处理时间和成本。</li>
<li>否则，系统处理完整 prompt，并在响应开始后缓存该前缀。</li>
</ol>
<p>这尤其适用于：</p>
<ul>
<li>包含大量示例的 prompt</li>
<li>大量上下文或背景信息</li>
<li>带有一致指令的重复性任务</li>
<li>较长的多轮对话</li>
</ul>
<p>默认情况下，缓存的生命周期为 5 分钟。每次使用缓存内容时，缓存都会刷新，且不产生额外费用。</p>
<p>生命周期从写入或读取该缓存条目的请求开始时刻起算，而非从其响应结束时刻起算。生成响应所花费的时间会计入生命周期：如果一次响应需要 4 分钟才能完成流式传输，则复用同一缓存前缀的后续请求必须在该响应完成后大约 1 分钟内开始。</p>
<Note>
  如果你觉得 5 分钟太短，Anthropic 还提供 1 小时缓存时长，[需额外付费](https://platform.claude.com/docs/en/build-with-claude/prompt-caching#pricing)。
<p>更多信息请参阅 <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#1-hour-cache-duration">1 小时缓存时长</a>。
</Note></p>
<Tip>
  **Prompt Caching 缓存完整前缀**
<p>Prompt Caching 引用整个 prompt——<code>tools</code>、<code>system</code> 和 <code>messages</code>（按此顺序），直到并包括用 <code>cache_control</code> 指定的块。
</Tip></p>
<hr>
<h2 id="定价">定价</h2>
<p>Prompt Caching 引入了新的定价结构。下表列出了每个支持的模型每百万 token 的价格：</p>
<table>
	<thead>
			<tr>
					<th>模型</th>
					<th>基础输入 token</th>
					<th>5 分钟缓存写入</th>
					<th>1 小时缓存写入</th>
					<th>缓存命中与刷新</th>
					<th>输出 token</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Claude Fable 5.1</td>
					<td>$10 / MTok</td>
					<td>$12.50 / MTok</td>
					<td>$20 / MTok</td>
					<td>$0.25 / MTok1</td>
					<td>$50 / MTok</td>
			</tr>
			<tr>
					<td>Claude Mythos 5.1 (<a href="https://anthropic.com/glasswing">有限供应</a>)</td>
					<td>$10 / MTok</td>
					<td>$12.50 / MTok</td>
					<td>$20 / MTok</td>
					<td>$0.25 / MTok1</td>
					<td>$50 / MTok</td>
			</tr>
			<tr>
					<td>Claude Fable 5</td>
					<td>$10 / MTok</td>
					<td>$12.50 / MTok</td>
					<td>$20 / MTok</td>
					<td>$1 / MTok</td>
					<td>$50 / MTok</td>
			</tr>
			<tr>
					<td>Claude Mythos 5 (<a href="https://anthropic.com/glasswing">有限供应</a>)</td>
					<td>$10 / MTok</td>
					<td>$12.50 / MTok</td>
					<td>$20 / MTok</td>
					<td>$1 / MTok</td>
					<td>$50 / MTok</td>
			</tr>
			<tr>
					<td>Claude Opus 5</td>
					<td>$5 / MTok</td>
					<td>$6.25 / MTok</td>
					<td>$10 / MTok</td>
					<td>$0.50 / MTok</td>
					<td>$25 / MTok</td>
			</tr>
			<tr>
					<td>Claude Opus 4.8</td>
					<td>$5 / MTok</td>
					<td>$6.25 / MTok</td>
					<td>$10 / MTok</td>
					<td>$0.50 / MTok</td>
					<td>$25 / MTok</td>
			</tr>
			<tr>
					<td>Claude Opus 4.7</td>
					<td>$5 / MTok</td>
					<td>$6.25 / MTok</td>
					<td>$10 / MTok</td>
					<td>$0.50 / MTok</td>
					<td>$25 / MTok</td>
			</tr>
			<tr>
					<td>Claude Opus 4.6</td>
					<td>$5 / MTok</td>
					<td>$6.25 / MTok</td>
					<td>$10 / MTok</td>
					<td>$0.50 / MTok</td>
					<td>$25 / MTok</td>
			</tr>
			<tr>
					<td>Claude Opus 4.5</td>
					<td>$5 / MTok</td>
					<td>$6.25 / MTok</td>
					<td>$10 / MTok</td>
					<td>$0.50 / MTok</td>
					<td>$25 / MTok</td>
			</tr>
			<tr>
					<td>Claude Opus 4.1 (<a href="https://platform.claude.com/docs/en/about-claude/model-deprecations">已退役，Bedrock 和 Google Cloud 除外</a>)</td>
					<td>$15 / MTok</td>
					<td>$18.75 / MTok</td>
					<td>$30 / MTok</td>
					<td>$1.50 / MTok</td>
					<td>$75 / MTok</td>
			</tr>
			<tr>
					<td>Claude Opus 4 (<a href="https://platform.claude.com/docs/en/about-claude/model-deprecations">已退役，Google Cloud 除外</a>)</td>
					<td>$15 / MTok</td>
					<td>$18.75 / MTok</td>
					<td>$30 / MTok</td>
					<td>$1.50 / MTok</td>
					<td>$75 / MTok</td>
			</tr>
			<tr>
					<td>Claude Sonnet 5</td>
					<td>$2 / MTok</td>
					<td>$2.50 / MTok</td>
					<td>$4 / MTok</td>
					<td>$0.20 / MTok</td>
					<td>$10 / MTok</td>
			</tr>
			<tr>
					<td>Claude Sonnet 4.6</td>
					<td>$3 / MTok</td>
					<td>$3.75 / MTok</td>
					<td>$6 / MTok</td>
					<td>$0.30 / MTok</td>
					<td>$15 / MTok</td>
			</tr>
			<tr>
					<td>Claude Sonnet 4.5</td>
					<td>$3 / MTok</td>
					<td>$3.75 / MTok</td>
					<td>$6 / MTok</td>
					<td>$0.30 / MTok</td>
					<td>$15 / MTok</td>
			</tr>
			<tr>
					<td>Claude Sonnet 4 (<a href="https://platform.claude.com/docs/en/about-claude/model-deprecations">已退役，Bedrock 和 Google Cloud 除外</a>)</td>
					<td>$3 / MTok</td>
					<td>$3.75 / MTok</td>
					<td>$6 / MTok</td>
					<td>$0.30 / MTok</td>
					<td>$15 / MTok</td>
			</tr>
			<tr>
					<td>Claude Haiku 4.5</td>
					<td>$1 / MTok</td>
					<td>$1.25 / MTok</td>
					<td>$2 / MTok</td>
					<td>$0.10 / MTok</td>
					<td>$5 / MTok</td>
			</tr>
			<tr>
					<td>Claude Haiku 3.5 (<a href="https://platform.claude.com/docs/en/about-claude/model-deprecations">已退役，Bedrock 和 Google Cloud 除外</a>)</td>
					<td>$0.80 / MTok</td>
					<td>$1 / MTok</td>
					<td>$1.60 / MTok</td>
					<td>$0.08 / MTok</td>
					<td>$4 / MTok</td>
			</tr>
	</tbody>
</table>
<p><em>1 Claude Fable 5.1 和 Claude Mythos 5.1 的缓存命中与刷新按基础输入价格的 0.025 倍计费。所有其他模型使用标准的 0.1 倍乘数。</em></p>
<Note>
  上表反映了 Prompt Caching 的以下定价乘数：
<ul>
<li>5 分钟缓存写入 token 为基础输入 token 价格的 1.25 倍</li>
<li>1 小时缓存写入 token 为基础输入 token 价格的 2 倍</li>
<li>缓存读取 token 为基础输入 token 价格的 0.1 倍（各模型例外见上表脚注）</li>
</ul>
<p>这些乘数会与其他定价调整项叠加，例如 Batch API 折扣和数据驻留。完整详情请参阅 <a href="https://platform.claude.com/docs/en/about-claude/pricing">pricing</a>。
</Note></p>
<hr>
<h2 id="支持的模型">支持的模型</h2>
<p>Prompt Caching（自动缓存和显式缓存断点）在所有<a href="https://platform.claude.com/docs/en/models/overview">当前可用的 Claude 模型</a>上均受支持。</p>
<hr>
<h2 id="自动缓存">自动缓存</h2>
<p>自动缓存是启用 Prompt Caching 的最简单方式。不必在各个内容块上放置 <code>cache_control</code>，只需在请求体顶层添加单个 <code>cache_control</code> 字段。系统会自动将缓存断点应用到最后一个可缓存块。</p>
<CodeGroup>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">client</span> <span class="o">=</span> <span class="n">anthropic</span><span class="o">.</span><span class="n">Anthropic</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">response</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">messages</span><span class="o">.</span><span class="n">create</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">model</span><span class="o">=</span><span class="s2">&#34;claude-opus-5&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">max_tokens</span><span class="o">=</span><span class="mi">1024</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">cache_control</span><span class="o">=</span><span class="p">{</span><span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;ephemeral&#34;</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="n">system</span><span class="o">=</span><span class="s2">&#34;You are a helpful assistant that remembers our conversation.&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">messages</span><span class="o">=</span><span class="p">[</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span><span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span> <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;My name is Alex. I work on machine learning.&#34;</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;assistant&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;Nice to meet you, Alex! How can I help with your ML work today?&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="p">},</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span><span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span> <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;What did I say I work on?&#34;</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">],</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">response</span><span class="o">.</span><span class="n">usage</span><span class="o">.</span><span class="n">model_dump_json</span><span class="p">())</span>
</span></span></code></pre></td></tr></table>
</div>
</div></CodeGroup>
<h3 id="自动缓存在多轮对话中如何工作">自动缓存在多轮对话中如何工作</h3>
<p>使用自动缓存时，缓存点会随对话增长自动向前移动。每个新请求会缓存直到最后一个可缓存块的全部内容，而先前内容则从缓存读取。</p>
<table>
	<thead>
			<tr>
					<th>请求</th>
					<th>内容</th>
					<th>缓存行为</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>请求 1</td>
					<td>System + User(1) + Asst(1) + <strong>User(2)</strong> ◀ cache</td>
					<td>全部写入缓存</td>
			</tr>
			<tr>
					<td>请求 2</td>
					<td>System + User(1) + Asst(1) + User(2) + Asst(2) + <strong>User(3)</strong> ◀ cache</td>
					<td>System 到 User(2) 从缓存读取；Asst(2) + User(3) 写入缓存</td>
			</tr>
			<tr>
					<td>请求 3</td>
					<td>System + User(1) + Asst(1) + User(2) + Asst(2) + User(3) + Asst(3) + <strong>User(4)</strong> ◀ cache</td>
					<td>System 到 User(3) 从缓存读取；Asst(3) + User(4) 写入缓存</td>
			</tr>
	</tbody>
</table>
<p>缓存断点会在每个请求中自动移到最后一个可缓存块，因此你无需随对话增长去更新任何 <code>cache_control</code> 标记。</p>
<h3 id="ttl-支持">TTL 支持</h3>
<p>默认情况下，自动缓存使用 5 分钟 TTL。你可以指定 1 小时 TTL，价格为基础输入 token 价格的 2 倍：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span> <span class="nt">&#34;cache_control&#34;</span><span class="p">:</span> <span class="p">{</span> <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;ephemeral&#34;</span><span class="p">,</span> <span class="nt">&#34;ttl&#34;</span><span class="p">:</span> <span class="s2">&#34;1h&#34;</span> <span class="p">}</span> <span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="与块级缓存结合">与块级缓存结合</h3>
<p>自动缓存与<a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#explicit-cache-breakpoints">显式缓存断点</a>兼容。一起使用时，自动缓存断点会占用 4 个可用断点槽位中的一个。</p>
<p>这让你可以同时采用两种方式。例如，用显式断点缓存 system prompt，同时由自动缓存处理对话：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;model&#34;</span><span class="p">:</span> <span class="s2">&#34;claude-opus-5&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;max_tokens&#34;</span><span class="p">:</span> <span class="mi">1024</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;cache_control&#34;</span><span class="p">:</span> <span class="p">{</span> <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;ephemeral&#34;</span> <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;system&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;text&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;text&#34;</span><span class="p">:</span> <span class="s2">&#34;You are a helpful assistant.&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;cache_control&#34;</span><span class="p">:</span> <span class="p">{</span> <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;ephemeral&#34;</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">],</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;messages&#34;</span><span class="p">:</span> <span class="p">[{</span> <span class="nt">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span> <span class="nt">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;What are the key terms?&#34;</span> <span class="p">}]</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="哪些保持不变">哪些保持不变</h3>
<p>自动缓存使用相同的底层缓存基础设施。定价、最低 token 阈值、上下文顺序要求以及 20 块回看窗口，均与显式缓存断点相同。</p>
<h3 id="边界情况">边界情况</h3>
<ul>
<li>如果最后一个块已经带有相同 TTL 的显式 <code>cache_control</code>，自动缓存为 no-op。</li>
<li>如果最后一个块带有不同 TTL 的显式 <code>cache_control</code>，API 返回 400 error。</li>
<li>如果已经存在 4 个显式块级断点，API 返回 400 error（没有剩余槽位给自动缓存）。</li>
<li>如果最后一个块不适合作为自动缓存断点目标，系统会静默向后查找最近的合格块。如果找不到，则跳过缓存。</li>
</ul>
<Note>
  自动缓存在除旧版 [Amazon Bedrock (Opus 4.6 and earlier)](https://platform.claude.com/docs/en/build-with-claude/claude-on-amazon-bedrock-legacy) 集成之外的所有平台上均可用。在该集成上，顶层 `cache_control` 字段会使 API 返回 400 error，因此请改用[显式缓存断点](https://platform.claude.com/docs/en/build-with-claude/prompt-caching#explicit-cache-breakpoints)。
</Note>
<hr>
<h2 id="显式缓存断点">显式缓存断点</h2>
<p>若要更精细地控制缓存，你可以将 <code>cache_control</code> 直接放在各个内容块上。当你需要缓存以不同频率变化的不同区段，或需要精细控制究竟缓存哪些内容时，这很有用。</p>
<h3 id="组织你的-prompt">组织你的 prompt</h3>
<p>将静态内容（工具定义、系统指令、上下文、示例）放在 prompt 开头。使用 <code>cache_control</code> 参数标记可复用内容的末尾以便缓存。</p>
<p>缓存前缀按以下顺序创建：<code>tools</code>、<code>system</code>，然后是 <code>messages</code>。该顺序形成层级，每一层都建立在前一层之上。</p>
<h4 id="自动前缀检查如何工作">自动前缀检查如何工作</h4>
<p>你可以只在静态内容末尾使用一个缓存断点，系统会自动找到先前请求已经写入缓存的最长前缀。理解其工作方式有助于优化缓存策略。</p>
<p><strong>三条核心原则：</strong></p>
<ol>
<li>
<p><strong>缓存写入只发生在你的断点处。</strong> 用 <code>cache_control</code> 标记一个块只会写入恰好一条缓存条目：以该块结尾的前缀的哈希。系统不会为任何更早的位置写入条目。因为哈希是累积的，覆盖直到并包括断点的全部内容，所以更改断点处或断点之前的任何块都会在下一次请求时产生不同的哈希。</p>
</li>
<li>
<p><strong>缓存读取会向后查找先前请求写入的条目。</strong> 每次请求时，系统会在你的断点处计算前缀哈希并检查是否有匹配的缓存条目。如果不存在，它会一次向后走一个块，检查每个更早位置的前缀哈希是否匹配缓存中已有的内容。它查找的是先前的写入，而不是稳定内容。</p>
</li>
<li>
<p><strong>回看窗口为 20 块。</strong> 每个断点系统最多检查 20 个位置，断点本身计为第一个。如果系统在该窗口内找不到匹配条目，检查即停止（若存在下一个显式缓存断点，则从该断点继续）。在 Claude API 上，连续的 <code>tool_use</code> 块计为一个位置，连续的 <code>tool_result</code> 块也是如此，因此一轮中有许多并行工具调用本身不会把先前请求的条目挤出窗口。</p>
</li>
</ol>
<p><strong>示例：增长中的对话里的回看</strong></p>
<p>你每轮追加新块，并在每个请求的最后一个块上设置 <code>cache_control</code>：</p>
<ul>
<li><strong>第 1 轮：</strong> 10 个块，断点在第 10 块。不存在先前的缓存条目。系统在第 10 块写入一条条目。</li>
<li><strong>第 2 轮：</strong> 15 个块，断点在第 15 块。第 15 块没有条目，因此系统回看到第 10 块并找到第 1 轮的条目。在第 10 块缓存命中；系统只重新处理第 11 到第 15 块，并在第 15 块写入新条目。</li>
<li><strong>第 3 轮：</strong> 35 个块，断点在第 35 块。系统检查 20 个位置（第 35 到第 16 块）且什么也没找到。第 2 轮在第 15 块的条目刚好在窗口外一个位置，因此没有缓存命中。在第 15 块添加第二个断点会在那里开启第二个回看窗口，从而找到第 2 轮的条目。</li>
</ul>
<p><strong>常见错误：把断点放在每次请求都会变化的内容上</strong></p>
<p>你的 prompt 有一大段静态系统上下文（第 1 到第 5 块），后面跟着一个每请求都会出现的块，其中包含时间戳和用户消息（第 6 块）。你在第 6 块上设置 <code>cache_control</code>：</p>
<ul>
<li><strong>请求 1：</strong> 在第 6 块缓存写入。哈希包含时间戳。</li>
<li><strong>请求 2：</strong> 时间戳不同，因此第 6 块的前缀哈希不同。回看走过第 5、4、3、2 和 1 块，但系统从未在这些位置写入过条目。没有缓存命中。你每次请求都要为一次全新的缓存写入付费，并且永远得不到读取。</li>
</ul>
<p>回看不会去发现断点之前的稳定内容并缓存它。它查找的是先前请求已经写入的条目，而写入只发生在断点处。把 <code>cache_control</code> 移到第 5 块——跨请求保持不变的最后一块——之后每个后续请求都会读取该缓存前缀。<a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#automatic-caching">自动缓存</a>会落入同样的陷阱：它把断点放在最后一个可缓存块上，而在这种结构中该块每次请求都会变化，因此应改在第 5 块使用显式缓存断点。</p>
<p><strong>关键要点：</strong> 将 <code>cache_control</code> 放在你希望共享缓存的那些请求之间前缀完全相同的最后一个块上。在增长中的对话里，只要每轮新增少于 20 个块，最后一个块就可以：更早的内容从不变化，因此下一次请求的回看能找到先前的写入。对于带有变化后缀（时间戳、每请求上下文、传入消息）的 prompt，把断点放在静态前缀的末尾，而不是放在变化的块上。</p>
<h4 id="何时使用多个断点">何时使用多个断点</h4>
<p>如果你希望做到以下几点，最多可以定义 4 个缓存断点：</p>
<ul>
<li>缓存以不同频率变化的不同区段（例如，工具很少变化，但上下文每天更新）</li>
<li>更精细地控制究竟缓存哪些内容</li>
<li>当增长中的对话把你的断点推到距上次缓存写入 20 个或更多块时，仍能确保缓存命中</li>
</ul>
<Note>
  **重要限制：** 回看只能找到更早请求已经写入的条目。如果增长中的对话把你的断点推到距上次写入 20 个或更多块，回看窗口就会错过它。从一开始就在更靠近该位置处添加第二个断点，以便在你需要之前就在那里累积一次写入。
</Note>
<h3 id="理解缓存断点的成本">理解缓存断点的成本</h3>
<p><strong>缓存断点本身不会增加任何成本。</strong> 你只需为以下项付费：</p>
<ul>
<li><strong>缓存写入：</strong> 当新内容写入缓存时（5 分钟 TTL 比基础输入 token 贵 25%）</li>
<li><strong>缓存读取：</strong> 当使用缓存内容时（基础输入 token 价格的 10%，或在 Claude Fable 5.1 和 Claude Mythos 5.1 上为 2.5%）</li>
<li><strong>常规输入 token：</strong> 任何未缓存的内容</li>
</ul>
<p>添加更多 <code>cache_control</code> 断点不会增加成本——你仍然根据实际被缓存和读取的内容支付相同金额。断点让你可以控制哪些区段能被独立缓存。</p>
<hr>
<h2 id="缓存策略与注意事项">缓存策略与注意事项</h2>
<h3 id="缓存限制">缓存限制</h3>
<p>在 Claude API、<a href="https://platform.claude.com/docs/en/build-with-claude/claude-platform-on-aws">Claude Platform on AWS</a>、<a href="https://platform.claude.com/docs/en/build-with-claude/claude-on-vertex-ai">Google Cloud</a> 和 <a href="https://platform.claude.com/docs/en/build-with-claude/claude-in-microsoft-foundry">Microsoft Foundry</a> 上，可缓存 prompt 的最短长度为：</p>
<ul>
<li>Claude Fable 5.1、Claude Mythos 5.1、Claude Opus 5、Claude Fable 5 和 <a href="https://anthropic.com/glasswing">Claude Mythos 5</a> 为 512 tokens</li>
<li><a href="https://anthropic.com/glasswing">Claude Mythos Preview</a> 和 Claude Opus 4.7 为 2,048 tokens</li>
<li>Claude Opus 4.6 和 Claude Opus 4.5 为 4,096 tokens</li>
<li>Claude Opus 4.8、Claude Sonnet 5、Claude Sonnet 4.6、Claude Sonnet 4.5、Claude Opus 4.1（<a href="https://platform.claude.com/docs/en/about-claude/model-deprecations">已退役，Bedrock 和 Google Cloud 除外</a>）、Claude Opus 4（<a href="https://platform.claude.com/docs/en/about-claude/model-deprecations">已退役，Google Cloud 除外</a>）和 Claude Sonnet 4（<a href="https://platform.claude.com/docs/en/about-claude/model-deprecations">已退役，Bedrock 和 Google Cloud 除外</a>）为 1,024 tokens</li>
<li>Claude Haiku 4.5 为 4,096 tokens</li>
<li>Claude Haiku 3.5（<a href="https://platform.claude.com/docs/en/about-claude/model-deprecations">已退役，Bedrock 和 Google Cloud 除外</a>）为 2,048 tokens</li>
</ul>
<p>这些下限适用于每个模型可用的所有平台。</p>
<p>更短的 prompt 即使标有 <code>cache_control</code> 也无法缓存。任何请求缓存少于该数量 token 的内容都会在不缓存的情况下处理，且不会返回错误。要验证 prompt 是否被缓存，请检查<a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#tracking-cache-performance">响应 usage 字段</a>：如果 <code>cache_creation_input_tokens</code> 和 <code>cache_read_input_tokens</code> 均为 0，则该 prompt 未被缓存（很可能是因为它未达到最短长度要求）。</p>
<p>如果你的 prompt 刚好略低于所用模型和平台的下限，扩展被缓存内容以达到阈值通常是值得的。缓存读取的成本显著低于未缓存的输入 token，因此达到下限可以降低频繁复用 prompt 的成本。</p>
<Note>
  [Bedrock](https://platform.claude.com/docs/en/build-with-claude/claude-in-amazon-bedrock) 是 AWS 运营的平台。在 Bedrock 上，请参阅 [Bedrock prompt caching documentation](https://docs.aws.amazon.com/bedrock/latest/userguide/prompt-caching.html)，了解适用的各模型下限、失败行为以及 usage 字段名称。
</Note>
<p>对于并发请求，请注意缓存条目只有在第一次响应开始之后才可用。如果并行请求需要缓存命中，请在发送后续请求之前等待第一次响应。</p>
<p>目前，&ldquo;ephemeral&rdquo; 是唯一受支持的缓存类型，默认生命周期为 5 分钟。</p>
<h3 id="哪些内容可以缓存">哪些内容可以缓存</h3>
<p>请求中的大多数块都可以缓存。这包括：</p>
<ul>
<li>工具：<code>tools</code> 数组中的工具定义</li>
<li>系统消息：<code>system</code> 数组中的内容块</li>
<li>文本消息：<code>messages.content</code> 数组中的内容块，适用于 user 和 assistant 两轮</li>
<li>图像和文档：<code>messages.content</code> 数组中的内容块，位于 user 轮</li>
<li>工具使用和工具结果：<code>messages.content</code> 数组中的内容块，适用于 user 和 assistant 两轮</li>
</ul>
<p>这些元素都可以缓存，既可以自动缓存，也可以用 <code>cache_control</code> 标记。</p>
<h3 id="哪些内容不能缓存">哪些内容不能缓存</h3>
<p>虽然大多数请求块可以缓存，但也有一些例外：</p>
<ul>
<li>
<p>Thinking 块不能用 <code>cache_control</code> 直接缓存。但是，当 thinking 块出现在先前的 assistant 轮中时，它们可以与其他内容一起被缓存。以这种方式缓存时，从缓存读取时它们会计入输入 token。</p>
</li>
<li>
<p>子内容块（例如 <a href="https://platform.claude.com/docs/en/build-with-claude/citations">citations</a>）本身不能直接缓存。应改为缓存顶层块。</p>
<p>对于 citations，作为 citations 源材料的顶层文档内容块可以缓存。这样你可以通过缓存 citations 将引用的文档，有效地将 Prompt Caching 与 citations 一起使用。</p>
</li>
<li>
<p>空文本块不能缓存。</p>
</li>
</ul>
<h3 id="什么会使缓存失效">什么会使缓存失效</h3>
<p>对已缓存内容的修改会使部分或全部缓存失效。</p>
<p>如<a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#structuring-your-prompt">组织你的 prompt</a> 所述，缓存遵循层级：<code>tools</code> → <code>system</code> → <code>messages</code>。每一层的变更会使该层及之后的所有层失效。</p>
<p>下表显示不同类型的变更会使缓存的哪些部分失效。✘ 表示缓存失效，✓ 表示缓存仍然有效。</p>
<table>
	<thead>
			<tr>
					<th>变更内容</th>
					<th>Tools 缓存</th>
					<th>System 缓存</th>
					<th>Messages 缓存</th>
					<th>影响</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><strong>工具定义</strong></td>
					<td>✘</td>
					<td>✘</td>
					<td>✘</td>
					<td>修改工具定义（名称、描述、参数）会使整个缓存失效</td>
			</tr>
			<tr>
					<td><strong>Web search 开关</strong></td>
					<td>✓</td>
					<td>✘</td>
					<td>✘</td>
					<td>启用/禁用 web search 会修改 system prompt</td>
			</tr>
			<tr>
					<td><strong>Citations 开关</strong></td>
					<td>✓</td>
					<td>✘</td>
					<td>✘</td>
					<td>启用/禁用 citations 会修改 system prompt</td>
			</tr>
			<tr>
					<td><strong>速度设置</strong></td>
					<td>✓</td>
					<td>✘</td>
					<td>✘</td>
					<td>在 <a href="https://platform.claude.com/docs/en/build-with-claude/fast-mode"><code>speed: &quot;fast&quot;</code> 与标准速度</a> 之间切换会使 system 和 message 缓存失效</td>
			</tr>
			<tr>
					<td><strong>Tool choice</strong></td>
					<td>✓</td>
					<td>✓</td>
					<td>✘</td>
					<td>对 <code>tool_choice</code> 参数的更改只影响 message 块</td>
			</tr>
			<tr>
					<td><strong>图像</strong></td>
					<td>✓</td>
					<td>✓</td>
					<td>✘</td>
					<td>在 prompt 任意位置添加/移除图像会影响 message 块</td>
			</tr>
			<tr>
					<td><strong>Thinking 参数</strong></td>
					<td>因模型而异</td>
					<td>因模型而异</td>
					<td>✘</td>
					<td>thinking 配置（模式，以及 extended mode 中的 <code>budget_tokens</code>）会被渲染进 prompt，因此更改它总会使 message 块失效；在把该配置渲染在它们之前的模型上，tool 和 system 缓存也会失效。参见 <a href="https://platform.claude.com/docs/en/build-with-claude/thinking#thinking-and-prompt-caching">Thinking and prompt caching</a>。</td>
			</tr>
			<tr>
					<td><strong>Effort 设置</strong></td>
					<td>因模型而异</td>
					<td>因模型而异</td>
					<td>✘</td>
					<td>更改 <a href="https://platform.claude.com/docs/en/build-with-claude/effort"><code>output_config.effort</code></a> 值总会使 message 块失效，对 tool 和 system 缓存的模型相关影响与 thinking 参数相同。将 effort 显式设为模型默认值等价于省略它，不会使缓存失效。在支持<a href="https://platform.claude.com/docs/en/build-with-claude/effort#change-effort-mid-conversation-beta">逐条消息 effort</a> 的模型上，通过 <code>messages</code> 内 <code>role: &quot;system&quot;</code> 消息携带的 effort 变更会保持缓存前缀完好。</td>
			</tr>
			<tr>
					<td><strong>传入 extended thinking 请求的非工具结果</strong></td>
					<td>✓</td>
					<td>✓</td>
					<td>因模型而异</td>
					<td>在 Opus 4.5+ 和 Sonnet 4.6+ 上，thinking 块默认被保留，因此缓存仍然有效（✓）。在更早的 Opus/Sonnet 模型以及所有 Haiku 模型上，所有先前已缓存的 thinking 块会从上下文中剥离，跟随这些 thinking 块的任何消息也会从缓存中移除（✘）。更多详情见 <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#caching-with-thinking-blocks">Caching with thinking blocks</a>。</td>
			</tr>
			<tr>
					<td><strong>被丢弃的 thinking 块</strong></td>
					<td>✓</td>
					<td>✓</td>
					<td>✘</td>
					<td>当 API 丢弃一个在该请求上未被<a href="https://platform.claude.com/docs/en/build-with-claude/thinking#preserved-thinking">保留</a> 的 Claude Fable 5.1 或 Claude Mythos 5.1 thinking 块时（例如，你把它重放到更早的模型），该请求上从该块位置起的缓存前缀会发生变化。接收模型能够读取、且原样传回的块会保持缓存完好。</td>
			</tr>
	</tbody>
</table>
<Note>
  在 Claude Fable 5.1、Claude Mythos 5.1、Claude Fable 5、[Claude Mythos 5](https://anthropic.com/glasswing)、Claude Opus 4.8 和 Claude Opus 5 上，你可以在对话中途添加新的系统指令，而不会使 system 或 message 缓存失效。向 `messages` 追加一条 `{"role": "system"}` 消息，而不是编辑顶层 `system` 字段，这样缓存前缀保持不变。此功能在 Claude Sonnet 5 上不可用。请改用顶层 `system` 字段。参见 [Mid-conversation system messages](https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages)。
</Note>
<h3 id="跟踪缓存表现">跟踪缓存表现</h3>
<p>使用 API 响应中 <code>usage</code> 内的这些字段监控缓存表现（若使用 <a href="https://platform.claude.com/docs/en/build-with-claude/streaming">streaming</a>，则在 <code>message_start</code> 事件中）：</p>
<ul>
<li><code>cache_creation_input_tokens</code>：创建新条目时写入缓存的 token 数。</li>
<li><code>cache_read_input_tokens</code>：本次请求从缓存检索的 token 数。</li>
<li><code>input_tokens</code>：既未从缓存读取、也未用于创建缓存的输入 token 数（即最后一个缓存断点之后的 token）。</li>
</ul>
<Note>
  **理解 token 分解**
<p><code>input_tokens</code> 字段只表示请求中<strong>最后一个缓存断点之后</strong>的 token——并非你发送的全部输入 token。</p>
<p>要计算总输入 token：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">total_input_tokens = cache_read_input_tokens + cache_creation_input_tokens + input_tokens
</span></span></code></pre></td></tr></table>
</div>
</div><p><strong>空间解释：</strong></p>
<ul>
<li><code>cache_read_input_tokens</code> = 断点之前已经缓存的 token（读取）</li>
<li><code>cache_creation_input_tokens</code> = 断点之前正在被缓存的 token（写入）</li>
<li><code>input_tokens</code> = 最后一个断点之后的 token（不符合缓存条件）</li>
</ul>
<p><strong>示例：</strong> 如果你有一个请求包含 100,000 tokens 的已缓存内容（从缓存读取）、0 tokens 的正在被缓存的新内容，以及用户消息中的 50 tokens（在缓存断点之后）：</p>
<ul>
<li><code>cache_read_input_tokens</code>: 100,000</li>
<li><code>cache_creation_input_tokens</code>: 0</li>
<li><code>input_tokens</code>: 50</li>
<li><strong>处理的总输入 token：</strong> 100,050 tokens</li>
</ul>
<p>这对于理解成本和速率限制都很重要，因为有效使用缓存时，<code>input_tokens</code> 通常会远小于你的总输入。
</Note></p>
<h3 id="使用-thinking-块进行缓存">使用 thinking 块进行缓存</h3>
<p>将 <a href="https://platform.claude.com/docs/en/build-with-claude/thinking">thinking</a> 与 Prompt Caching 一起使用时，thinking 块有特殊行为：</p>
<p><strong>与其他内容一起自动缓存：</strong> 虽然 thinking 块不能用 <code>cache_control</code> 显式标记，但当你带着 tool results 发起后续 API 调用时，它们会作为请求内容的一部分被缓存。这在 tool use 期间很常见：你把 thinking 块传回去以继续对话。</p>
<p><strong>输入 token 计数：</strong> 当 thinking 块从缓存读取时，它们会计入 usage 指标中的输入 token。这对成本计算和 token 预算很重要。</p>
<p><strong>缓存失效模式：</strong></p>
<ul>
<li>当仅以 user messages 提供 tool results 时，缓存仍然有效</li>
<li>在 Opus 4.5+ 和 Sonnet 4.6+ 上，即使添加了非 tool-result 的用户内容，thinking 块默认仍被保留，因此缓存仍然有效</li>
<li>在更早的 Opus/Sonnet 模型以及所有 Haiku 模型上，添加非 tool-result 的用户内容会使缓存失效，导致所有先前的 thinking 块从上下文中剥离</li>
<li>即使没有显式的 <code>cache_control</code> 标记，也会出现这种缓存行为</li>
</ul>
<p>关于缓存失效的更多详情，请参阅<a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#what-invalidates-the-cache">什么会使缓存失效</a>。</p>
<p><strong>结合 tool use 的示例：</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">Request 1: User: &#34;What&#39;s the weather in Paris?&#34;
</span></span><span class="line"><span class="cl">Response: [thinking_block_1] + [tool_use block 1]
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">Request 2:
</span></span><span class="line"><span class="cl">User: [&#34;What&#39;s the weather in Paris?&#34;],
</span></span><span class="line"><span class="cl">Assistant: [thinking_block_1] + [tool_use block 1],
</span></span><span class="line"><span class="cl">User: [tool_result_1, cache=True]
</span></span><span class="line"><span class="cl">Response: [thinking_block_2] + [text block 2]
</span></span><span class="line"><span class="cl"># Request 2 caches its request content (not the response)
</span></span><span class="line"><span class="cl"># The cache includes: user message, thinking_block_1, tool_use block 1, and tool_result_1
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">Request 3:
</span></span><span class="line"><span class="cl">User: [&#34;What&#39;s the weather in Paris?&#34;],
</span></span><span class="line"><span class="cl">Assistant: [thinking_block_1] + [tool_use block 1],
</span></span><span class="line"><span class="cl">User: [tool_result_1, cache=True],
</span></span><span class="line"><span class="cl">Assistant: [thinking_block_2] + [text block 2],
</span></span><span class="line"><span class="cl">User: [Text response, cache=True]
</span></span><span class="line"><span class="cl"># On earlier Opus/Sonnet and all Haiku models, non-tool-result user block causes prior thinking blocks to be stripped; on Opus 4.5+/Sonnet 4.6+ they are kept
</span></span></code></pre></td></tr></table>
</div>
</div><p>在更早的 Opus/Sonnet 模型以及所有 Haiku 模型上，此时所有先前的 thinking 块都会从上下文中移除。在 Opus 4.5+ 和 Sonnet 4.6+ 上，先前的 thinking 块默认被保留，并仍是缓存前缀的一部分。</p>
<p>更详细的信息请参阅 <a href="https://platform.claude.com/docs/en/build-with-claude/thinking#thinking-and-prompt-caching">Thinking and prompt caching</a>。</p>
<h3 id="缓存存储与共享">缓存存储与共享</h3>
<Warning>
  Prompt Caching 使用 [workspace](https://platform.claude.com/docs/en/manage-claude/workspaces) 级隔离。缓存在每个 workspace 之间隔离，确保同一组织内各 workspace 之间的数据分离。这适用于 Claude API、Claude Platform on AWS 和 Microsoft Foundry；Bedrock 和 Google Cloud 保持组织级缓存隔离。如果你使用多个 workspace，请审视缓存策略以考虑这一差异。
</Warning>
<ul>
<li>
<p><strong>组织和 workspace 隔离：</strong> 缓存在组织之间隔离。不同组织永远不会共享缓存，即使它们使用相同的 prompt。在 Claude API、Claude Platform on AWS 和 Microsoft Foundry 上，缓存在组织内也按 workspace 隔离；Bedrock 和 Google Cloud 仅使用组织级隔离。</p>
</li>
<li>
<p><strong>精确匹配：</strong> 缓存命中要求 prompt 片段 100% 相同，包括直到并包括用 cache control 标记的块在内的所有文本和图像。</p>
</li>
<li>
<p><strong>输出 token 生成：</strong> Prompt Caching 对输出 token 生成没有影响。你收到的响应与未使用 Prompt Caching 时完全相同。</p>
</li>
</ul>
<h3 id="有效缓存的最佳实践">有效缓存的最佳实践</h3>
<p>要优化 Prompt Caching 表现：</p>
<ul>
<li>对于多轮对话，从<a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#automatic-caching">自动缓存</a>开始。它会自动处理断点管理。</li>
<li>当你需要以不同变化频率缓存不同区段时，使用<a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#explicit-cache-breakpoints">显式块级断点</a>。</li>
<li>缓存稳定、可复用的内容，例如系统指令、背景信息、大型上下文或常用工具定义。</li>
<li>将缓存内容放在 prompt 开头以获得最佳表现。</li>
<li>有策略地使用缓存断点，以分隔不同的可缓存前缀区段。</li>
<li>将断点放在跨请求保持相同的最后一个块上。对于带有静态前缀和变化后缀（时间戳、每请求上下文、传入消息）的 prompt，那就是前缀的末尾，而不是变化的块。</li>
<li>定期分析缓存命中率并根据需要调整策略。</li>
</ul>
<h3 id="针对不同用例进行优化">针对不同用例进行优化</h3>
<p>根据你的场景调整 Prompt Caching 策略：</p>
<ul>
<li>对话式 agent：降低长对话的成本和延迟，尤其是带有长指令或上传文档的对话。</li>
<li>编程助手：通过在 prompt 中保留相关区段或代码库的摘要版本，改善自动补全和代码库问答。</li>
<li>大型文档处理：在 prompt 中纳入包括图像在内的完整长篇材料，而不增加响应延迟。</li>
<li>详尽指令集：共享详尽的指令、流程和示例列表，以微调 Claude 的响应。开发者通常会在 prompt 中放一两个示例，但借助 Prompt Caching，你可以通过包含 20+ 个高质量答案的多样化示例获得更好的表现。</li>
<li>智能体工具使用：增强涉及多次工具调用和迭代代码更改的场景表现，其中每一步通常都需要一次新的 API 调用。</li>
<li>与书籍、论文、文档、播客转录稿及其他长篇内容对话：通过把整份文档嵌入 prompt，让用户向其提问，使任何知识库变得可用。</li>
</ul>
<h3 id="排查常见问题">排查常见问题</h3>
<p>如果遇到意外行为：</p>
<Tip>
  [Cache diagnostics](https://platform.claude.com/docs/en/build-with-claude/cache-diagnostics)（beta）让 API 比较连续请求并报告 prompt 前缀究竟在何处发生分歧，从而自动处理本列表中的许多步骤。
</Tip>
<ul>
<li>确保跨调用的缓存区段完全相同。对于显式缓存断点，验证 <code>cache_control</code> 标记位于相同位置</li>
<li>检查调用是在缓存生命周期内发出的（默认为 5 分钟）</li>
<li>验证 <code>tool_choice</code>、图像使用、thinking 配置和 <code>output_config.effort</code> 在调用之间保持一致</li>
<li>确认你至少缓存了所用模型和平台要求的最低 token 数（参见<a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#cache-limitations">缓存限制</a>）</li>
<li>确认断点位于跨请求保持相同的块上。缓存写入只发生在断点处，如果该块发生变化（时间戳、每请求上下文、传入消息），前缀哈希永远不会匹配。回看不会发现断点之前的稳定内容；它只查找更早请求在其自身断点处写入的条目</li>
<li>验证 <code>tool_use</code> 内容块中的键具有稳定顺序，因为某些语言（例如 Swift、Go）在 JSON 转换期间会随机化键顺序，从而破坏缓存</li>
<li>使用 <a href="https://platform.claude.com/docs/en/build-with-claude/cache-diagnostics">cache diagnostics</a> 让 API 比较连续请求并报告 prompt 的哪一部分发生了分歧</li>
</ul>
<Note>
  对 `tool_choice` 的更改，或 prompt 任意位置图像的存在/缺失，都会使缓存失效，需要创建新的缓存条目。关于缓存失效的更多详情，请参阅[什么会使缓存失效](https://platform.claude.com/docs/en/build-with-claude/prompt-caching#what-invalidates-the-cache)。
</Note>
<hr>
<h2 id="1-小时缓存时长">1 小时缓存时长</h2>
<p>如果你觉得 5 分钟太短，Anthropic 还提供 1 小时缓存时长，<a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#pricing">需额外付费</a>。</p>
<Note>
  1 小时缓存时长在 Claude API、[Amazon Bedrock](https://platform.claude.com/docs/en/build-with-claude/claude-in-amazon-bedrock)、[Amazon Bedrock (Opus 4.6 and earlier)](https://platform.claude.com/docs/en/build-with-claude/claude-on-amazon-bedrock-legacy)、[Claude Platform on AWS](https://platform.claude.com/docs/en/build-with-claude/claude-platform-on-aws)、[Google Cloud](https://platform.claude.com/docs/en/build-with-claude/claude-on-vertex-ai) 和 [Microsoft Foundry](https://platform.claude.com/docs/en/build-with-claude/claude-in-microsoft-foundry) 上可用。
</Note>
<p>要使用延长缓存，请像这样在 <code>cache_control</code> 定义中包含 <code>ttl</code>：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="s2">&#34;cache_control&#34;</span><span class="err">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;ephemeral&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;ttl&#34;</span><span class="p">:</span> <span class="s2">&#34;1h&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>响应包含如下详细缓存信息：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;usage&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;input_tokens&#34;</span><span class="p">:</span> <span class="mi">2048</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;cache_read_input_tokens&#34;</span><span class="p">:</span> <span class="mi">1800</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;cache_creation_input_tokens&#34;</span><span class="p">:</span> <span class="mi">248</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;output_tokens&#34;</span><span class="p">:</span> <span class="mi">503</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;cache_creation&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;ephemeral_5m_input_tokens&#34;</span><span class="p">:</span> <span class="mi">148</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;ephemeral_1h_input_tokens&#34;</span><span class="p">:</span> <span class="mi">100</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>请注意，当前的 <code>cache_creation_input_tokens</code> 字段等于 <code>cache_creation</code> 对象中各值之和。</p>
<p>如果你在使用 web search 等 server tools 时看到并未请求的 <code>ephemeral_5m_input_tokens</code> 写入，请参阅 <a href="https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-use-with-prompt-caching#server-tool-results-are-cached-automatically">Tool use with prompt caching</a>。</p>
<h3 id="何时使用-1-小时缓存">何时使用 1 小时缓存</h3>
<p>如果你有按固定节奏使用的 prompt（也就是使用频率高于每 5 分钟一次的 system prompts），请继续使用 5 分钟缓存，因为它会继续刷新且不产生额外费用。</p>
<p>1 小时缓存最适合以下场景：</p>
<ul>
<li>当你的 prompt 使用频率可能低于每 5 分钟一次，但高于每小时一次。例如，某个 agentic side-agent 会花费超过 5 分钟，或者在存储与用户的长聊天对话时，你通常预期该用户可能不会在接下来 5 分钟内回复。</li>
<li>当延迟很重要，且后续 prompt 可能在 5 分钟之后才发送。</li>
<li>当你想改善速率限制利用率时，因为缓存命中不会从速率限制中扣减。</li>
</ul>
<Note>
  5 分钟缓存和 1 小时缓存在延迟方面表现相同。对于长文档，你通常会看到更好的首 token 时间（TTFT）。
</Note>
<h3 id="混合不同-ttl">混合不同 TTL</h3>
<p>你可以在同一请求中同时使用 1 小时和 5 分钟的 cache controls，但有一个重要约束：TTL 更长的缓存条目必须出现在更短 TTL 之前（也就是说，1 小时缓存条目必须出现在任何 5 分钟缓存条目之前）。</p>
<p>混合 TTL 时，API 会在你的 prompt 中确定三个计费位置：</p>
<ol>
<li>位置 <code>A</code>：最高缓存命中处的 token 数（若无命中则为 0）。</li>
<li>位置 <code>B</code>：<code>A</code> 之后最高的 1 小时 <code>cache_control</code> 块处的 token 数（若不存在则等于 <code>A</code>）。</li>
<li>位置 <code>C</code>：最后一个 <code>cache_control</code> 块处的 token 数。</li>
</ol>
<Note>
  如果 `B` 或 `C` 大于 `A`，则必然是缓存未命中，因为 `A` 是最高缓存命中。
</Note>
<p>你将被收取：</p>
<ol>
<li><code>A</code> 的缓存读取 token。</li>
<li><code>(B - A)</code> 的 1 小时缓存写入 token。</li>
<li><code>(C - B)</code> 的 5 分钟缓存写入 token。</li>
</ol>
<p>下面是三个示例。图中描绘了 3 个请求的输入 token，每个请求具有不同的缓存命中和缓存未命中。因此每个请求都有不同的计算定价，显示在彩色框中。 <img alt="混合 TTL 示意图" loading="lazy" src="https://platform.claude.com/docs/images/prompt-cache-mixed-ttl.svg"></p>
<hr>
<h2 id="预热缓存">预热缓存</h2>
<p>缓存预热让你在用户触发真实请求之前，把 system prompt 或工具定义加载进 prompt 缓存。这消除了首次用户交互时的缓存未命中延迟惩罚，从而降低对延迟敏感的应用的首 token 时间（TTFT）。</p>
<h3 id="工作原理">工作原理</h3>
<p>在请求中设置 <code>max_tokens: 0</code>。API 将你的 prompt 读入模型，并在任何 <code>cache_control</code> 断点处写入缓存，然后立即返回而不生成任何输出。响应包含空的 <code>content</code> 数组、<code>stop_reason: &quot;max_tokens&quot;</code>，以及完整填充的 <code>usage</code> 块。</p>
<p>将 <code>cache_control</code> 断点放在与后续请求共享的最后一个块上（通常是你的 system prompt 或工具定义），而不是放在占位用户消息上。否则缓存条目会以占位符为键，后续请求将无法命中它。也要使用与后续请求相同的 thinking 配置和 <code>output_config.effort</code>：这些值会被渲染进 prompt（参见<a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#what-invalidates-the-cache">什么会使缓存失效</a>），因此使用不同配置的预热可能写入一条真实流量永远命中不到的条目。这意味着应使用<a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#explicit-cache-breakpoints">显式缓存断点</a>而不是<a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#automatic-caching">自动缓存</a>，因为自动缓存会把断点放在最后一个块上，而这里最后一个块就是占位符。占位用户消息可以是任何含非空白内容的字符串（此处示例使用 <code>&quot;warmup&quot;</code>）；其内容会被读入模型但永远不会被回答。</p>
<Note>
  如果前缀尚未被缓存，预热请求会产生**缓存写入**费用，与任何其他请求相同。检查响应中的 `usage.cache_creation_input_tokens` 以确认发生了写入。输出 token 按零计费。
</Note>
<CodeGroup>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">client</span> <span class="o">=</span> <span class="n">anthropic</span><span class="o">.</span><span class="n">Anthropic</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Fire this before users arrive to warm the shared system-prompt cache.</span>
</span></span><span class="line"><span class="cl"><span class="n">prewarm</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">messages</span><span class="o">.</span><span class="n">create</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">model</span><span class="o">=</span><span class="s2">&#34;claude-opus-5&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">max_tokens</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">system</span><span class="o">=</span><span class="p">[</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;text&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;text&#34;</span><span class="p">:</span> <span class="s2">&#34;You are an expert software engineer with deep knowledge of distributed systems...&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;cache_control&#34;</span><span class="p">:</span> <span class="p">{</span><span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;ephemeral&#34;</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">],</span>
</span></span><span class="line"><span class="cl">    <span class="n">messages</span><span class="o">=</span><span class="p">[{</span><span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span> <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;warmup&#34;</span><span class="p">}],</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">prewarm</span><span class="o">.</span><span class="n">stop_reason</span><span class="p">)</span>  <span class="c1"># &#34;max_tokens&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">prewarm</span><span class="o">.</span><span class="n">content</span><span class="p">)</span>  <span class="c1"># []</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">prewarm</span><span class="o">.</span><span class="n">usage</span><span class="p">)</span>
</span></span></code></pre></td></tr></table>
</div>
</div></CodeGroup>
<p>API 返回空的 <code>content</code> 数组：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;id&#34;</span><span class="p">:</span> <span class="s2">&#34;msg_01XFDUDYJgAACzvnptvVoYEL&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;message&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;assistant&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;content&#34;</span><span class="p">:</span> <span class="p">[],</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;model&#34;</span><span class="p">:</span> <span class="s2">&#34;claude-opus-5&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;stop_reason&#34;</span><span class="p">:</span> <span class="s2">&#34;max_tokens&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;stop_sequence&#34;</span><span class="p">:</span> <span class="kc">null</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;usage&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;input_tokens&#34;</span><span class="p">:</span> <span class="mi">8</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;cache_creation_input_tokens&#34;</span><span class="p">:</span> <span class="mi">5120</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;cache_read_input_tokens&#34;</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;cache_creation&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;ephemeral_5m_input_tokens&#34;</span><span class="p">:</span> <span class="mi">5120</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;ephemeral_1h_input_tokens&#34;</span><span class="p">:</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;iterations&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">      <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;input_tokens&#34;</span><span class="p">:</span> <span class="mi">8</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;output_tokens&#34;</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;cache_read_input_tokens&#34;</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;cache_creation_input_tokens&#34;</span><span class="p">:</span> <span class="mi">5120</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;cache_creation&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;ephemeral_5m_input_tokens&#34;</span><span class="p">:</span> <span class="mi">5120</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;ephemeral_1h_input_tokens&#34;</span><span class="p">:</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl">        <span class="p">},</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;message&#34;</span>
</span></span><span class="line"><span class="cl">      <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">],</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;output_tokens&#34;</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;service_tier&#34;</span><span class="p">:</span> <span class="s2">&#34;standard&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;inference_geo&#34;</span><span class="p">:</span> <span class="s2">&#34;global&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="典型用法模式">典型用法模式</h3>
<p>在应用启动时（或按计划间隔）发出一次预热请求，然后在预热完成后发送真实用户请求：</p>
<CodeGroup>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">client</span> <span class="o">=</span> <span class="n">anthropic</span><span class="o">.</span><span class="n">Anthropic</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">SYSTEM_PROMPT</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;text&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;text&#34;</span><span class="p">:</span> <span class="s2">&#34;You are an expert software engineer with deep knowledge of distributed systems...&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;cache_control&#34;</span><span class="p">:</span> <span class="p">{</span><span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;ephemeral&#34;</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">prewarm_cache</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;&#34;&#34;Call this at application startup or on a scheduled interval.&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="n">client</span><span class="o">.</span><span class="n">messages</span><span class="o">.</span><span class="n">create</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="n">model</span><span class="o">=</span><span class="s2">&#34;claude-opus-5&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="n">max_tokens</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="n">system</span><span class="o">=</span><span class="n">SYSTEM_PROMPT</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="n">messages</span><span class="o">=</span><span class="p">[{</span><span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span> <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;warmup&#34;</span><span class="p">}],</span>
</span></span><span class="line"><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">respond</span><span class="p">(</span><span class="n">user_message</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">anthropic</span><span class="o">.</span><span class="n">types</span><span class="o">.</span><span class="n">Message</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;&#34;&#34;The real user request; benefits from a warm cache.&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">client</span><span class="o">.</span><span class="n">messages</span><span class="o">.</span><span class="n">create</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="n">model</span><span class="o">=</span><span class="s2">&#34;claude-opus-5&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="n">max_tokens</span><span class="o">=</span><span class="mi">1024</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="n">system</span><span class="o">=</span><span class="n">SYSTEM_PROMPT</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="n">messages</span><span class="o">=</span><span class="p">[{</span><span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span> <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="n">user_message</span><span class="p">}],</span>
</span></span><span class="line"><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Warm the cache before any user traffic arrives.</span>
</span></span><span class="line"><span class="cl"><span class="n">prewarm_cache</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Later, when the user submits a message, the system-prompt prefix is already cached.</span>
</span></span><span class="line"><span class="cl"><span class="n">response</span> <span class="o">=</span> <span class="n">respond</span><span class="p">(</span><span class="s2">&#34;How do I implement a binary search tree?&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">block</span> <span class="ow">in</span> <span class="n">response</span><span class="o">.</span><span class="n">content</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="n">block</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="s2">&#34;text&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="n">block</span><span class="o">.</span><span class="n">text</span><span class="p">)</span>
</span></span></code></pre></td></tr></table>
</div>
</div></CodeGroup>
<p>请记住缓存 TTL 仍然适用。对于默认的 5 分钟缓存，至少每 5 分钟发送一次新的预热请求以保持缓存温热。如果用户请求之间的间隔更长，请改用 <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#1-hour-cache-duration">1 小时缓存时长</a>。</p>
<h3 id="限制">限制</h3>
<p>如果设置了以下任何一项，<code>max_tokens: 0</code> 请求会被拒绝并返回 <code>invalid_request_error</code>，因为每一项都意味着需要零 token 预算无法产生的输出：</p>
<ul>
<li><code>stream: true</code></li>
<li><a href="https://platform.claude.com/docs/en/build-with-claude/extended-thinking">Extended thinking</a>（<code>thinking.type: &quot;enabled&quot;</code>）</li>
<li><a href="https://platform.claude.com/docs/en/build-with-claude/structured-outputs">Structured outputs</a>（<code>output_config.format</code>）</li>
<li><code>tool_choice</code> 为 <code>{&quot;type&quot;: &quot;tool&quot;, ...}</code> 或 <code>{&quot;type&quot;: &quot;any&quot;}</code></li>
</ul>
<p><code>max_tokens: 0</code> 在 <a href="https://platform.claude.com/docs/en/build-with-claude/batch-processing">Message Batches</a> 请求中也会被拒绝。预热针对的是首 token 时间（TTFT），这不适用于批处理，而且在批处理期间写入的缓存条目很可能在后续请求运行之前就已过期。</p>
<h3 id="替代-max_tokens1-变通方法">替代 max_tokens=1 变通方法</h3>
<p>在 <code>max_tokens: 0</code> 可用之前，一些应用使用 <code>max_tokens: 1</code> 预热调用以达到同样效果。更推荐 <code>max_tokens: 0</code> 方式：不产生任何输出，因此没有需要丢弃的单 token 回复，不产生输出 token 费用，并且请求意图明确。</p>
<hr>
<h2 id="prompt-caching-示例">Prompt Caching 示例</h2>
<p>为帮助你开始使用 Prompt Caching，<a href="https://platform.claude.com/cookbook/misc-prompt-caching">prompt caching cookbook</a> 提供了详细示例和最佳实践。</p>
<p>以下代码片段展示了各种 Prompt Caching 模式。这些示例演示如何在不同场景中实现缓存，帮助你理解该功能的实际应用：</p>
<AccordionGroup>
  <Accordion title="大型上下文缓存示例">
    <CodeGroup>
<pre><code>  ```python Python
  client = anthropic.Anthropic()

  response = client.messages.create(
      model=&quot;claude-opus-5&quot;,
      max_tokens=1024,
      system=[
          {
              &quot;type&quot;: &quot;text&quot;,
              &quot;text&quot;: &quot;You are an AI assistant tasked with analyzing legal documents.&quot;,
          },
          {
              &quot;type&quot;: &quot;text&quot;,
              &quot;text&quot;: &quot;Here is the full text of a complex legal agreement: [Insert full text of a 50-page legal agreement here]&quot;,
              &quot;cache_control&quot;: {&quot;type&quot;: &quot;ephemeral&quot;},
          },
      ],
      messages=[
          {
              &quot;role&quot;: &quot;user&quot;,
              &quot;content&quot;: &quot;What are the key terms and conditions in this agreement?&quot;,
          }
      ],
  )
  print(response.usage.model_dump_json())
  ```

&lt;/CodeGroup&gt;

本示例演示基本的 Prompt Caching 用法：将法律协议全文作为前缀缓存，同时保持用户指令不缓存。

对于第一次请求：

* `input_tokens`：仅用户消息中的 token 数
* `cache_creation_input_tokens`：整个 system message 中的 token 数，包括法律文档
* `cache_read_input_tokens`: 0（第一次请求没有缓存命中）

对于缓存生命周期内的后续请求：

* `input_tokens`：仅用户消息中的 token 数
* `cache_creation_input_tokens`: 0（没有新的缓存创建）
* `cache_read_input_tokens`：整个已缓存 system message 中的 token 数
</code></pre>
  </Accordion>
  <Accordion title="缓存工具定义">
    可以通过在 `tools` 数组的最后一个工具上放置 `cache_control` 来缓存工具定义。在该工具之前（含该工具）定义的所有工具会作为一个前缀被缓存。
<pre><code>```json
{
  &quot;model&quot;: &quot;claude-opus-5&quot;,
  &quot;max_tokens&quot;: 1024,
  &quot;tools&quot;: [
    {
      &quot;name&quot;: &quot;get_weather&quot;,
      &quot;description&quot;: &quot;Get the current weather in a given location&quot;,
      &quot;input_schema&quot;: {
        &quot;type&quot;: &quot;object&quot;,
        &quot;properties&quot;: { &quot;location&quot;: { &quot;type&quot;: &quot;string&quot; } },
        &quot;required&quot;: [&quot;location&quot;]
      }
    },
    {
      &quot;name&quot;: &quot;get_time&quot;,
      &quot;description&quot;: &quot;Get the current time in a given time zone&quot;,
      &quot;input_schema&quot;: {
        &quot;type&quot;: &quot;object&quot;,
        &quot;properties&quot;: { &quot;timezone&quot;: { &quot;type&quot;: &quot;string&quot; } },
        &quot;required&quot;: [&quot;timezone&quot;]
      },
      &quot;cache_control&quot;: { &quot;type&quot;: &quot;ephemeral&quot; }
    }
  ],
  &quot;messages&quot;: [{ &quot;role&quot;: &quot;user&quot;, &quot;content&quot;: &quot;What is the weather and time in New York?&quot; }]
}
```

在第一次请求中，`cache_creation_input_tokens` 反映所有工具定义的 token 数。在缓存生命周期内的后续请求中，这些 token 会出现在 `cache_read_input_tokens` 下。

关于工具定义、`defer_loading` 和缓存失效之间的详细交互，请参阅 [Tool use with prompt caching](https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-use-with-prompt-caching)。
</code></pre>
  </Accordion>
  <Accordion title="继续多轮对话">
    <CodeGroup>
<pre><code>  ```python Python
  client = anthropic.Anthropic()

  response = client.messages.create(
      model=&quot;claude-opus-5&quot;,
      max_tokens=1024,
      system=[
          {
              &quot;type&quot;: &quot;text&quot;,
              &quot;text&quot;: &quot;...long system prompt&quot;,
              &quot;cache_control&quot;: {&quot;type&quot;: &quot;ephemeral&quot;},
          }
      ],
      messages=[
          # ...long conversation so far
          {
              &quot;role&quot;: &quot;user&quot;,
              &quot;content&quot;: [
                  {
                      &quot;type&quot;: &quot;text&quot;,
                      &quot;text&quot;: &quot;Hello, can you tell me more about the solar system?&quot;,
                  }
              ],
          },
          {
              &quot;role&quot;: &quot;assistant&quot;,
              &quot;content&quot;: &quot;Certainly! The solar system is the collection of celestial bodies that orbit our Sun. It consists of eight planets, numerous moons, asteroids, comets, and other objects. The planets, in order from closest to farthest from the Sun, are: Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, and Neptune. Each planet has its own unique characteristics and features. Is there a specific aspect of the solar system you'd like to know more about?&quot;,
          },
          {
              &quot;role&quot;: &quot;user&quot;,
              &quot;content&quot;: [
                  {&quot;type&quot;: &quot;text&quot;, &quot;text&quot;: &quot;Good to know.&quot;},
                  {
                      &quot;type&quot;: &quot;text&quot;,
                      &quot;text&quot;: &quot;Tell me more about Mars.&quot;,
                      &quot;cache_control&quot;: {&quot;type&quot;: &quot;ephemeral&quot;},
                  },
              ],
          },
      ],
  )
  print(response.usage.model_dump_json())
  ```

&lt;/CodeGroup&gt;

本示例演示如何在多轮对话中使用 Prompt Caching。

在每一轮中，最后一条消息的最后一个块会标上 `cache_control`，以便对话可以被增量缓存。系统会自动查找并使用先前已缓存的最长块序列来处理后续消息。也就是说，先前用 `cache_control` 标记过的块之后不再带此标记，但如果在 5 分钟内被命中，它们仍会被视为缓存命中（同时也是一次缓存刷新！）。

此外，请注意 `cache_control` 参数放在了 system message 上。这是为了确保如果它从缓存中被驱逐（超过 5 分钟未被使用之后），会在下一次请求时被重新加入缓存。

这种方法适用于在进行中的对话里维持上下文，而无需反复处理相同信息。

正确设置后，你应在每个请求的 usage 响应中看到以下内容：

* `input_tokens`：新用户消息中的 token 数（会很少）
* `cache_creation_input_tokens`：新的 assistant 和 user 轮中的 token 数
* `cache_read_input_tokens`：直到上一轮为止的对话中的 token 数
</code></pre>
  </Accordion>
  <Accordion title="综合运用：多个缓存断点">
    <CodeGroup>
<pre><code>  ```python Python
  client = anthropic.Anthropic()

  response = client.messages.create(
      model=&quot;claude-opus-5&quot;,
      max_tokens=1024,
      tools=[
          {
              &quot;name&quot;: &quot;search_documents&quot;,
              &quot;description&quot;: &quot;Search through the knowledge base&quot;,
              &quot;input_schema&quot;: {
                  &quot;type&quot;: &quot;object&quot;,
                  &quot;properties&quot;: {
                      &quot;query&quot;: {&quot;type&quot;: &quot;string&quot;, &quot;description&quot;: &quot;Search query&quot;}
                  },
                  &quot;required&quot;: [&quot;query&quot;],
              },
          },
          {
              &quot;name&quot;: &quot;get_document&quot;,
              &quot;description&quot;: &quot;Retrieve a specific document by ID&quot;,
              &quot;input_schema&quot;: {
                  &quot;type&quot;: &quot;object&quot;,
                  &quot;properties&quot;: {
                      &quot;doc_id&quot;: {&quot;type&quot;: &quot;string&quot;, &quot;description&quot;: &quot;Document ID&quot;}
                  },
                  &quot;required&quot;: [&quot;doc_id&quot;],
              },
              &quot;cache_control&quot;: {&quot;type&quot;: &quot;ephemeral&quot;},
          },
      ],
      system=[
          {
              &quot;type&quot;: &quot;text&quot;,
              &quot;text&quot;: &quot;You are a helpful research assistant with access to a document knowledge base.\n\n# Instructions\n- Always search for relevant documents before answering\n- Provide citations for your sources\n- Be objective and accurate in your responses\n- If multiple documents contain relevant information, synthesize them\n- Acknowledge when information is not available in the knowledge base&quot;,
              &quot;cache_control&quot;: {&quot;type&quot;: &quot;ephemeral&quot;},
          },
          {
              &quot;type&quot;: &quot;text&quot;,
              &quot;text&quot;: &quot;# Knowledge Base Context\n\nHere are the relevant documents for this conversation:\n\n## Document 1: Solar System Overview\nThe solar system consists of the Sun and all objects that orbit it...\n\n## Document 2: Planetary Characteristics\nEach planet has unique features. Mercury is the smallest planet...\n\n## Document 3: Mars Exploration\nMars has been a target of exploration for decades...\n\n[Additional documents...]&quot;,
              &quot;cache_control&quot;: {&quot;type&quot;: &quot;ephemeral&quot;},
          },
      ],
      messages=[
          {
              &quot;role&quot;: &quot;user&quot;,
              &quot;content&quot;: &quot;Can you search for information about Mars rovers?&quot;,
          },
          {
              &quot;role&quot;: &quot;assistant&quot;,
              &quot;content&quot;: [
                  {
                      &quot;type&quot;: &quot;tool_use&quot;,
                      &quot;id&quot;: &quot;tool_1&quot;,
                      &quot;name&quot;: &quot;search_documents&quot;,
                      &quot;input&quot;: {&quot;query&quot;: &quot;Mars rovers&quot;},
                  }
              ],
          },
          {
              &quot;role&quot;: &quot;user&quot;,
              &quot;content&quot;: [
                  {
                      &quot;type&quot;: &quot;tool_result&quot;,
                      &quot;tool_use_id&quot;: &quot;tool_1&quot;,
                      &quot;content&quot;: &quot;Found 3 relevant documents: Document 3 (Mars Exploration), Document 7 (Rover Technology), Document 9 (Mission History)&quot;,
                  }
              ],
          },
          {
              &quot;role&quot;: &quot;assistant&quot;,
              &quot;content&quot;: [
                  {
                      &quot;type&quot;: &quot;text&quot;,
                      &quot;text&quot;: &quot;I found 3 relevant documents about Mars rovers. Let me get more details from the Mars Exploration document.&quot;,
                  }
              ],
          },
          {
              &quot;role&quot;: &quot;user&quot;,
              &quot;content&quot;: [
                  {
                      &quot;type&quot;: &quot;text&quot;,
                      &quot;text&quot;: &quot;Yes, please tell me about the Perseverance rover specifically.&quot;,
                      &quot;cache_control&quot;: {&quot;type&quot;: &quot;ephemeral&quot;},
                  }
              ],
          },
      ],
  )
  print(response.usage.model_dump_json())
  ```

&lt;/CodeGroup&gt;

这个综合示例演示如何使用全部 4 个可用缓存断点来优化 prompt 的不同部分：

1. **工具缓存**（缓存断点 1）：最后一个工具定义上的 `cache_control` 参数会缓存所有工具定义。

2. **可复用指令缓存**（缓存断点 2）：system prompt 中的静态指令被单独缓存。这些指令在请求之间很少变化。

3. **RAG 上下文缓存**（缓存断点 3）：知识库文档被独立缓存，让你可以更新 RAG 文档而不使 tools 或 instructions 缓存失效。

4. **对话历史缓存**（缓存断点 4）：最后一条用户消息标有 `cache_control`，以便随对话推进进行增量缓存。

这种方法提供最大灵活性：

* 如果你向对话追加新一轮且不更改更早的内容，全部四个缓存区段都会被复用
* 如果你更新 RAG 文档但保持相同的 tools 和 instructions，前两个缓存区段会被复用
* 如果你更改对话但保持相同的 tools、instructions 和 documents，前三个区段会被复用
* 任何断点处的变更会使该区段及其之后的一切失效，而更早的已缓存区段仍然有效

对于第一次请求：

* `input_tokens`：很少（最后一个缓存断点之后的 token，本示例中接近 0）
* `cache_creation_input_tokens`：所有被缓存区段中的 token（tools + instructions + RAG documents + conversation history）
* `cache_read_input_tokens`: 0（没有缓存命中）

对于仅带有新用户消息的后续请求（并且第四个断点移到该新的最后一条消息上，如示例所示）：

* `input_tokens`：很少（最后一个缓存断点之后的 token，本示例中接近 0）
* `cache_creation_input_tokens`：新用户消息和上一轮 assistant 中的 token（正在被缓存的新对话区段）
* `cache_read_input_tokens`：所有先前已缓存的 token（tools + instructions + RAG documents + previous conversation）

这种模式尤其适用于：

* 带有大型文档上下文的 RAG 应用
* 使用多种工具的 Agent 系统
* 需要维持上下文的长时间运行对话
* 需要独立优化 prompt 不同部分的应用
</code></pre>
  </Accordion>
</AccordionGroup>
<h2 id="数据保留">数据保留</h2>
<p>Prompt Caching（自动缓存和显式缓存断点）符合 ZDR 资格。Anthropic 不会存储你的 prompt 原文或 Claude 的响应。</p>
<p>KV（key-value）缓存表示以及已缓存内容的加密哈希仅保存在内存中，不会持久化存储。缓存条目的最短生命周期为 5 分钟（标准）或 1 小时（延长），之后会及时（尽管不是立即）删除。缓存条目在组织之间隔离；在 Claude API、Claude Platform on AWS 和 Microsoft Foundry 上，还在组织内的 workspace 之间隔离。</p>
<p>关于所有功能的 ZDR 资格，请参阅 <a href="https://platform.claude.com/docs/en/manage-claude/api-and-data-retention">API and data retention</a>。</p>
<hr>
<h2 id="faq">FAQ</h2>
<AccordionGroup>
  <Accordion title="我需要多个缓存断点，还是末尾一个就足够？">
    **在大多数情况下，静态内容末尾的单个缓存断点就足够了。** 缓存写入只发生在你标记的块上。把它放在跨请求保持相同的最后一个块上，之后每个后续请求都会读取同一条条目。如果后面的块每次请求都会变化（时间戳、传入消息），把断点保持在它之前，即最后一个稳定块上。
<pre><code>你只在以下情况下需要多个断点：

* 增长中的对话把你的断点推到距上次缓存写入 20 个或更多块，使先前条目落在回看窗口之外
* 你希望独立缓存以不同频率更新的区段
* 你需要显式控制缓存内容以便优化成本

示例：如果你有系统指令（很少变化）和 RAG 上下文（每天变化），你可能会使用两个断点分别缓存它们。
</code></pre>
  </Accordion>
  <Accordion title="缓存断点会增加额外成本吗？">
    不会，缓存断点本身是免费的。你只需为以下项付费：
<pre><code>* 将内容写入缓存（5 分钟 TTL 比基础输入 token 贵 25%）
* 从缓存读取（基础输入 token 价格的一小部分，参见[定价](https://platform.claude.com/docs/en/build-with-claude/prompt-caching#pricing)）
* 未缓存内容的常规输入 token

断点数量不影响定价——只有实际被缓存和读取的内容量才重要。
</code></pre>
  </Accordion>
  <Accordion title="如何从 usage 字段计算总输入 token？">
    usage 响应包含三个独立的输入 token 字段，它们合在一起表示你的总输入：
<pre><code>```text wrap
total_input_tokens = cache_read_input_tokens + cache_creation_input_tokens + input_tokens
```

* `cache_read_input_tokens`：从缓存检索的 token（缓存断点之前已缓存的一切）
* `cache_creation_input_tokens`：正在写入缓存的新 token（在缓存断点处）
* `input_tokens`：**最后一个缓存断点之后**未被缓存的 token

**重要：** `input_tokens` 并不代表全部输入 token——只代表最后一个缓存断点之后的部分。如果有已缓存内容，`input_tokens` 通常会远小于你的总输入。

**示例：** 一份 200k token 的文档已缓存，加上 50 token 的用户问题：

* `cache_read_input_tokens`: 200,000
* `cache_creation_input_tokens`: 0
* `input_tokens`: 50
* **总计：** 200,050 tokens

这一分解对于理解成本和速率限制用量都至关重要。更多详情请参阅[跟踪缓存表现](https://platform.claude.com/docs/en/build-with-claude/prompt-caching#tracking-cache-performance)。
</code></pre>
  </Accordion>
  <Accordion title="缓存生命周期是多久？">
    缓存的默认最短生命周期（TTL）为 5 分钟。每次使用缓存内容时，该生命周期都会刷新。
<pre><code>如果你觉得 5 分钟太短，Anthropic 还提供 [1 小时缓存 TTL](https://platform.claude.com/docs/en/build-with-claude/prompt-caching#1-hour-cache-duration)。
</code></pre>
  </Accordion>
  <Accordion title="缓存生命周期从何时开始？">
    生命周期从写入或读取该缓存条目的请求开始时刻起算，而非从其响应结束时刻起算。生成响应所花费的时间会计入生命周期，因此后续请求复用缓存的窗口是生命周期减去生成时间。
<pre><code>如果你的请求会产生很长的响应，且下一次请求可能在生命周期结束之后才开始，请使用 [1 小时缓存 TTL](https://platform.claude.com/docs/en/build-with-claude/prompt-caching#1-hour-cache-duration)。
</code></pre>
  </Accordion>
  <Accordion title="我可以使用多少个缓存断点？">
    你可以在 prompt 中定义最多 4 个缓存断点（使用 `cache_control` 参数）。
  </Accordion>
  <Accordion title="Prompt Caching 是否适用于所有模型？">
    Prompt Caching 在所有[当前可用的 Claude 模型](https://platform.claude.com/docs/en/models/overview)上均受支持。
  </Accordion>
  <Accordion title="Prompt Caching 与 thinking 如何配合？">
    更改 thinking 参数（切换模式，或更改 extended mode 中的 budget）会使已缓存的 message 前缀失效，也可能使已缓存的 system prompts 和 tools 失效，因为 thinking 配置会被渲染进 prompt。[`output_config.effort`](https://platform.claude.com/docs/en/build-with-claude/effort) 值的行为相同。
<pre><code>关于缓存失效的更多详情，请参阅[什么会使缓存失效](https://platform.claude.com/docs/en/build-with-claude/prompt-caching#what-invalidates-the-cache)。

关于 thinking 的更多信息，包括它与 tool use 和 Prompt Caching 的交互，请参阅 [Thinking and prompt caching](https://platform.claude.com/docs/en/build-with-claude/thinking#thinking-and-prompt-caching)。
</code></pre>
  </Accordion>
  <Accordion title="如何启用 Prompt Caching？">
    最简单的方式是在请求体顶层添加 `"cache_control": {"type": "ephemeral"}`（[自动缓存](https://platform.claude.com/docs/en/build-with-claude/prompt-caching#automatic-caching)）。或者，在各个内容块上至少包含一个 `cache_control` 断点（[显式缓存断点](https://platform.claude.com/docs/en/build-with-claude/prompt-caching#explicit-cache-breakpoints)）。
  </Accordion>
  <Accordion title="我可以将 Prompt Caching 与其他 API 功能一起使用吗？">
    可以，Prompt Caching 可以与 tool use 和视觉能力等其他 API 功能一起使用。但是，更改 prompt 中是否包含图像或修改 tool use 设置会使缓存失效。
<pre><code>关于缓存失效的更多详情，请参阅[什么会使缓存失效](https://platform.claude.com/docs/en/build-with-claude/prompt-caching#what-invalidates-the-cache)。
</code></pre>
  </Accordion>
  <Accordion title="Prompt Caching 如何影响定价？">
    Prompt Caching 引入了新的定价结构：5 分钟缓存写入比基础输入 token 贵 25%，1 小时缓存写入为基础输入 token 的 2 倍，缓存命中为基础输入 token 价格的一小部分（各模型乘数见[定价](https://platform.claude.com/docs/en/build-with-claude/prompt-caching#pricing)）。
  </Accordion>
  <Accordion title="我可以手动清除缓存吗？">
    目前无法手动清除缓存。已缓存前缀在至少 5 分钟不活动后自动过期。
  </Accordion>
  <Accordion title="如何跟踪缓存策略的有效性？">
    你可以使用 API 响应中的 `cache_creation_input_tokens` 和 `cache_read_input_tokens` 字段监控缓存表现。
  </Accordion>
  <Accordion title="什么会破坏缓存？">
    关于缓存失效的更多详情，包括需要创建新缓存条目的变更列表，请参阅[什么会使缓存失效](https://platform.claude.com/docs/en/build-with-claude/prompt-caching#what-invalidates-the-cache)。
  </Accordion>
  <Accordion title="Prompt Caching 如何处理隐私和数据隔离？">
    Prompt Caching 在设计上采用了严格的隐私和数据隔离措施：
<pre><code>1. 缓存键使用直到 cache control 点为止的 prompt 的加密哈希生成。这意味着只有具有相同 prompt 的请求才能访问特定缓存。

2. 在 Claude API、Claude Platform on AWS 和 Microsoft Foundry 上，缓存在组织内按 workspace 隔离。在 Bedrock 和 Google Cloud 上，缓存在组织级隔离。在任何情况下，缓存都不会跨组织共享，即使 prompt 相同。详情见[缓存存储与共享](https://platform.claude.com/docs/en/build-with-claude/prompt-caching#cache-storage-and-sharing)。

3. 缓存机制旨在维护每个独特对话或上下文的完整性和隐私。

4. 在 prompt 的任何位置使用 `cache_control` 都是安全的。要让缓存产生读取，把断点放在稳定前缀的末尾：把它放在每次请求都会变化的块上（例如时间戳或用户的任意输入）会每次写入一条新条目，并且永远不会命中。

这些措施确保 Prompt Caching 在提供性能收益的同时维护数据隐私和安全。
</code></pre>
  </Accordion>
  <Accordion title="我可以将 Prompt Caching 与 Batches API 一起使用吗？">
    可以，你可以在 [Batches API](https://platform.claude.com/docs/en/build-with-claude/batch-processing) 请求中使用 Prompt Caching。但是，由于异步批处理请求可以并发并以任意顺序处理，缓存命中按尽力而为提供。
<pre><code>[1 小时缓存](https://platform.claude.com/docs/en/build-with-claude/prompt-caching#1-hour-cache-duration)可以帮助提高缓存命中。使用它的最经济方式如下：

* 收集一组具有共享前缀的 message 请求。
* 发送一个批处理请求，其中包含单个带有该共享前缀和 1 小时缓存块的请求。这会将该前缀写入 1 小时缓存。
* 一旦完成，提交其余请求。你需要监控该作业以知道它何时完成。

这通常优于使用 5 分钟缓存，因为批处理请求通常需要 5 分钟到 1 小时才能完成。
</code></pre>
  </Accordion>
  <Accordion title="为什么我在 Python 中看到错误 `AttributeError: 'Beta' object has no attribute 'prompt_caching'`？">
    此错误通常出现在你已升级 SDK 或正在使用过时代码示例时。Prompt Caching 不再需要 beta 前缀。不要使用：
<pre><code>&lt;CodeGroup&gt;
  ```python Python
  client.beta.prompt_caching.messages.create(**params)
  ```
&lt;/CodeGroup&gt;

而应使用：

&lt;CodeGroup&gt;
  ```python Python
  client.messages.create(**params)
  ```
&lt;/CodeGroup&gt;
</code></pre>
  </Accordion>
  <Accordion title="为什么我会看到 'TypeError: Cannot read properties of undefined (reading 'messages')'？">
    此错误通常出现在你已升级 SDK 或正在使用过时代码示例时。Prompt Caching 不再需要 beta 前缀。不要使用：
<pre><code>直接使用：
</code></pre>
  </Accordion>
</AccordionGroup>]]></content:encoded>
    </item>
    <item>
      <title>Token counting</title>
      <link>https://tuanzi-wow.cn/%E4%B8%8A%E4%B8%8B%E6%96%87%E5%B7%A5%E7%A8%8B/claudecode_context_management_cn/token-counting/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://tuanzi-wow.cn/%E4%B8%8A%E4%B8%8B%E6%96%87%E5%B7%A5%E7%A8%8B/claudecode_context_management_cn/token-counting/</guid>
      <description>在把 message 发给 Claude 之前统计其中的 tokens。用 token 计数来管理速率限制和成本、做模型路由决策，以及把 prompt 调整到目标长度。</description>
      <content:encoded><![CDATA[<h2 id="兼容性">兼容性</h2>
<ul>
<li><a href="https://platform.claude.com/docs/en/manage-claude/api-and-data-retention">ZDR</a>: 符合条件（不含 <a href="https://platform.claude.com/docs/en/manage-claude/api-and-data-retention#model-specific-data-retention-requirements">Covered Models</a>）</li>
<li>平台: Claude API, Claude Platform on AWS, Amazon Bedrock, Google Cloud, Microsoft Foundry</li>
</ul>
<p>Token counting 可以让你在把 message 发给 Claude 之前确定其中的 token 数量。这有助于你就 prompt 和用量做出更有依据的决策。借助 token counting，你可以：</p>
<ul>
<li>主动管理速率限制和成本</li>
<li>做出明智的模型路由决策</li>
<li>将 prompt 优化到特定长度</li>
</ul>
<hr>
<h2 id="如何统计-message-tokens">如何统计 message tokens</h2>
<p><a href="https://platform.claude.com/docs/en/api/messages-count-tokens">token counting</a> endpoint 接受与创建 message 相同的结构化输入列表，包括对 system prompt、<a href="https://platform.claude.com/docs/en/agents-and-tools/tool-use/overview">tools</a>、<a href="https://platform.claude.com/docs/en/build-with-claude/vision">images</a> 和 <a href="https://platform.claude.com/docs/en/build-with-claude/pdf-support">PDFs</a> 的支持。响应中包含输入 tokens 的总数。</p>
<p>对于 Messages API 会接受、但本 endpoint 不接受的少数输入，该 endpoint 会返回 <code>invalid_request_error</code>：例如 web search、web fetch、code execution 和 tool search 等 <a href="https://platform.claude.com/docs/en/agents-and-tools/tool-use/server-tools">server tools</a>（<a href="https://platform.claude.com/docs/en/agents-and-tools/tool-use/advisor-tool">advisor tool</a> 除外的所有 server tool）、<a href="https://platform.claude.com/docs/en/agents-and-tools/mcp-connector">MCP connector</a>，以及 <code>source</code> 为 <code>url</code> 或 <code>file</code> 的 <code>image</code> 或 <code>document</code> blocks。统计图片和 PDF 时请以 base64 发送。对于使用 server tools 或 MCP servers 的请求，Messages API 响应会在其 <code>usage</code> 对象中报告所用 tokens。</p>
<Note>
  Token 计数是一个**估计**。在某些情况下，创建 message 时实际使用的输入 tokens 数量可能有小幅差异。
<p>Token 计数可能包含 Anthropic 为系统优化自动添加的 tokens。<strong>系统添加的 tokens 不会向你计费</strong>。计费只反映你的内容。
</Note></p>
<h3 id="支持的模型">支持的模型</h3>
<p>所有 <a href="https://platform.claude.com/docs/en/models/overview">active models</a> 都支持 token counting。</p>
<Note>
  Claude 4.7 及之后的模型和 Claude Mythos Preview 使用较新的 tokenizer。同一段输入文本产生的 tokens 大约比早期模型多 30 percent。具体增幅取决于内容和 workload 形态。请针对你计划使用的模型重新统计 prompt，而不是复用在早期模型上测得的计数。
</Note>
<h3 id="统计基本-messages-中的-tokens">统计基本 messages 中的 tokens</h3>
<CodeGroup>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span><span class="lnt">9
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">client</span> <span class="o">=</span> <span class="n">anthropic</span><span class="o">.</span><span class="n">Anthropic</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">response</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">messages</span><span class="o">.</span><span class="n">count_tokens</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">model</span><span class="o">=</span><span class="s2">&#34;claude-opus-5&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">system</span><span class="o">=</span><span class="s2">&#34;You are a scientist&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">messages</span><span class="o">=</span><span class="p">[{</span><span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span> <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;Hello, Claude&#34;</span><span class="p">}],</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">response</span><span class="o">.</span><span class="n">json</span><span class="p">())</span>
</span></span></code></pre></td></tr></table>
</div>
</div></CodeGroup>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span> <span class="nt">&#34;input_tokens&#34;</span><span class="p">:</span> <span class="mi">14</span> <span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="统计带-tools-的-messages-中的-tokens">统计带 tools 的 messages 中的 tokens</h3>
<Note>
  Token counting 支持 client tools 和 [advisor tool](https://platform.claude.com/docs/en/agents-and-tools/tool-use/advisor-tool)。包含其他 [server tools](https://platform.claude.com/docs/en/agents-and-tools/tool-use/server-tools) 的请求会返回错误。对于 advisor tool，计数只覆盖 executor 的第一次 sampling call。
</Note>
<CodeGroup>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">client</span> <span class="o">=</span> <span class="n">anthropic</span><span class="o">.</span><span class="n">Anthropic</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">response</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">messages</span><span class="o">.</span><span class="n">count_tokens</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">model</span><span class="o">=</span><span class="s2">&#34;claude-opus-5&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">tools</span><span class="o">=</span><span class="p">[</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;get_weather&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;description&#34;</span><span class="p">:</span> <span class="s2">&#34;Get the current weather in a given location&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;input_schema&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;object&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;properties&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                    <span class="s2">&#34;location&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                        <span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;string&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                        <span class="s2">&#34;description&#34;</span><span class="p">:</span> <span class="s2">&#34;The city and state, e.g. San Francisco, CA&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                    <span class="p">}</span>
</span></span><span class="line"><span class="cl">                <span class="p">},</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;required&#34;</span><span class="p">:</span> <span class="p">[</span><span class="s2">&#34;location&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">            <span class="p">},</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">],</span>
</span></span><span class="line"><span class="cl">    <span class="n">messages</span><span class="o">=</span><span class="p">[{</span><span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span> <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;What&#39;s the weather like in San Francisco?&#34;</span><span class="p">}],</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">response</span><span class="o">.</span><span class="n">json</span><span class="p">())</span>
</span></span></code></pre></td></tr></table>
</div>
</div></CodeGroup>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span> <span class="nt">&#34;input_tokens&#34;</span><span class="p">:</span> <span class="mi">403</span> <span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="统计带图片的-messages-中的-tokens">统计带图片的 messages 中的 tokens</h3>
<CodeGroup>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">base64</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">httpx2</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">image_url</span> <span class="o">=</span> <span class="s2">&#34;https://platform.claude.com/docs/images/vision-example.jpg&#34;</span>
</span></span><span class="line"><span class="cl"><span class="n">image_media_type</span> <span class="o">=</span> <span class="s2">&#34;image/jpeg&#34;</span>
</span></span><span class="line"><span class="cl"><span class="n">image_data</span> <span class="o">=</span> <span class="n">base64</span><span class="o">.</span><span class="n">standard_b64encode</span><span class="p">(</span><span class="n">httpx2</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">image_url</span><span class="p">)</span><span class="o">.</span><span class="n">content</span><span class="p">)</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">&#34;utf-8&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">client</span> <span class="o">=</span> <span class="n">anthropic</span><span class="o">.</span><span class="n">Anthropic</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">response</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">messages</span><span class="o">.</span><span class="n">count_tokens</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">model</span><span class="o">=</span><span class="s2">&#34;claude-opus-5&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">messages</span><span class="o">=</span><span class="p">[</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">                <span class="p">{</span>
</span></span><span class="line"><span class="cl">                    <span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;image&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                    <span class="s2">&#34;source&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                        <span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;base64&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                        <span class="s2">&#34;media_type&#34;</span><span class="p">:</span> <span class="n">image_media_type</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                        <span class="s2">&#34;data&#34;</span><span class="p">:</span> <span class="n">image_data</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                    <span class="p">},</span>
</span></span><span class="line"><span class="cl">                <span class="p">},</span>
</span></span><span class="line"><span class="cl">                <span class="p">{</span><span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;text&#34;</span><span class="p">,</span> <span class="s2">&#34;text&#34;</span><span class="p">:</span> <span class="s2">&#34;Describe this image&#34;</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">            <span class="p">],</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">],</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">response</span><span class="o">.</span><span class="n">json</span><span class="p">())</span>
</span></span></code></pre></td></tr></table>
</div>
</div></CodeGroup>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span> <span class="nt">&#34;input_tokens&#34;</span><span class="p">:</span> <span class="mi">1028</span> <span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>设置了 <a href="https://platform.claude.com/docs/en/build-with-claude/vision-coordinates#oversized-image-error"><code>&quot;oversized_image&quot;: &quot;error&quot;</code></a> 的嵌入 image block 会在计数时被拒绝，拒绝方式与 Messages API 完全相同。</p>
<h3 id="统计带-thinking-的-messages-中的-tokens">统计带 thinking 的 messages 中的 tokens</h3>
<Note>
  更多细节见 [Thinking and the context window](https://platform.claude.com/docs/en/build-with-claude/thinking#thinking-and-the-context-window)。
<ul>
<li>来自<strong>先前</strong> assistant turn 的 thinking blocks，在 <a href="https://platform.claude.com/docs/en/build-with-claude/thinking#thinking-block-preservation-by-model">保留全部先前 turns</a> 的模型上会计入你的输入 tokens；在只保留最后一个 turn 的模型上，API 会剥离它们，因此<strong>不</strong>计入</li>
<li><strong>当前</strong> assistant turn 的 thinking <strong>会</strong>计入你的输入 tokens
</Note></li>
</ul>
<CodeGroup>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">client</span> <span class="o">=</span> <span class="n">anthropic</span><span class="o">.</span><span class="n">Anthropic</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">response</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">messages</span><span class="o">.</span><span class="n">count_tokens</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">model</span><span class="o">=</span><span class="s2">&#34;claude-opus-5&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">thinking</span><span class="o">=</span><span class="p">{</span><span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;adaptive&#34;</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="n">messages</span><span class="o">=</span><span class="p">[</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;Are there an infinite number of prime numbers such that n mod 4 == 3?&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="p">},</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;assistant&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">                <span class="p">{</span>
</span></span><span class="line"><span class="cl">                    <span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;thinking&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                    <span class="s2">&#34;thinking&#34;</span><span class="p">:</span> <span class="s2">&#34;This is a nice number theory question. Let&#39;s think about it step by step...&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                    <span class="s2">&#34;signature&#34;</span><span class="p">:</span> <span class="s2">&#34;EuYBCkQYAiJAgCs1le6/Pol5Z4/JMomVOouGrWdhYNsH3ukzUECbB6iWrSQtsQuRHJID6lWV...&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="p">},</span>
</span></span><span class="line"><span class="cl">                <span class="p">{</span>
</span></span><span class="line"><span class="cl">                    <span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;text&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                    <span class="s2">&#34;text&#34;</span><span class="p">:</span> <span class="s2">&#34;Yes, there are infinitely many prime numbers p such that p mod 4 = 3...&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="p">},</span>
</span></span><span class="line"><span class="cl">            <span class="p">],</span>
</span></span><span class="line"><span class="cl">        <span class="p">},</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span><span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span> <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;Can you write a formal proof?&#34;</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">],</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">response</span><span class="o">.</span><span class="n">json</span><span class="p">())</span>
</span></span></code></pre></td></tr></table>
</div>
</div></CodeGroup>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span> <span class="nt">&#34;input_tokens&#34;</span><span class="p">:</span> <span class="mi">88</span> <span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="统计带-pdf-的-messages-中的-tokens">统计带 PDF 的 messages 中的 tokens</h3>
<Note>
  Token counting 支持 base64 编码的 PDF，要求与 Messages API 的 [PDF requirements](https://platform.claude.com/docs/en/build-with-claude/pdf-support#check-pdf-requirements) 相同。该 endpoint 不支持 `url` 或 `file` 类型的 document source。
</Note>
<CodeGroup>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">base64</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">anthropic</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">client</span> <span class="o">=</span> <span class="n">anthropic</span><span class="o">.</span><span class="n">Anthropic</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s2">&#34;/path/to/document.pdf&#34;</span><span class="p">,</span> <span class="s2">&#34;rb&#34;</span><span class="p">)</span> <span class="k">as</span> <span class="n">pdf_file</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">pdf_base64</span> <span class="o">=</span> <span class="n">base64</span><span class="o">.</span><span class="n">standard_b64encode</span><span class="p">(</span><span class="n">pdf_file</span><span class="o">.</span><span class="n">read</span><span class="p">())</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">&#34;utf-8&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">response</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">messages</span><span class="o">.</span><span class="n">count_tokens</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">model</span><span class="o">=</span><span class="s2">&#34;claude-opus-5&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">messages</span><span class="o">=</span><span class="p">[</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">                <span class="p">{</span>
</span></span><span class="line"><span class="cl">                    <span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;document&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                    <span class="s2">&#34;source&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                        <span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;base64&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                        <span class="s2">&#34;media_type&#34;</span><span class="p">:</span> <span class="s2">&#34;application/pdf&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                        <span class="s2">&#34;data&#34;</span><span class="p">:</span> <span class="n">pdf_base64</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                    <span class="p">},</span>
</span></span><span class="line"><span class="cl">                <span class="p">},</span>
</span></span><span class="line"><span class="cl">                <span class="p">{</span><span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;text&#34;</span><span class="p">,</span> <span class="s2">&#34;text&#34;</span><span class="p">:</span> <span class="s2">&#34;Please summarize this document.&#34;</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">            <span class="p">],</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">],</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">response</span><span class="o">.</span><span class="n">json</span><span class="p">())</span>
</span></span></code></pre></td></tr></table>
</div>
</div></CodeGroup>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span> <span class="nt">&#34;input_tokens&#34;</span><span class="p">:</span> <span class="mi">2188</span> <span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><hr>
<h2 id="claude-fable-和-claude-mythos-模型上的-token-计数">Claude Fable 和 Claude Mythos 模型上的 token 计数</h2>
<p>Claude Fable 5.1、Claude Mythos 5.1、Claude Fable 5 和 Claude Mythos 5 共用 Claude Opus 4.7 引入的 tokenizer。同一段 prompt 在这四个模型上的计数相同，并且比 Claude Opus 4.7 之前的模型大约高 30 percent（具体增幅取决于内容）。token counting endpoint 按你传入的 <code>model</code> 所对应的 tokenizer 计数。要衡量对你 workload 的差异，请对同一请求计数两次：一次用当前模型，一次用你计划迁移到的模型，然后比较两次的 <code>input_tokens</code> 值。</p>
<Note>
  **计费与迁移：** 这些模型上的用量和计费以该 tokenizer 的计数为准。从 Claude Opus 4.7 之前的模型迁移时，不要复用在旧模型上测得的 token 计数来估计成本或上下文窗口是否放得下。请用你计划使用的 `model` ID（例如 `"claude-fable-5-1"`）来统计 prompt。
</Note>
<hr>
<h2 id="定价与速率限制">定价与速率限制</h2>
<p>Token counting <strong>免费使用</strong>，但受基于你的 <a href="https://platform.claude.com/docs/en/api/rate-limits#rate-limits">usage tier</a> 的每分钟请求数速率限制约束。如果需要更高限额，请在 <a href="https://platform.claude.com/settings/limits">Rate limits</a> 页面使用 <strong>Request rate limit increase</strong>。</p>
<table>
	<thead>
			<tr>
					<th>Usage tier</th>
					<th>每分钟请求数 (RPM)</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Start</td>
					<td>5,000</td>
			</tr>
			<tr>
					<td>Build</td>
					<td>10,000</td>
			</tr>
			<tr>
					<td>Scale</td>
					<td>20,000</td>
			</tr>
	</tbody>
</table>
<Note>
  Token counting 与 message 创建有各自独立的速率限制。使用其中一项不会占用另一项的限额。
</Note>
<hr>
<h2 id="faq">FAQ</h2>
<AccordionGroup>
  <Accordion title="Token counting 会使用 prompt caching 吗？">
    不会。Token counting 提供估计，不使用缓存逻辑。虽然你可以在 token counting 请求中提供 `cache_control` blocks，但 prompt caching 只在实际创建 message 时发生。
  </Accordion>
</AccordionGroup>
<hr>
<h2 id="后续步骤">后续步骤</h2>
<CardGroup cols={2}>
  <Card title="统计 message tokens" icon="code" href="https://platform.claude.com/docs/en/api/messages-count-tokens">
    阅读 token counting endpoint 的完整 API 参考。
  </Card>
  <Card title="上下文窗口" icon="arrows-maximize" href="https://platform.claude.com/docs/en/build-with-claude/context-windows">
    用 token 计数把 prompt 控制在模型的上下文窗口内。
  </Card>
  <Card title="速率限制" icon="gauge" href="https://platform.claude.com/docs/en/api/rate-limits">
    在发送请求前检查 token 计数，以保持在你的 usage tier 内。
  </Card>
  <Card title="Prompt caching" icon="database" href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching">
    通过缓存 prompt 前缀，降低重复 prompt 的成本和延迟。
  </Card>
</CardGroup>]]></content:encoded>
    </item>
  </channel>
</rss>
