<?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 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/claude_context_management/</link>
    <description>Recent content in Claude Context Management on On My Way</description>
    <generator>Hugo</generator>
    <language>zh-CN</language>
    <lastBuildDate>Sun, 06 Sep 2026 00:00:00 +0800</lastBuildDate>
    <atom:link href="https://tuanzi-wow.cn/%E4%B8%8A%E4%B8%8B%E6%96%87%E5%B7%A5%E7%A8%8B/claude_context_management/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Context Management · Compaction</title>
      <link>https://tuanzi-wow.cn/%E4%B8%8A%E4%B8%8B%E6%96%87%E5%B7%A5%E7%A8%8B/claude_context_management/context-compaction/</link>
      <pubDate>Sun, 06 Sep 2026 00:00:00 +0800</pubDate>
      <guid>https://tuanzi-wow.cn/%E4%B8%8A%E4%B8%8B%E6%96%87%E5%B7%A5%E7%A8%8B/claude_context_management/context-compaction/</guid>
      <description>Claude 的 Server-side Compaction：自动压缩会话上下文以突破窗口限制。</description>
      <content:encoded><![CDATA[<h1 id="compaction">Compaction</h1>
<p>Server-side context compaction for managing long conversations that approaching context window limits</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-fallback" data-lang="fallback"><span class="line"><span class="cl">Server-side compaction is the recommended strategy for managing context in long-running conversations and agentic workflows. It handles context management automatically, without client-side summarization code.
</span></span></code></pre></td></tr></table>
</div>
</div><p>as a conversation grows, response quality degrades,Compaction extends the effective context length for long-running conversations and tasks
compaction replaces older content with a concise summary.</p>
<p>This is ideal for:</p>
<ul>
<li>Chat-based, multi-turn conversations where you want users to use one chat for a long period of time</li>
<li>Task-oriented prompts that require a lot of follow-up work (often tool use) that might exceed the context window</li>
</ul>
<h2 id="how-compaction-works">How compaction works</h2>
<p>four steps:</p>
<ol>
<li>Detects when input tokens reach your specified trigger threshold.</li>
<li>Generates a summary of the current conversation.</li>
<li>Creates a <code>compaction</code> block containing the summary.</li>
<li>Continues the response with the compacted context.</li>
</ol>
<h2 id="basic-usage">Basic usage</h2>
<p>Enable compaction by adding the <code>compact_20260112</code> strategy to <code>context_management.edits</code> in your Messages API request.</p>
<h2 id="parameters">Parameters</h2>
<table>
	<thead>
			<tr>
					<th style="text-align: left">Parameter</th>
					<th style="text-align: left">Type</th>
					<th style="text-align: left">Default</th>
					<th style="text-align: left">Description</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td style="text-align: left"><code>type</code></td>
					<td style="text-align: left">string</td>
					<td style="text-align: left">Required</td>
					<td style="text-align: left">Must be <code>&quot;compact_20260112&quot;</code></td>
			</tr>
			<tr>
					<td style="text-align: left"><code>trigger</code></td>
					<td style="text-align: left">object</td>
					<td style="text-align: left"><code>{&quot;type&quot;: &quot;input_tokens&quot;, &quot;value&quot;: 150000}</code></td>
					<td style="text-align: left">When to trigger compaction. <code>input_tokens</code> is the only supported trigger type. <code>value</code> must be at least 50,000 tokens.</td>
			</tr>
			<tr>
					<td style="text-align: left"><code>pause_after_compaction</code></td>
					<td style="text-align: left">boolean</td>
					<td style="text-align: left"><code>false</code></td>
					<td style="text-align: left">Whether to pause after generating the compaction summary</td>
			</tr>
			<tr>
					<td style="text-align: left"><code>instructions</code></td>
					<td style="text-align: left">string</td>
					<td style="text-align: left"><code>null</code></td>
					<td style="text-align: left">Custom summarization prompt. Completely replaces the default prompt when provided.</td>
			</tr>
	</tbody>
</table>
<p>ps:
type must be &ldquo;compact_20260112&rdquo;:
if u use Claude API, for sure; but if u def your own compaction function, it change use other value</p>
<h2 id="trigger-configuration">Trigger configuration</h2>
<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-fallback" data-lang="fallback"><span class="line"><span class="cl">client = anthropic.Anthropic()
</span></span><span class="line"><span class="cl">messages = [{&#34;role&#34;: &#34;user&#34;, &#34;content&#34;: &#34;Hello, Claude&#34;}]
</span></span><span class="line"><span class="cl">response = client.beta.messages.create(
</span></span><span class="line"><span class="cl">    betas=[&#34;compact-2026-01-12&#34;],
</span></span><span class="line"><span class="cl">    model=&#34;claude-opus-5&#34;,
</span></span><span class="line"><span class="cl">    max_tokens=4096,
</span></span><span class="line"><span class="cl">    messages=messages,
</span></span><span class="line"><span class="cl">    context_management={
</span></span><span class="line"><span class="cl">        &#34;edits&#34;: [
</span></span><span class="line"><span class="cl">            {
</span></span><span class="line"><span class="cl">                &#34;type&#34;: &#34;compact_20260112&#34;,
</span></span><span class="line"><span class="cl">                &#34;trigger&#34;: {&#34;type&#34;: &#34;input_tokens&#34;, &#34;value&#34;: 150000},
</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="custom-summarization-instructions">Custom summarization instructions</h2>
<p>/compaction <instruction></p>
<p>default instructions:</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-fallback" data-lang="fallback"><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>Custom instructions don&rsquo;t supplement the default prompt. They replace it completely</p>
<p>On Claude Fable 5.1 and Claude Mythos 5.1, a request with custom <code>instructions</code> summarizes from the visible conversation only: earlier thinking blocks are not part of the summarizer&rsquo;s input.</p>
<h2 id="pausing-after-compaction">Pausing after compaction</h2>
<p>Use <code>pause_after_compaction</code> to pause the API after generating the compaction summary. This allows you to add additional content blocks</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></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl"> context_management={
</span></span><span class="line"><span class="cl">        &#34;edits&#34;: [{&#34;type&#34;: &#34;compact_20260112&#34;, &#34;pause_after_compaction&#34;: True}]
</span></span><span class="line"><span class="cl">    }
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="enforce-a-total-token-budget">Enforce a total token budget</h2>
<p>When a model works on long tasks with many tool-use iterations, total token consumption can grow significantly. You can combine <code>pause_after_compaction</code> with a compaction counter to estimate cumulative usage and gracefully wrap up the task once a budget is reached.</p>
<p>This example appears in the SDK languages only: its value is the budget-tracking logic around the request. The raw request combines the <code>trigger</code> from <a href="https://platform.claude.com/docs/en/build-with-claude/compaction#trigger-configuration">Trigger configuration</a> with <code>pause_after_compaction</code> from <a href="https://platform.claude.com/docs/en/build-with-claude/compaction#pausing-after-compaction">Pausing after compaction</a>.</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-fallback" data-lang="fallback"><span class="line"><span class="cl">client = anthropic.Anthropic()
</span></span><span class="line"><span class="cl">messages = [{&#34;role&#34;: &#34;user&#34;, &#34;content&#34;: &#34;Hello, Claude&#34;}]
</span></span><span class="line"><span class="cl">TRIGGER_THRESHOLD = 100_000
</span></span><span class="line"><span class="cl">TOTAL_TOKEN_BUDGET = 3_000_000
</span></span><span class="line"><span class="cl">n_compactions = 0
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">response = client.beta.messages.create(
</span></span><span class="line"><span class="cl">    betas=[&#34;compact-2026-01-12&#34;],
</span></span><span class="line"><span class="cl">    model=&#34;claude-opus-5&#34;,
</span></span><span class="line"><span class="cl">    max_tokens=4096,
</span></span><span class="line"><span class="cl">    messages=messages,
</span></span><span class="line"><span class="cl">    context_management={
</span></span><span class="line"><span class="cl">        &#34;edits&#34;: [
</span></span><span class="line"><span class="cl">            {
</span></span><span class="line"><span class="cl">                &#34;type&#34;: &#34;compact_20260112&#34;,
</span></span><span class="line"><span class="cl">                &#34;trigger&#34;: {&#34;type&#34;: &#34;input_tokens&#34;, &#34;value&#34;: TRIGGER_THRESHOLD},
</span></span><span class="line"><span class="cl">                &#34;pause_after_compaction&#34;: True,
</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><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">if response.stop_reason == &#34;compaction&#34;:
</span></span><span class="line"><span class="cl">    n_compactions += 1
</span></span><span class="line"><span class="cl">    messages.append({&#34;role&#34;: &#34;assistant&#34;, &#34;content&#34;: response.content})
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    # Estimate total tokens consumed; prompt wrap-up if over budget
</span></span><span class="line"><span class="cl">    if n_compactions * TRIGGER_THRESHOLD &gt;= TOTAL_TOKEN_BUDGET:
</span></span><span class="line"><span class="cl">        messages.append(
</span></span><span class="line"><span class="cl">            {
</span></span><span class="line"><span class="cl">                &#34;role&#34;: &#34;user&#34;,
</span></span><span class="line"><span class="cl">                &#34;content&#34;: &#34;Please wrap up your current work and summarize the final state.&#34;,
</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>pause能够允许用户能够塞入自己的判断逻辑,防止超过总预算但是task未停止</p>
<h2 id="working-with-compaction-blocks">Working with compaction blocks</h2>
<p>When compaction is triggered, the API returns a <code>compaction</code> block at the start of the assistant response.
The new compaction block will replace the old one</p>
<h3 id="passing-compaction-blocks-back">Passing compaction blocks back</h3>
<p>You must pass the <code>compaction</code> block back to the API on subsequent requests to continue the conversation with the shortened prompt.</p>
<p>When the API receives a <code>compaction</code> block, <strong>all content blocks before it are ignored</strong>. You can either:</p>
<ul>
<li>Keep the original messages in your list and let the API handle removing the compacted content</li>
<li>Manually drop the compacted messages and only include the compaction block onwards</li>
</ul>
<h3 id="streaming">Streaming</h3>
<p>The compaction block streams differently from text blocks. You receive a <code>content_block_start</code> event, followed by a single <code>content_block_delta</code> with the complete summary content (no intermediate streaming), and then a <code>content_block_stop</code> event.</p>
<p>content_block_start -&gt; content_block_delta -&gt; content_block_stop</p>
<p>content_block_delta has the  complete summary content</p>
<h3 id="prompt-caching">Prompt caching</h3>
<p>Compaction works well with <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching">prompt caching</a>. You can add a <code>cache_control</code> breakpoint on compaction blocks to cache the summarized content.</p>
<h3 id="maximining-cache-hits-with-system-prompts">Maximining cache hits with system prompts</h3>
<p>系统提示词的缓存和压缩新写入的内容会分开,这样写入的就只有压缩后的内容,而系统提示词的缓存不会失效,实现的方法是在你的系统提示词的后面打一个断点</p>
<p>When compaction occurs, the summary becomes new content that needs to be written to the cache. Without additional cache breakpoints, this would also invalidate any cached system prompt, requiring it to be re-cached along with the compaction summary.</p>
<p>To maximize cache hit rates, add a <code>cache_control</code> breakpoint at the end of your system prompt. This keeps the system prompt cached separately from the conversation, so when compaction occurs:</p>
<ul>
<li>The system prompt cache remains valid and is read from cache</li>
<li>Only the compaction summary needs to be written as a new cache entry</li>
</ul>
<p>his keeps long system prompts cached across multiple compaction events throughout a conversation.</p>
<h2 id="understanding-usage">Understanding usage</h2>
<p>Compaction requires an additional sampling step, which contributes to rate limits and billing. The API returns detailed usage information in the response:</p>
<p>Output</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;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>The <code>iterations</code> array shows usage for each sampling iteration. When compaction occurs, you&rsquo;ll see a <code>compaction</code> iteration followed by the main <code>message</code> iteration. The top-level <code>input_tokens</code> and <code>output_tokens</code> match the <code>message</code> iteration exactly in this example because there is only one non-compaction iteration. The final iteration&rsquo;s token counts reflect the effective context size after compaction.</p>
<p>inerations数组中comapaction部分记录了压缩之前的上下文大小和压缩后的上下文大小,上面的usage和message相同是因为:
上述只有一次非compaction迭代</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></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">The top-level input_tokens and output_tokens do not include compaction iteration usage. They reflect the sum of all non-compaction iterations. To calculate total tokens consumed and billed for a request, sum across all entries in the usage.iterations array.
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">If you previously relied on usage.input_tokens and usage.output_tokens for cost tracking or auditing, you&#39;ll need to update your tracking logic to aggregate across usage.iterations when compaction is enabled. With the compaction beta enabled, every response includes usage.iterations, even if no compaction occurred. A compaction entry appears only when a new compaction is triggered during the request. Re-applying a previous compaction block incurs no additional compaction cost, and the top-level usage fields remain accurate in that case.
</span></span></code></pre></td></tr></table>
</div>
</div><p>顶端的input_token和output_token不包含压缩迭代所产生的使用量,反应的是非压缩迭代的总和
要计算一次实际请求用量,要对usage.iteration中数组中的所有条目求和依赖usage.input_token和usage.output.token来进行成本统计的方式需要转变逻辑结构,转化为对于usage.interation中的每一项进行汇总
在启用compaction Beta之后,每个响应都会柏寒usage.interation,即使没有发生上下文压缩
但是只有出现了compaction,才会在interation中出现compaction条目
重新应用原来已经存在的compaction block不会产生额外的上下文压缩费用</p>
<h2 id="combing-with-other-features">Combing With other Features</h2>
<h3 id="server-tools">Server tools</h3>
<p>When using server tools (such as web search), the compaction trigger is checked at the start of each sampling iteration. Compaction might occur multiple times within a single request depending on your trigger threshold and the amount of output generated.
系统会在每个迭代之前检查是否需要压缩,这取决于你的设置和产出的数量</p>
<h3 id="token-counting">Token counting</h3>
<p>The token counting endpoint (<code>/v1/messages/count_tokens</code>) applies existing <code>compaction</code> blocks in your prompt but does not trigger new compactions. Use it to check your effective token count after previous compactions
使用现存的compaction块而不会激活compaction,所哟不会产生新的上下文费用</p>
<h2 id="current-limitations">Current limitations</h2>
<ul>
<li><strong>Same model for summarization:</strong> The model specified in your request is used for summarization. There is no option to use a different (for example, cheaper) model for the summary.</li>
</ul>
<p>有点变态的是,Claudecode会给每一个模型都开新的缓存</p>
<ul>
<li><strong>Compaction might fail when tools are defined:</strong> When your request includes <code>tools</code>, the model occasionally calls a tool during the internal summarization step instead of writing a summary. When this occurs, the response contains a <code>compaction</code> block with <code>content: null</code>. To prevent this, set <a href="https://platform.claude.com/docs/en/build-with-claude/compaction#custom-summarization-instructions"><code>instructions</code></a> to a prompt that explicitly tells the model not to call tools, for example:
当你的请求中包含tools是,有时候压缩会因为调用工具而失败
解决方法:在Instruction中显式地声明不调用工具</li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>Context Management · Context Windows</title>
      <link>https://tuanzi-wow.cn/%E4%B8%8A%E4%B8%8B%E6%96%87%E5%B7%A5%E7%A8%8B/claude_context_management/context-windows/</link>
      <pubDate>Sun, 06 Sep 2026 00:00:00 +0800</pubDate>
      <guid>https://tuanzi-wow.cn/%E4%B8%8A%E4%B8%8B%E6%96%87%E5%B7%A5%E7%A8%8B/claude_context_management/context-windows/</guid>
      <description>Claude 的 Context Window 机制：Token 限制、Context Rot 与长上下文管理。</description>
      <content:encoded><![CDATA[<h1 id="context-windows">Context windows</h1>
<p>Understand how the context window works, how extended thinking and tool use count toward it, and how to manage context as conversations grow.</p>
<p>the primary strategy is <strong>server-side-compaction</strong></p>
<h2 id="how-the-context-window-works">How the context window works</h2>
<h3 id="what-is-the-context-window">what is the context window:</h3>
<p>The &ldquo;context window&rdquo; refers to all the text a language model can reference when generating a response, <strong>including the response itself.</strong>
<a href="https://platform.claude.com/docs/images/context-window.svg">https://platform.claude.com/docs/images/context-window.svg</a></p>
<p>As token count grows, accuracy and recall degrade, a phenomenon known as <strong><em>context rot</em>.</strong></p>
<p>Chat interfaces manage the context window on a rolling &ldquo;first in,first out &ldquo;basis</p>
<ul>
<li>Progressive token accumulation: user message and assistant response accumulates within the context window and previous is preserved</li>
<li>Context window capacity:</li>
<li>Input-Output flow: Each turn consists of
<ul>
<li>input phase</li>
<li>output phase</li>
</ul>
</li>
</ul>
<p>Everything in the turns counts:</p>
<ul>
<li>the system prompt,every message in messages(including tool results,images, and documents) and your tool definition</li>
<li>the output LLM generates, including the extended thinking</li>
</ul>
<p>If you use <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching">prompt caching</a>, the input count is split across <code>input_tokens</code>, <code>cache_read_input_tokens</code>, and <code>cache_creation_input_tokens</code></p>
<h2 id="context-window-sizes-by-model">Context window sizes by model</h2>
<p>the max length of context window is up to the model</p>
<h2 id="the-context-window-with-thinking">The context window with thinking</h2>
<p>Thinking tokens are a subset of your <code>max_tokens</code> parameter, are billed as <strong>output tokens</strong> .
Whether thinking blocks from previous assistant turns stay in the context window depends on the model.
Most of LLMs  keep previous thinking blocks by default, and they count toward the context window like any other <strong>input tokens</strong>.</p>
<p>The following diagram shows how tokens are managed when thinking is enabled on a model that strips previous thinking blocks:
<a href="https://platform.claude.com/docs/images/context-window-thinking.svg">https://platform.claude.com/docs/images/context-window-thinking.svg</a></p>
<p><strong>Billing:</strong> Thinking tokens are billed as output tokens once, when they are generated. On models that keep previous thinking blocks, the kept blocks are then part of later requests&rsquo; input and are billed as input tokens, like the rest of the conversation history.</p>
<h2 id="the-context-with-thinking-and-tool-use">The context with thinking and tool use</h2>
<p>The following diagram illustrates how tokens are managed when you combine thinking with tool use on a model that <strong>strips</strong> previous thinking blocks:
<a href="https://platform.claude.com/docs/images/context-window-thinking-tools.svg">https://platform.claude.com/docs/images/context-window-thinking-tools.svg</a></p>
<p>A little bit different from my previous thought</p>
<ol>
<li>
<h3 id="first-turn-architecture">First turn architecture</h3>
<ul>
<li><strong>Input components:</strong> Tools configuration and user message</li>
<li><strong>Output components:</strong> Thinking + text response + tool use request</li>
<li><strong>Token calculation:</strong> All input and output components count toward the context window, and all output components are billed as output tokens.</li>
</ul>
</li>
<li>
<p>Tool result handling (turn 2)</p>
<ul>
<li><strong>Input components:</strong> Every block in the first turn and the <code>tool_result</code>. You must return the thinking block with the corresponding tool results. This is the only case where you have to return thinking blocks.</li>
<li><strong>Output components:</strong> After tool results have been passed back to Claude, Claude responds with only text (no additional thinking until the next <code>user</code> message, unless <a href="https://platform.claude.com/docs/en/build-with-claude/thinking#interleaved-thinking">interleaved thinking</a> is enabled).</li>
<li><strong>Token calculation:</strong> All input and output components count toward the context window, and all output components are billed as output tokens.</li>
</ul>
</li>
<li>
<p>New user turn (turn 3)</p>
<ul>
<li><strong>Input components:</strong> All inputs and the output from the previous turn are carried forward. The thinking block from the completed tool use cycle no longer has to stay in context: on models that strip previous thinking blocks, the API drops it automatically when you pass it back, and on models that keep previous thinking blocks, it stays unless you clear it with <a href="https://platform.claude.com/docs/en/build-with-claude/context-editing#thinking-block-clearing">thinking block clearing</a>. This is also where you add the next <code>user</code> turn.</li>
<li><strong>Output components:</strong> Because there is a new <code>user</code> turn outside the tool use cycle, Claude generates a new thinking block and continues from there.</li>
<li><strong>Token calculation:</strong> On models that strip previous thinking blocks, the previous thinking tokens no longer count toward the context window. All other previous blocks still count toward the context window, as does the thinking block in the current <code>assistant</code> turn.</li>
</ul>
</li>
</ol>
<h3 id="interleaved-thinking">Interleaved thinking:</h3>
<p>Let LLMs think between tool calls.,including after it receives tool results</p>
<h2 id="context-awareness">Context awareness</h2>
<p>these models track their remaining context window (their &ldquo;token budget&rdquo;) throughout a conversation.</p>
<h2 id="how-it-works">How it works</h2>
<p>In the system prompt of every request, the API gives Claude its total context window:</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-fallback" data-lang="fallback"><span class="line"><span class="cl">&lt;budget:token_budget&gt;200000&lt;/budget:token_budget&gt;
</span></span></code></pre></td></tr></table>
</div>
</div><p>After each tool call, the API gives Claude an update on its remaining capacity:</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-fallback" data-lang="fallback"><span class="line"><span class="cl">&lt;system_warning&gt;Token usage: 35000/200000; 165000 remaining&lt;/system_warning&gt;
</span></span></code></pre></td></tr></table>
</div>
</div><p>For agents that span multiple sessions, design your state artifacts so that context recovery is fast when a new session starts. The <a href="https://platform.claude.com/docs/en/agents-and-tools/tool-use/memory-tool#multisession-software-development-pattern">memory tool&rsquo;s multisession pattern</a> walks through a concrete approach. See also <a href="https://www.anthropic.com/engineering/effective-harnesses-for-long-running-agents">Effective harnesses for long-running agents</a>.</p>
<h2 id="manage-context-with-compaction">Manage context with compaction</h2>
<p>If your conversations regularly approach context window limits, use <a href="https://platform.claude.com/docs/en/build-with-claude/compaction">server-side compaction</a>. Compaction automatically summarizes earlier parts of the conversation on the server, so the conversation can continue past the context window limit. It is available in beta for Claude 4.6 and later models and <a href="https://anthropic.com/glasswing">Claude Mythos Preview</a>.</p>
<ul>
<li><strong>Tool result clearing:</strong> Clear old tool results in agentic workflows</li>
<li><strong>Thinking block clearing:</strong> Manage thinking blocks when you use extended thinking</li>
</ul>
<h2 id="context-window-overflow-behavior">Context window overflow behavior</h2>
<p>If the input alone already exceeds the model&rsquo;s context window, the API returns a 400 <code>invalid_request_error</code> (&ldquo;prompt is too long&rdquo;) on every model.</p>
<p>On Claude 4.5 models and newer, if input tokens plus <code>max_tokens</code> exceeds the context window size, the API accepts the request. If generation then reaches the context window limit, it stops with <code>stop_reason: &quot;model_context_window_exceeded&quot;</code></p>
<p>On earlier models, the API returns a <a href="https://platform.claude.com/docs/en/api/errors">validation error</a> instead.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Context Management · Context Editing</title>
      <link>https://tuanzi-wow.cn/%E4%B8%8A%E4%B8%8B%E6%96%87%E5%B7%A5%E7%A8%8B/claude_context_management/context-editing/</link>
      <pubDate>Sun, 06 Sep 2026 00:00:00 +0800</pubDate>
      <guid>https://tuanzi-wow.cn/%E4%B8%8A%E4%B8%8B%E6%96%87%E5%B7%A5%E7%A8%8B/claude_context_management/context-editing/</guid>
      <description>Claude 的 Context Editing：自动清理过时的工具调用结果以管理对话上下文。</description>
      <content:encoded><![CDATA[<h1 id="context-editing">Context editing</h1>
<p>Automatically manage conversation context as it grows with context editing
注意断句</p>
<h2 id="overview">Overview</h2>
<p>The strategies on this page are useful for specific scenarios where you need more fine-grained control over what content is cleared.</p>
<p>更适用于在特定场景中,你需要清楚哪些内容进行更加细粒度的控制</p>
<p>Context editing allows you to selectively clear specific content from conversation history as it grows. Beyond optimizing costs and staying within limits, this is about actively curating what Claude sees: context is a finite resource with diminishing returns, and irrelevant content degrades model focus. Context editing gives you fine-grained runtime control over that curation. For the broader principles behind context management, see <a href="https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents">Effective context engineering</a>.</p>
<p>上下文编辑允许你选择性地清楚会话内容</p>
<p>除了控制成本和避免超出限制以外,这也是在主动管理Claude对于上下文的可见性:上下文是一种有限的资源,且存在边界效应;无关内容会导致模型降级和降低注意力</p>
<p>主要提供了三种方法:</p>
<ul>
<li>Tool result clearing: 适用于工具调用频繁且旧的工具调用结果不再需要的场景</li>
<li>Thinking block clear:可有有选择性地保留最近地think block</li>
<li>Client-side SDK compaction:An SDK-based alternative for summary-based context management (server-side compaction is generally preferred)官方Compaction的替代</li>
</ul>
<table>
	<thead>
			<tr>
					<th>Approach</th>
					<th>Where it runs</th>
					<th>Strategies</th>
					<th>How it works</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><strong>Server-side</strong></td>
					<td>API</td>
					<td>Tool result clearing (<code>clear_tool_uses_20250919</code>) Thinking block clearing (<code>clear_thinking_20251015</code>)</td>
					<td>Applied before the prompt reaches Claude. Clears specific content from conversation history. Each strategy <strong>can be configured independently.</strong></td>
			</tr>
			<tr>
					<td><strong>Client-side</strong></td>
					<td>SDK</td>
					<td>Compaction</td>
					<td>Available in <a href="https://platform.claude.com/docs/en/cli-sdks-libraries/overview">TypeScript and Ruby SDKs</a> when using <a href="https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-runner"><code>tool_runner</code></a>. Generates a summary and replaces full conversation history. See <a href="https://platform.claude.com/docs/en/build-with-claude/context-editing#client-side-compaction-sdk">Client-side compaction</a>.</td>
			</tr>
	</tbody>
</table>
<h2 id="server-side-strategies">Server-side Strategies</h2>
<h3 id="tool-result-clearing">Tool result clearing</h3>
<p>when conversation context grows beyond your configured threshold
Best  for agentic workflows with heavy tool use and Older tool results are no longer needed once Claude has processed them.</p>
<p>通过清楚oldest tool result并且使用占位文本进行替换来告知模型结果已经被移除
默认情况下,只有results会被移除,但是你也可以在配置文件中将clear_tool_call 甚至为True,这样会同时清楚tool_calls以及调用时的tool use parameters和tool_results</p>
<h3 id="think-block-clearing">Think block clearing</h3>
<p>The <code>clear_thinking_20251015</code> strategy manages <code>thinking</code> blocks in conversations when extended thinking is enabled. This strategy gives you control over thinking preservation: you can choose to keep more thinking blocks to maintain reasoning continuity, or clear them more aggressively to save context space.
用于启用了extend_thinking的会话中的think_blocks;
你可以选择保留更多的thinking_block也可以积极清理来节省上下文空间</p>
<p><strong>Default behavior:</strong> The default varies by model class.</p>
<table>
	<thead>
			<tr>
					<th>Model class</th>
					<th>Keep all prior thinking</th>
					<th>Keep only the last turn&rsquo;s thinking</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Opus</td>
					<td>Claude Opus 4.5 and later</td>
					<td>Claude Opus 4.1 and earlier</td>
			</tr>
			<tr>
					<td>Sonnet</td>
					<td>Claude Sonnet 4.6 and later</td>
					<td>Claude Sonnet 4.5 and earlier</td>
			</tr>
			<tr>
					<td>Haiku</td>
					<td>(none)</td>
					<td>All models through Claude Haiku 4.5</td>
			</tr>
			<tr>
					<td>Fable and Mythos</td>
					<td>All models</td>
					<td>(none)</td>
			</tr>
	</tbody>
</table>
<p>You can override the default,if your code runs across multiple models tiers,ser **keep **explicitly rather than relying on the per-model default</p>
<p>With interleaved thinking,there includes multiple thinking blocks</p>
<h3 id="context-editing-happens-server-side">Context editing happens server-side</h3>
<p>Context editing is applied server-side before the prompt reaches Claude.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Build An Orchestration Mode</title>
      <link>https://tuanzi-wow.cn/%E4%B8%8A%E4%B8%8B%E6%96%87%E5%B7%A5%E7%A8%8B/claude_context_management/build-an-orchestration-mode/</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/claude_context_management/build-an-orchestration-mode/</guid>
      <description>Build An Orchestration Mode相关学习笔记与实践要点。</description>
      <content:encoded><![CDATA[<h1 id="build-an-orchestration-mode">Build an orchestration mode</h1>
<p>Build a session-level mode that grants standing consent for multiagent fan-out, switched on and off with mid-conversation system messages.</p>
<p>会话级别的;持续性凭证;multiagent;mid-conversation</p>
<p>编排模式(orchestration mode)是一种会话级开关:当他开启时,model will pay most efforts to every request,先自行见检查和分析任务,然后默认将工作拆分给几个并发的子智能体
It is not an API parameter. It is built entirely from documented pieces</p>
<ol>
<li>1.An effort level: requests run at a documented effort value such as Max,there no other level higher than it</li>
<li>A mode reminder: a mid-conversation system message tells the model the mode is active, 每个几次对话发送一行通知
当推出时,会发出退出通知</li>
<li>Standing consent(持续授权) in the tool description:该模式开启时,对于每一个实质性的任务,都应该在不经过询问的情况下自己设计和运行一套工作流程</li>
</ol>
<p>该模式会造成成本的增加,原因有二:Max effort level;Multi-agents,subagents</p>
<h2 id="ser-up-the-loop">Ser up the loop</h2>
<p>MAX_CONCURRENT限制并发的subagents的数量
MAX_TOTAL_SUBTASKS在一次工作流中的排队的任务的数量
当DOC_TEST_MODE开启时,会将循环次数限制为一次,这样地自动化文本测试框架就可以快速完成编译并快速结束,而不需要运行完整地编排流程
但是在运行个人的用例时,请不要开启或者leave it unset,不然你就会进入文档测试模式</p>
<h2 id="define-the-mode-reminder">Define the mode reminder</h2>
<p>这些reminders都很简短,他们切换模式并且指向tool description
完整的文本只在刚开启时发送一次;the refresher每隔几轮对话发一次;退出通知只在退出的时候发送</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-gdscript3" data-lang="gdscript3"><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><h2 id="grant-standing-consent-in-the-tool-description">Grant standing consent in the tool description</h2>
<p>Workflow工具承载了真正的行为约定(behavioral contract):包括准入规则,持续授权,模型可以采用的质量保障模式等等
subagent还会获得一个report_findings工具,将他们的结果以JSON结构化的形式返回;而bash工具则是anthropic定义的bash_20250124工具,在本地运行</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 class="n">WORKFLOW_TOOL</span> <span class="o">=</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;Workflow&#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="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;Orchestrate a multiagent workflow: split a large task into independent subtasks &#34;</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;and run them as parallel agents, then collect their results.</span><span class="se">\n\n</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;Opt-in: only use this tool when the user explicitly asks for a workflow, or when a &#34;</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;system message confirms that orchestration mode is on.</span><span class="se">\n\n</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;Quality patterns: adversarial verification (a second wave of agents checks the first &#34;</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;wave&#39;s findings against the source), a completeness critic (one agent hunts for what &#34;</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;the others missed), and multiphase sequencing (understand, design, implement, and &#34;</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;review as separate workflow calls, reading results between phases). A useful default &#34;</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;is hybrid: scout inline first to discover the work-list, then fan out over it.</span><span class="se">\n\n</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;Granularity: scope each subtask to a distinct concern, component, or question rather &#34;</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;than per line or per file section. Scale the count to what the user asked for: a &#34;</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;focused review of a module of a few hundred lines rarely needs more than about ten &#34;</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;subtasks; a broad audit of a large codebase can justify more.</span><span class="se">\n\n</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;Standing consent: while a system message confirms orchestration mode is on, that &#34;</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;opt-in is standing. Author and run a workflow for every substantive task by default, &#34;</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;and lean toward verifying findings adversarially. Work solo only on conversational &#34;</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;turns or trivial mechanical edits. When a system message says the mode is off, &#34;</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;revert to the opt-in rule above.&#34;</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;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;subtasks&#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;array&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;items&#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></span><span class="line"><span class="cl">                <span class="s2">&#34;description&#34;</span><span class="p">:</span> <span class="s2">&#34;Independent subtask prompts to run as parallel agents&#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;subtasks&#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="n">BASH_TOOL</span> <span class="o">=</span> <span class="p">{</span><span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;bash_20250124&#34;</span><span class="p">,</span> <span class="s2">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;bash&#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">REPORT_TOOL</span> <span class="o">=</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;report_findings&#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="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;Report the final findings for your subtask. Call this exactly once, when you are &#34;</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;done investigating; it ends your task.&#34;</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;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;summary&#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;Two or three sentences of synthesis&#34;</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;findings&#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;array&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;items&#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;claim&#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;The finding, one sentence&#34;</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">                        <span class="s2">&#34;evidence&#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;How it was verified (file, line, or command output)&#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;severity&#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;enum&#34;</span><span class="p">:</span> <span class="p">[</span><span class="s2">&#34;high&#34;</span><span class="p">,</span> <span class="s2">&#34;medium&#34;</span><span class="p">,</span> <span class="s2">&#34;low&#34;</span><span class="p">,</span> <span class="s2">&#34;info&#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;claim&#34;</span><span class="p">,</span> <span class="s2">&#34;evidence&#34;</span><span class="p">,</span> <span class="s2">&#34;severity&#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;required&#34;</span><span class="p">:</span> <span class="p">[</span><span class="s2">&#34;summary&#34;</span><span class="p">,</span> <span class="s2">&#34;findings&#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></code></pre></td></tr></table>
</div>
</div><h2 id="run-the-bash-tool-locally">Run the bash tool locally</h2>
<p>bash处理器运行命令并带运行超时时间,捕获合并后的stderr和stdout并且截断输出,以防止单次输出占满上下文窗口
命令会在启动的文件夹内运行
当DOC_TEST_MODE开启时,框架会给bash命令提供一个临时的,小型的测试目录,并且在退出时删除
没有沙箱,
示例每次调用都会在一个全新的子shell中运行,而不是维持持久化对话
而在生产环境中的agent则应该接入到一个长期运行的subshell</p>
<h2 id="run-one-subagent">Run one subagent</h2>
<p>每个workflow的子任务都会称为一个独立的小型的带有bash工具的agent循环,并且effort与主循环相同
每个请求都会设置一个单独的超时时间,这样即使链接中断也只是子agent受影响而不会让整个工作流瘫痪停滞</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></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="k">def</span> <span class="nf">run_subagent</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">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="s2">&#34;&#34;&#34;One subagent: a small nested agent loop with the bash tool plus report_findings.
</span></span></span><span class="line"><span class="cl"><span class="s2">    Subagents inherit the main loop&#39;s effort level.&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="n">subagent_system</span> <span class="o">=</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;You are one agent in a larger parallel fan-out, assigned a single subtask. &#34;</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;Investigate it directly, using bash to check facts rather than guessing, and finish &#34;</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;by calling report_findings exactly once. Return findings, not narration.&#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">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">prompt</span><span class="p">}]</span>
</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_SUBAGENT_TURNS</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="n">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="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">subagent_system</span><span class="p">,</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">BASH_TOOL</span><span class="p">,</span> <span class="n">REPORT_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="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="n">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="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 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="n">text</span> <span class="o">+=</span> <span class="s2">&#34;</span><span class="se">\n\n</span><span class="s2">(warning: subagent 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 class="n">tool_results</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl">        <span class="n">report</span> <span class="o">=</span> <span class="n">None</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;report_findings&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">                <span class="n">report</span> <span class="o">=</span> <span class="n">json</span><span class="o">.</span><span class="n">dumps</span><span class="p">(</span><span class="n">block</span><span class="o">.</span><span class="n">input</span><span class="p">,</span> <span class="n">indent</span><span class="o">=</span><span class="mi">2</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="s2">&#34;Findings recorded.&#34;</span><span class="p">,</span> <span class="n">False</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="n">f</span><span class="s2">&#34;unknown tool: {block.name}&#34;</span><span class="p">,</span> <span class="n">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="k">if</span> <span class="n">report</span> <span class="n">is</span> <span class="ow">not</span> <span class="n">None</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="n">report</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">tool_results</span><span class="p">})</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="s2">&#34;(subagent hit the turn limit before finishing)&#34;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="journal-results-so-reruns-resume记录结果这样重新运行时可以接着执行">Journal results so reruns resume(记录结果这样重新运行时可以接着执行)</h2>
<p>该模式会开启许多子agent,重启的成本很高.而一个基于内容寻址的日志会使他具有幂等性(idempotent)
在分发智能体之前,先计算器prompt的SHA-256,并且在本地的JSON文件中查找这个哈希值,如果存在,则直接返回之前的结果
如果运行过程被中断,也只有那些从未被完成的子任务才会被重启
该日志会在不同的运行之间去重,但是不会在同一次fan-out中去重
如果想要重头开始执行,只需要删除这个日志文件即可</p>
<h2 id="fan-outthen-verify">Fan out,then verify</h2>
<p>扇出最多接受 <code>MAX_TOTAL_SUBTASKS</code> 个 prompt，并通过日志（journal）运行这些任务，同时最多允许 <code>MAX_CONCURRENT</code> 个任务处于执行中（PHP 版本则是顺序执行）。
它会<strong>隔离各个子任务的失败</strong>：某个子智能体出错时，只会将其降级为一个错误字符串，而不会导致整个运行流程终止。
第一轮执行完成后，会进行<strong>第二轮扇出</strong>，并复用相同的子智能体执行路径，对第一轮的每个结果进行尝试反驳：
每个验证器（verifier）都会根据<strong>原始来源重新推导和核实这些结论</strong>；如果无法确定，则默认判定为**“反驳（refuted）”**。
最终，<strong>原始结果和对应的验证结论（verdict）都会返回给编排器（orchestrator）</strong>，由编排器综合考虑两者。</p>
<h2 id="toggle-the-mode-with-mid-conversation-system-messages">Toggle the mode with mid-conversation system messages</h2>
<p>通过 mid-conversation来切换模式
先追加user_message,然后才是system-message(可能full text,也可能是定时的refresher,也可能是退出通知)
并且这满足了它的位置限制:
某个user turn之后(role: user的tool call也可以视为user turn),对应的assistant之前.或者最后面:
原因之前有,主要是为了prompt caching</p>
]]></content:encoded>
    </item>
    <item>
      <title>Mid-conversation-system-messages-and-tool-changes</title>
      <link>https://tuanzi-wow.cn/%E4%B8%8A%E4%B8%8B%E6%96%87%E5%B7%A5%E7%A8%8B/claude_context_management/mid-conversation-system-messages-and-tool-changes/</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/claude_context_management/mid-conversation-system-messages-and-tool-changes/</guid>
      <description>Mid-conversation-system-messages-and-tool-changes相关学习笔记与实践要点。</description>
      <content:encoded><![CDATA[<h1 id="mid-conversation-system-messages-and-tool-changes">Mid-conversation system messages and tool changes</h1>
<p>Change system instructions or tool availability partway through a conversation without invalidating the cached prefix that came before them.
在不使缓存失效的情况下,更改系统指令或者工具可用性
system instructions normally live in the top-level system field
it is great for prompt caching: because it is stable prefix
Mid-conversation system message  will not change the cached prefix ,and you append a {&ldquo;role&rdquo;: &ldquo;system&rdquo;},and this instruction is still applied ad system instruction rather than as a ordinary user text</p>
<h2 id="mid-conversation-tool-changes">Mid-conversation tool changes</h2>
<p>The tools array sets even earlier than  the top-level system field.
so editing it will make the whole cache invalided</p>
<p>Mid-conversation tool changes use <strong>tool_addition</strong> and <strong>tool_removal</strong> to offer a tool to model or withdraw it from a specific point in the conversation onward. The tool array never changes , so the prefix stays the same.</p>
<p><strong>tool_addition</strong> and <strong>tool_removal</strong> are content blocks in the <strong>content</strong> array of <strong>role : &ldquo;system&rdquo;</strong> message and they can be mixed with text blocks
The message follows the same placement rules as any mid-conversation system message</p>
<p>Each block&rsquo;s <code>tool</code> field <strong>references</strong> a tool rather than <strong>defining</strong> one: <code>{&quot;type&quot;: &quot;tool_reference&quot;, &quot;name&quot;: &quot;...&quot;}</code> names a tool declared in the request&rsquo;s <code>tools</code> array, and <a href="https://platform.claude.com/docs/en/agents-and-tools/mcp-connector">MCP connector</a> tools can be referenced individually with <code>mcp_tool_reference</code> (<code>server_name</code> and <code>name</code>) or as a whole toolset with <code>mcp_toolset_reference</code> (<code>server_name</code>). Referencing a name that is not declared in <code>tools</code> returns a 400 error.</p>
<p>可以使用defer_loading: true 来使得在tools offer的tool暂时隐藏,知道tool_addition激活它
并且tool_addition可以重新提供之前被 tool_removalde撤回的tool</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></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="n">client</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">anthropic</span><span class="p">.</span><span class="nf">Anthropic</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="n">response</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">client</span><span class="p">.</span><span class="n">beta</span><span class="p">.</span><span class="n">messages</span><span class="p">.</span><span class="k">create</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">model</span><span class="o">=</span><span class="s2">&#34;claude-opus-5&#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">max_tokens</span><span class="o">=</span><span class="mi">1024</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><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 class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><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="w">    </span><span class="c1"># cached prefix stays intact.
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">tools</span><span class="o">=</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;name&#34;</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;get_weather&#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;description&#34;</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Get the current weather for a location.&#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;input_schema&#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;type&#34;</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;object&#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;properties&#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;location&#34;</span><span class="p">:</span><span class="w"> </span><span class="err">{</span><span class="s2">&#34;type&#34;</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;string&#34;</span><span class="p">,</span><span class="w"> </span><span class="s2">&#34;description&#34;</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;City name&#34;</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="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="s2">&#34;required&#34;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&#34;location&#34;</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="err">}</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">messages</span><span class="o">=</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;role&#34;</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;user&#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;Say OK.&#34;</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="c1"># Withdraw get_weather from this point onward. The block references
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><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="w">        </span><span class="c1"># byte-identical and the cache still hits.
</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;role&#34;</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;system&#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="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;tool_removal&#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;tool&#34;</span><span class="p">:</span><span class="w"> </span><span class="err">{</span><span class="s2">&#34;type&#34;</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;tool_reference&#34;</span><span class="p">,</span><span class="w"> </span><span class="s2">&#34;name&#34;</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;get_weather&#34;</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="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="err">}</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="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="k">for</span><span class="w"> </span><span class="n">block</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">response</span><span class="p">.</span><span class="n">content</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">type</span><span class="w"> </span><span class="o">==</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="nf">print</span><span class="p">(</span><span class="n">block</span><span class="p">.</span><span class="kt">text</span><span class="p">)</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><ol>
<li>是role: system的content块</li>
<li>parameter: tool_reference  instead of tool_name</li>
</ol>
<h2 id="when-to-use-a-mid-conversation-system-message">When to use a mid-conversation system message</h2>
<p>prompt caching hashes the requests prefix in order: tools,system,message
Mid-conversation system let you add the instruction at the <strong>end</strong> of the message history instead great for matching the unchanged parts</p>
<p>A few situations where this matters:(随便看看就行)</p>
<ul>
<li><strong>Mid-session policy or persona changes.</strong> A long agentic session needs a new constraint (&ldquo;from now on, write all SQL as parameterized queries&rdquo;) after dozens of cached turns. Adding it to the top-level <code>system</code> field would re-process the entire history.</li>
<li><strong>Per-turn context that must be authoritative.</strong> You want to inject a freshness note, a session deadline, or a tool-availability change with system-level weight, and it changes too often to live in the cached prefix.</li>
<li><strong>Per-turn reminders that shouldn&rsquo;t pile up.</strong> A harness nudges the model after each batch of tool results (&ldquo;request independent reads together&rdquo;, &ldquo;the user hasn&rsquo;t heard from you in a while&rdquo;) and wants the model to see only the newest copy. A <a href="https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages#turn-scoped-system-messages">turn-scoped system message</a> renders for one turn and then costs nothing, without deleting anything from the history.</li>
<li><strong>State changes your application observes.</strong> Your application notices something Claude should treat as an operator-level fact: files changed on disk, the user toggled an auto-approve setting, available tools changed, or the remaining token budget dropped below a threshold.</li>
<li><strong>User input that should not interrupt an agentic loop.</strong> A user types a follow-up while Claude is still executing tools for the previous request. Relaying it as a system message after the next tool result lets Claude fold the new input into the work it is already doing, instead of treating it as a fresh request to switch to. See <a href="https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages#placement-after-tool-results">Placement after tool results</a>.</li>
<li><strong>Mode switches that grant standing permissions.</strong> A session-level mode can use a mid-conversation system message to grant standing consent to an expensive capability, such as automatically launching multiagent workflows, with a short refresher every several turns and an exit notice when the mode is turned off. For a worked example, see <a href="https://platform.claude.com/docs/en/build-with-claude/mid-conversation-effort-example">Build an orchestration mode</a>.</li>
</ul>
<p>A mid-conversation system message keeps that operator-level priority without paying the cache-miss cost of editing the top-level <code>system</code> field.</p>
<h2 id="how-it-works">How it works</h2>
<p>Add a message with &ldquo;role&rdquo; : &ldquo;system&rdquo; to the message array
Use a plain string or content blocks for content , the same as a user or assistant turn.</p>
<p>when the later and the earlier conflict, the later will precedence the earlier
mid-conversation system messages take precedence over the top-level <code>system</code> field for the turns that follow them</p>
<p>The position:
A mid-conversation system message must immediately follow a <code>user</code> turn (or an <code>assistant</code> turn ending in a server tool result), and must either be the last entry in <code>messages</code> or be immediately followed by an <code>assistant</code> turn.
Any other position, including between an <code>assistant</code> <code>tool_use</code> block and the <code>tool_result</code> that answers it, returns a 400 error.</p>
<h3 id="placement-after-tool-results">Placement after tool results</h3>
<p>Phrase the system content as context rather than as a command that overrides the user. State the fact (&ldquo;new input arrived from the user: X&rdquo;, &ldquo;the remaining token budget is now Y&rdquo;) and let Claude act on it. Claude is trained to resist instructions that appear to work against the user, and that protection still applies to the system role, so language such as &ldquo;ignore what the user said&rdquo; is less effective than stating what changed.</p>
<h3 id="turn-scoped-system-messages">Turn-scoped system messages</h3>
<p>要让有个role: system消息只作用与当前伦茨,可以设置它的clear_at,它的两个可选值:
&ldquo;never&rdquo;:默认值,该小心会包含在它的每一次请求中
next_user_message:限定为当前伦茨的turn-scope,只有当它后面没有role: user的消息是,其文本才会被渲染
而一个只包含tool_result block的用户小心也会被视为role: user消息
一旦后面出现了用户消息,他就会被清楚:它仍然保留在message array但是不会被渲染也不会被计入input_token</p>
<p>主要用途是在 tool loop中提供每一轮次的提醒,这个可以从上面那个(而一个只包含tool_result block的用户小心也会被视为role: user消息)特性进行设计</p>
<p>模型只能看到最后一个user message后的副本,因此消息不会叠加</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-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="s2">&#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="s2">&#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="s2">&#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="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;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="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 class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;thinking&#34;</span><span class="p">,</span> <span class="s2">&#34;thinking&#34;</span><span class="p">:</span> <span class="s2">&#34;&#34;</span><span class="p">,</span> <span class="s2">&#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="s2">&#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="s2">&#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="s2">&#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="s2">&#34;input&#34;</span><span class="p">:</span> <span class="p">{</span> <span class="s2">&#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="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 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;...&#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;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;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="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 class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;thinking&#34;</span><span class="p">,</span> <span class="s2">&#34;thinking&#34;</span><span class="p">:</span> <span class="s2">&#34;&#34;</span><span class="p">,</span> <span class="s2">&#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="s2">&#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="s2">&#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="s2">&#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="s2">&#34;input&#34;</span><span class="p">:</span> <span class="p">{</span> <span class="s2">&#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="s2">&#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="s2">&#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="s2">&#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="s2">&#34;input&#34;</span><span class="p">:</span> <span class="p">{</span> <span class="s2">&#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="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_02&#34;</span><span class="p">,</span> <span class="s2">&#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="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="s2">&#34;toolu_03&#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;...&#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="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;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;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="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 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>Rules for turn-scoped messages:</p>
<ul>
<li><strong>Re-send cleared messages verbatim.</strong> A cleared message is still part of the conversation history. Rebuilding it from current state (a fresh token count, a timestamp), dropping it as redundant, or changing its <code>clear_at</code> value is an edit to an earlier message. The prompt cache misses from that point, and on Claude Fable 5.1 every thinking block produced after it fails the <a href="https://platform.claude.com/docs/en/build-with-claude/thinking#preserved-in-conversation">conversation check</a>.</li>
<li><strong>Text only.</strong> <code>content</code> is one or more <code>text</code> blocks (or a string). <code>tool_addition</code> and <code>tool_removal</code> blocks return a 400 error on a turn-scoped message, and so does <code>output_config</code>. Use a separate <code>role: &quot;system&quot;</code> message without <code>clear_at</code> for those.</li>
<li><strong>No <code>cache_control</code> on its blocks.</strong> A cleared message is never part of a cache key, so a breakpoint on it could never match. Put the breakpoint on the last block of the preceding user turn instead, as the example does. The top-level <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#automatic-caching">automatic caching</a> field skips turn-scoped messages when it picks a breakpoint. On the request that clears a message, the reusable cached prefix ends at the user turn before it, so only the one assistant turn between that message and the new user message is reprocessed.</li>
<li><strong>Placement rules still apply</strong>, cleared or not. A turn-scoped message must follow a <code>user</code> turn (or an <code>assistant</code> turn ending in a server tool result) and precede an <code>assistant</code> turn or end the array, like any mid-conversation system message. One that ends the array always renders. One followed directly by another <code>user</code> message is a 400 error, not a cleared message: put all of a tool round&rsquo;s results in one user message and the reminders after it.</li>
<li><strong>Assistant turns don&rsquo;t clear it.</strong> A prefilled or <a href="https://platform.claude.com/docs/en/build-with-claude/handling-stop-reasons#pause-turn">paused</a> assistant turn after the message, or a server-side tool loop, adds no user message, so the message still renders on that continuation. To keep a reminder in view through a client-side tool loop, append it again after each <code>tool_result</code> message.</li>
<li><strong>Token counting follows what renders.</strong> A cleared message adds nothing to <code>usage.input_tokens</code> or to a <a href="https://platform.claude.com/docs/en/build-with-claude/token-counting">token count</a>.</li>
<li><strong>Imported history.</strong> In a transcript you construct in one step (few-shot examples, a migrated conversation), a turn-scoped message that already has an assistant turn and a user message after it is cleared from the first request and never renders. That is the right state for a per-turn reminder you are carrying over. Leave <code>clear_at</code> unset only on a message the model should see on every request.</li>
</ul>
<h2 id="combining-with-prompt-caching">Combining with prompt caching</h2>
<p>对话中途的系统消息（Mid-conversation 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">自动缓存（automatic caching）</a>字段，也可以是内容块上的<a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#explicit-cache-breakpoints">显式缓存断点（explicit breakpoint）</a>。对话中途的系统消息本身不会自动创建缓存条目；如果没有启用缓存，也就没有可以保留的缓存收益。</li>
<li><strong>像往常一样缓存稳定前缀。</strong> 将 <code>cache_control</code> 放在跨请求保持不变的最后一个内容块上。这个位置可以是顶层 <code>system</code> 字段的末尾、工具定义的末尾，或者消息历史中的某个稳定位置。</li>
<li><strong>将系统消息追加在缓存断点之后。</strong> 因为它位于已经缓存的前缀之后，所以不会改变前缀的哈希值，缓存仍然可以命中。</li>
<li><strong>对话中途的系统消息本身也可以被缓存。</strong> 一旦它进入对话，就会成为稳定历史的一部分。下一轮请求中，你可以将缓存断点向后移动到该系统消息之后（或者依赖<a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#automatic-caching">自动缓存（automatic caching）</a>自动将断点移动到那里），这样该系统消息就会像其他对话轮次一样从缓存中读取。</li>
</ul>
<h2 id="limitations">Limitations</h2>
<ul>
<li><strong>Not for the first message.</strong> A <code>system</code> message that carries content cannot be the first entry in <code>messages</code>. Use the top-level <code>system</code> field for instructions that apply from the very start.</li>
<li><strong>Placement is constrained.</strong> A <code>system</code> message that carries content (<code>text</code>, <code>tool_addition</code>, or <code>tool_removal</code> blocks) must immediately follow a <code>user</code> turn (including a <code>user</code> turn that carries <code>tool_result</code> blocks) or an <code>assistant</code> turn ending in a server tool result, and must precede an <code>assistant</code> turn or end the array. It cannot sit between a <code>tool_use</code> block and its <code>tool_result</code>. Placing it elsewhere returns a 400 error. One exception: <code>tool_addition</code> and <code>tool_removal</code> blocks are not accepted immediately after a <a href="https://platform.claude.com/docs/en/build-with-claude/handling-stop-reasons#pause-turn">paused</a> <code>assistant</code> turn (one ending in a server tool result), though <code>text</code> blocks are; resume the paused turn first, then send the tool change in the next <code>system</code> message. A message with empty <code>content</code> that only sets <a href="https://platform.claude.com/docs/en/build-with-claude/effort#change-effort-mid-conversation-beta"><code>output_config.effort</code></a> renders nothing at its position and is accepted anywhere in <code>messages</code>, including first or between an <code>assistant</code> turn and a <code>user</code> turn. Consecutive <code>system</code> messages are judged together, so adding a text-carrying message next to an effort-only one makes the whole group follow the content rule.</li>
<li><strong>Turn-scoped messages are text-only and re-sent verbatim.</strong> A <code>clear_at: &quot;next_user_message&quot;</code> message carries no <code>tool_addition</code>, <code>tool_removal</code>, <code>output_config</code>, or <code>cache_control</code>, and once cleared it must stay in <code>messages</code> byte-for-byte on later requests. See <a href="https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages#turn-scoped-system-messages">Turn-scoped system messages</a>.</li>
<li><strong>Not a place for untrusted content.</strong> Claude treats system content as operator instructions and follows it. Do not place text from outside the conversation, such as raw tool output, retrieved documents, or web content, directly in a system message; doing so gives that text operator-level authority. Keep that data in <code>tool_result</code> blocks and continue to follow <a href="https://platform.claude.com/docs/en/test-and-evaluate/strengthen-guardrails/mitigate-jailbreaks">Mitigate jailbreaks and prompt injections</a>.</li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>Mid-conversation</title>
      <link>https://tuanzi-wow.cn/%E4%B8%8A%E4%B8%8B%E6%96%87%E5%B7%A5%E7%A8%8B/claude_context_management/mid-conversation/</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/claude_context_management/mid-conversation/</guid>
      <description>Mid-conversation相关学习笔记与实践要点。</description>
      <content:encoded><![CDATA[<h1 id="mid-conversation-system-messages-and-tool-changes">Mid-conversation system messages and tool changes</h1>
<blockquote>
<p>原文：<a href="https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages">Mid-conversation system messages and tool changes</a></p>
</blockquote>
<p>在对话进行到一半时更改 system 指令或工具可用性，同时不使此前已缓存的 prefix 失效。</p>
<blockquote>
<p>关于 zero data retention (ZDR) 如何适用于本功能，参见 <a href="https://platform.claude.com/docs/en/manage-claude/api-and-data-retention">API and data retention</a>。</p>
</blockquote>
<p>System 指令通常放在顶层 <code>system</code> 字段中，位于对话里所有 message 之前。这个位置非常适合 <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching">prompt caching</a>：system prompt 属于稳定的 prefix，因此后续 turn 可以命中 cache。但如果你是在会话进行到一半才发现需要某条指令，这个位置就不合适了——因为修改顶层 <code>system</code> 字段会改变 prompt 的最开头，从而使其后全部内容的 cache 失效。</p>
<p>Mid-conversation system messages 补上了这个缺口。你不再去改顶层 <code>system</code> 字段，而是在新指令开始生效的那个对话位置，追加一条 <code>{&quot;role&quot;: &quot;system&quot;}</code> message。cached prefix 保持不变，下一次请求仍会从 cache 读取它；同时，新指令仍按 system instruction 生效，而不是普通的 user 文本。</p>
<blockquote>
<p>Mid-conversation system messages 可用于 Claude API、<a href="https://platform.claude.com/docs/en/build-with-claude/claude-in-amazon-bedrock">Claude in Amazon Bedrock</a> 以及 <a href="https://platform.claude.com/docs/en/build-with-claude/claude-on-vertex-ai">Google Cloud</a>。</p>
<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。使用 mid-conversation system messages <strong>不需要</strong> beta header。Claude Sonnet 5 不支持此功能，请改用顶层 <code>system</code> 字段。</p>
<p><a href="/%E4%B8%8A%E4%B8%8B%E6%96%87%E5%B7%A5%E7%A8%8B/claude_context_management/mid-conversation/#mid-conversation-tool-changes">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="/%E4%B8%8A%E4%B8%8B%E6%96%87%E5%B7%A5%E7%A8%8B/claude_context_management/mid-conversation/#turn-scoped-system-messages">Turn-scoped system messages</a>（<code>clear_at</code>）目前处于 beta，需要 <code>mid-conversation-system-clear-at-2026-08-21</code> 这个 beta header；可用模型与平台与 mid-conversation system messages 相同。</p>
</blockquote>
<h2 id="mid-conversation-tool-changes">Mid-conversation tool changes</h2>
<p><code>tools</code> 数组在 hashed request prefix 中的位置比顶层 <code>system</code> 字段还要靠前，因此改动它会使整段对话的 <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching">prompt cache</a> 失效。Mid-conversation tool changes 是 mid-conversation system messages 在工具侧的对应能力：不必把工具列表在整段对话生命周期内写死，而是可以在 turn 与 turn 之间改变向模型提供哪些工具——先在 <code>tools</code> 里一次性声明完整工具集，再通过 <code>tool_addition</code> 和 <code>tool_removal</code> 这两个 block，从对话中的某个位置起向模型提供某工具，或将其撤回。<code>tools</code> 数组本身始终不变，因此 cached prefix 保持完好。</p>
<p><code>tool_addition</code> 和 <code>tool_removal</code> 是 <code>role: &quot;system&quot;</code> message 的 <code>content</code> 数组中的 content block，可以与同一条 message 里的 <code>text</code> block 混用。该 message 的放置规则与任意 mid-conversation system message 相同（参见 <a href="/%E4%B8%8A%E4%B8%8B%E6%96%87%E5%B7%A5%E7%A8%8B/claude_context_management/mid-conversation/#limitations">Limitations</a>），变更从该位置起向后生效。每个 block 的 <code>tool</code> 字段是<strong>引用</strong>工具，而不是<strong>定义</strong>工具：<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>）引用整个 toolset。引用一个未在 <code>tools</code> 中声明的名字会返回 400 错误。</p>
<p><code>tools</code> 中声明的每个工具从对话一开始就会提供给模型，除非声明时带上 <code>defer_loading: true</code>——后者会把它扣住，直到某条 <code>tool_addition</code> block 把它亮出来。<code>tool_addition</code> 也可以重新提供此前被 <code>tool_removal</code> 撤回的工具。</p>
<blockquote>
<p>原文示例覆盖 cURL / CLI / Python / TypeScript / C# / Go / Java / PHP / Ruby。下文以 Python 为代表；其余语言的请求结构相同。使用本功能时需带上 beta header <code>mid-conversation-tool-changes-2026-07-01</code>。</p>
</blockquote>
<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></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"># 完整工具集在一开始就声明，且之后不再改动，因此 cached prefix 保持完好。</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"># 从这一位置起撤回 get_weather。该 block 按名字引用工具，而不是去改 `tools`，</span>
</span></span><span class="line"><span class="cl">        <span class="c1"># 因此更早的 turn 仍逐字节相同，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="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><p>Mid-conversation tool changes 目前处于 beta。使用时请在请求中带上 beta header <code>mid-conversation-tool-changes-2026-07-01</code>。</p>
<h2 id="when-to-use-a-mid-conversation-system-message">When to use a mid-conversation system message</h2>
<p><a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching">Prompt caching</a> 按如下顺序对 request prefix 做哈希：先 <code>tools</code>，再 <code>system</code>，再 <code>messages</code>。要命中 cache，prefix 必须与最近一次请求<strong>逐字节完全一致</strong>，直到 cache breakpoint 为止。</p>
<p>这个顺序意味着顶层 <code>system</code> 字段几乎位于 hashed prefix 的最开头。对它的任何改动——哪怕只是追加一句话——都会得到不同的 hash，于是这次请求会 miss cache：system prompt 本身，以及其后所有已缓存的 message，都无法复用。</p>
<p>Mid-conversation system messages 让你把指令加在 message history 的<strong>末尾</strong>。新指令之前的一切都没有改动，因此已有的 cache entry 仍然匹配，只有这条新 message 会作为 fresh input 被处理。</p>
<p>以下几种情况尤其值得这样做：</p>
<ul>
<li><strong>会话中途的 policy 或 persona 变更。</strong> 一段很长的 agentic session 已经缓存了几十个 turn，这时才需要加上新约束（例如 “from now on, write all SQL as parameterized queries”）。若把它写进顶层 <code>system</code> 字段，整段历史都要重新处理。</li>
<li><strong>必须具备权威性的 per-turn 上下文。</strong> 你想注入一条 freshness note、session deadline，或工具可用性变更，并且希望它带有 system 级别的权重；同时它变化太频繁，不适合放进 cached prefix。</li>
<li><strong>不应越积越多的 per-turn reminder。</strong> harness 在每批 tool result 之后提醒模型（例如 “request independent reads together”、“the user hasn&rsquo;t heard from you in a while”），并且希望模型只看到最新的那一份。<a href="/%E4%B8%8A%E4%B8%8B%E6%96%87%E5%B7%A5%E7%A8%8B/claude_context_management/mid-conversation/#turn-scoped-system-messages">Turn-scoped system message</a> 只在一个 turn 内渲染，之后不再消耗 token，也不必从 history 里删除任何内容。</li>
<li><strong>应用层观察到的状态变化。</strong> 你的应用注意到某些事实，希望 Claude 按 operator 级别对待：磁盘上的文件变了、用户切换了 auto-approve 设置、可用工具变了，或剩余 token budget 掉到阈值以下。</li>
<li><strong>不应打断 agentic loop 的用户输入。</strong> 用户在 Claude 仍在为上一次请求执行工具时输入了 follow-up。把它作为 system message 接在下一条 tool result 之后转发，可以让 Claude 把新输入并入正在进行的工作，而不是把它当成一次需要立刻切换过去的全新请求。参见 <a href="/%E4%B8%8A%E4%B8%8B%E6%96%87%E5%B7%A5%E7%A8%8B/claude_context_management/mid-conversation/#placement-after-tool-results">Placement after tool results</a>。</li>
<li><strong>授予 standing permission 的 mode 切换。</strong> 会话级 mode 可以用 mid-conversation system message 为某项昂贵能力授予 standing consent（持续性授权），例如自动启动 multiagent workflow；每隔若干 turn 发一条简短 refresher，mode 关闭时再发一条退出通知。完整示例见 <a href="https://platform.claude.com/docs/en/build-with-claude/mid-conversation-effort-example">Build an orchestration mode</a>。</li>
</ul>
<p>上述所有情况，你也可以把指令放进普通 <code>user</code> message，而 Claude 确实会遵循出现在 user turn 中的指令。差别在于优先级：<code>user</code> message 被视为来自终端用户，<code>system</code> message 被视为来自你——应用的 operator。两者冲突时，system 指令优先。因此，对于即便终端用户提出不同要求也应继续成立的 operator 级事实与约束，请使用 <code>system</code> role。Mid-conversation system message 能保住这种 operator 级优先级，又不必付出改动顶层 <code>system</code> 字段所带来的 cache miss 成本。</p>
<h2 id="how-it-works">How it works</h2>
<p>向 <code>messages</code> 数组追加一条 <code>&quot;role&quot;: &quot;system&quot;</code> 的 message。<code>content</code> 可以用纯字符串，也可以用 content block，与 <code>user</code> 或 <code>assistant</code> turn 相同。该指令从对话中的这个位置起向后生效。指令冲突时，后出现的 system message 优先于更早的；对跟随其后的那些 turn 而言，mid-conversation system messages 也优先于顶层 <code>system</code> 字段。</p>
<p>对整段对话都应生效的指令，仍然可以写在顶层 <code>system</code> 字段。Mid-conversation system messages 留给那些稍后才变得相关的指令，或那些你希望追加、同时又不想让 cached prefix 失效的指令。</p>
<p><code>role: &quot;system&quot;</code> message 还可以携带 <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">Per-message effort</a>。</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></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"># 自动 prompt caching：每次请求都会缓存截至目前的对话，</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># 下一次请求则从 cache 读取未改动的 prefix。</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"># reviewer 在会话中途意识到：所有建议还必须满足团队严格的 typing 政策。</span>
</span></span><span class="line"><span class="cl">        <span class="c1"># 把指令追加在这里，更早的 turn 仍逐字节相同，</span>
</span></span><span class="line"><span class="cl">        <span class="c1"># 因此上一次请求缓存下来的 prefix 仍会从 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><p>这个例子通过顶层 <code>cache_control</code> 字段启用了 <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#automatic-caching">automatic caching</a>。Prompt caching 是 opt-in 的：如果请求既没有 <code>cache_control</code> 字段（无论是 automatic，还是 <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#explicit-cache-breakpoints">explicit breakpoint</a>），就不会有任何内容被缓存，每次请求都按常规 input token 价格为整段对话付费。启用 caching 后，追加这条 system message 不会改动已经缓存的那些 turn，因此携带新指令的那次请求仍会从 cache 读取它们，而不是重新处理。Caching 还要求对话达到 <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#cache-limitations">minimum cacheable prompt length</a>；像上面这样短的例子会低于该阈值，所以在对话变长之前，<code>cache_creation_input_tokens</code> 和 <code>cache_read_input_tokens</code> 都会保持为 0。</p>
<p>一条 mid-conversation system message 必须紧跟在某个 <code>user</code> turn 之后（或紧跟在以 server tool result 结尾的 <code>assistant</code> turn 之后），并且它要么是 <code>messages</code> 的最后一项，要么紧跟着一个 <code>assistant</code> turn。携带 <code>tool_result</code> block 的 <code>user</code> message 也算：在 agentic loop 中，你可以把 system message 紧接在 tool result 之后、Claude 的下一 turn 之前。任何其他位置——包括夹在 <code>assistant</code> 的 <code>tool_use</code> block 与回答它的 <code>tool_result</code> 之间——都会返回 400 错误。</p>
<h3 id="placement-after-tool-results">Placement after tool results</h3>
<p>在 <a href="https://platform.claude.com/docs/en/agents-and-tools/tool-use/overview">agentic loop</a> 中，system message 应放在投递 tool result 的那条 <code>user</code> message 之后。你的应用也可以在这里转发用户在 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 content 写成<strong>上下文</strong>，而不是一条覆盖用户意图的命令。陈述事实（“new input arrived from the user: X”、“the remaining token budget is now Y”），然后让 Claude 据此行动。Claude 被训练为抵制那些看起来与用户作对的指令，这种保护对 system role 同样生效，因此 “ignore what the user said” 这类措辞，效果不如直接说明发生了什么变化。</p>
<p>这种模式用于转发<strong>本段对话终端用户</strong>的输入。不要用它传递 tool output、检索到的文档或其他第三方内容；那些内容应放在 <code>tool_result</code> block 中（参见 <a href="/%E4%B8%8A%E4%B8%8B%E6%96%87%E5%B7%A5%E7%A8%8B/claude_context_management/mid-conversation/#limitations">Limitations</a>）。</p>
<h3 id="turn-scoped-system-messages">Turn-scoped system messages</h3>
<p>若要把一条 <code>role: &quot;system&quot;</code> message 限定在当前 turn，设置它的 <code>clear_at</code> 字段。该字段只有两个取值：</p>
<ul>
<li><code>&quot;never&quot;</code>（默认）：只要请求里包含这条 message，它就会在其所在位置渲染。省略该字段效果相同。</li>
<li><code>&quot;next_user_message&quot;</code>：这条 message 是 <strong>turn-scoped</strong> 的。只有当 <code>messages</code> 中它后面还没有 <code>role: &quot;user&quot;</code> message 时，其文本才会被渲染。这里，只携带 <code>tool_result</code> block 的 user message 也算 user message。一旦后面出现了更新的 user message，该条就会被 <strong>cleared</strong>：它仍留在数组中，但不再渲染任何内容，也不再消耗 input token——本次请求以及之后每一次都是如此。</li>
</ul>
<p>Turn-scoped 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>。不带该 header 时，<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>主要用途是 tool loop 中的 per-turn reminder。每次希望模型看到这条提醒时，就把它追加在 <code>tool_result</code> message 之后，更早的副本原样留着。模型只会看到位于最后一条 user message 之后的那些副本，因此 reminder 不会越积越多。<code>messages</code> 中更早的内容没有任何改动，所以 <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching">prompt cache</a> 仍然匹配。在 Claude Fable 5.1 上，这样做还能让后续 <a href="https://platform.claude.com/docs/en/build-with-claude/thinking#preserved-in-conversation">thinking block 保持有效</a>：删除更早的 reminder 会改变那些 block 之前的对话，导致 conversation check 失败；而被 cleared 的 message 仍留在数组中，对话保持不变。</p>
<p>下面这次请求是 agent loop 中较后的一步。<code>messages[3]</code> 在更早的那次请求中被渲染过，当时它是数组的最后一项。一旦存在 <code>messages[5]</code>（一条更后的 user message），<code>messages[3]</code> 就被 cleared：cleared message 仍留在数组中，因此 <code>messages[4]</code> 里 thinking block 之前的对话没有变化，但模型不再看到它的文本。<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-scoped message 的规则：</p>
<ul>
<li><strong>按原文原样重新发送已 cleared 的 message。</strong> 一条 cleared message 仍是 conversation history 的一部分。按当前状态重建它（新的 token 计数、时间戳）、因为它冗余而丢掉它、或改它的 <code>clear_at</code> 值，都等于在编辑更早的 message。Prompt cache 会从该点起 miss；在 Claude Fable 5.1 上，它之后产生的每一个 thinking block 都会通不过 <a href="https://platform.claude.com/docs/en/build-with-claude/thinking#preserved-in-conversation">conversation check</a>。</li>
<li><strong>只允许文本。</strong> <code>content</code> 是一个或多个 <code>text</code> block（或字符串）。在 turn-scoped message 上使用 <code>tool_addition</code>、<code>tool_removal</code> 会返回 400 错误，<code>output_config</code> 同样不行。这些内容请用另一条不带 <code>clear_at</code> 的 <code>role: &quot;system&quot;</code> message。</li>
<li><strong>其 block 上不能带 <code>cache_control</code>。</strong> Cleared message 从不参与 cache key，因此打在它上面的 breakpoint 永远无法匹配。请像示例那样，把 breakpoint 放在前一个 user turn 的最后一个 block 上。顶层 <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#automatic-caching">automatic caching</a> 字段在选择 breakpoint 时会跳过 turn-scoped message。在把某条 message cleared 掉的那次请求上，可复用的 cached prefix 止于它之前的那个 user turn，因此只有「该 message 与新的 user message 之间」那一个 assistant turn 会被重新处理。</li>
<li><strong>放置规则始终生效</strong>，无论是否已被 cleared。Turn-scoped message 必须跟在 <code>user</code> turn 之后（或以 server tool result 结尾的 <code>assistant</code> turn 之后），并且位于 <code>assistant</code> turn 之前或作为数组末项，与任意 mid-conversation system message 相同。位于数组末尾的那一条始终会渲染。若它后面直接跟另一条 <code>user</code> message，得到的是 400 错误，而不是一条 cleared message：请把同一轮 tool 的全部 result 放进<strong>一条</strong> user message，再把 reminder 接在它后面。</li>
<li><strong>Assistant turn 不会把它 cleared。</strong> 该 message 之后若是一条 prefilled 或 <a href="https://platform.claude.com/docs/en/build-with-claude/handling-stop-reasons#pause-turn">paused</a> 的 assistant turn，或一次 server-side tool loop，都不会新增 user message，因此在那次续写上它仍会渲染。若要在 client-side tool loop 中让 reminder 持续可见，请在每条 <code>tool_result</code> message 之后再追加一次。</li>
<li><strong>Token 计数以实际渲染为准。</strong> Cleared message 不会计入 <code>usage.input_tokens</code>，也不会计入 <a href="https://platform.claude.com/docs/en/build-with-claude/token-counting">token count</a>。</li>
<li><strong>导入的 history。</strong> 若你一次性构造整份 transcript（few-shot 示例、迁移过来的对话），一条 turn-scoped message 后面如果已经既有 assistant turn 又有 user message，那么从第一次请求起它就是 cleared 的，永远不会渲染。对于你正在沿用的 per-turn reminder，这正是正确状态。只有希望模型在每次请求都看到的 message，才不要设置 <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-scoped reminder；下一次请求中，一旦出现更后的 user message，这条 reminder 仍留在数组里，但不再渲染：</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-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="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;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：本 turn 会渲染；一旦后面出现更新的 user message，就会被 cleared。</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><h2 id="combining-with-prompt-caching">Combining with prompt caching</h2>
<p>Mid-conversation system messages 与 <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching">prompt caching</a> 就是为一起使用而设计的：</p>
<ul>
<li><strong>显式启用 caching。</strong> 只有请求包含 <code>cache_control</code> 时才会发生 caching——可以是顶层 <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#automatic-caching">automatic caching</a> 字段，也可以是某个 content block 上的 <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#explicit-cache-breakpoints">explicit breakpoint</a>。Mid-conversation system message 本身不会创建 cache entry；若不启用 caching，也就没有可保全的节省。</li>
<li><strong>照常缓存稳定的 prefix。</strong> 把 <code>cache_control</code> 放在跨请求保持不变的最后一个 block 上，无论那是顶层 <code>system</code> 字段的末尾、工具定义的末尾，还是 message history 中某个稳定位置。</li>
<li><strong>把 system message 追加在 breakpoint 之后。</strong> 因为它位于 cached prefix 之后，不会改变 prefix hash，cache 仍然命中。</li>
<li><strong>Mid-conversation system message 本身也可被缓存。</strong> 一旦它进入对话，就成为稳定 history 的一部分。下一 turn 你可以把 cache breakpoint 移过它（或依赖 <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#automatic-caching">automatic caching</a> 自动前移），这条 system message 就会像其他 turn 一样从 cache 读取。</li>
</ul>
<p>避免编辑或删除已经发送过的 mid-conversation system message。与改动更早的任意 message 一样，这会从该点起使 cache 失效。在 Claude Fable 5.1 上，它还会使之后每一个 assistant turn 中的 <a href="https://platform.claude.com/docs/en/build-with-claude/thinking#preserved-in-conversation">thinking block</a> 失效。只应对单个 turn 生效的指导，请使用 <a href="/%E4%B8%8A%E4%B8%8B%E6%96%87%E5%B7%A5%E7%A8%8B/claude_context_management/mid-conversation/#turn-scoped-system-messages">turn-scoped system message</a>，并把它留在原位。若指令需要演进，请追加一条新的 system message，而不是改写旧的。连续的 system message 会被接受，并视为同一个 system section，整体仍遵循同一套放置规则。</p>
<h2 id="limitations">Limitations</h2>
<ul>
<li><strong>不能作为第一条 message。</strong> 携带 content 的 <code>system</code> message 不能是 <code>messages</code> 的第一项。从一开始就应生效的指令，请使用顶层 <code>system</code> 字段。</li>
<li><strong>放置位置受限。</strong> 携带 content（<code>text</code>、<code>tool_addition</code> 或 <code>tool_removal</code> block）的 <code>system</code> message 必须紧跟在 <code>user</code> turn 之后（包括携带 <code>tool_result</code> block 的 <code>user</code> turn），或紧跟在以 server tool result 结尾的 <code>assistant</code> turn 之后，并且必须位于 <code>assistant</code> turn 之前或作为数组末项。它不能夹在 <code>tool_use</code> block 与对应的 <code>tool_result</code> 之间。放在其他位置会返回 400 错误。有一个例外：<code>tool_addition</code> 和 <code>tool_removal</code> block <strong>不能</strong>紧接在 <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 结尾的那条）之后，尽管 <code>text</code> block 可以；请先恢复被 pause 的 turn，再在下一条 <code>system</code> message 中发送工具变更。一条 <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> 的 message 在其所在位置不渲染任何内容，可以出现在 <code>messages</code> 的任意位置，包括第一项，或夹在 <code>assistant</code> turn 与 <code>user</code> turn 之间。连续的 <code>system</code> message 会被一并判定，因此若在一条仅含 effort 的 message 旁边再加一条带文本的 message，整组都会按「带 content」的规则处理。</li>
<li><strong>Turn-scoped message 只能是文本，且必须按原文原样重发。</strong> <code>clear_at: &quot;next_user_message&quot;</code> 的 message 不能携带 <code>tool_addition</code>、<code>tool_removal</code>、<code>output_config</code> 或 <code>cache_control</code>；一旦被 cleared，后续请求必须把它逐字节原样留在 <code>messages</code> 中。参见 <a href="/%E4%B8%8A%E4%B8%8B%E6%96%87%E5%B7%A5%E7%A8%8B/claude_context_management/mid-conversation/#turn-scoped-system-messages">Turn-scoped system messages</a>。</li>
<li><strong>不要放入不可信内容。</strong> Claude 把 system content 当作 operator 指令并会遵循它。不要把对话之外的文本——例如原始 tool output、检索到的文档或网页内容——直接放进 system message；那样会赋予这些文本 operator 级权威。把那些数据放在 <code>tool_result</code> block 中，并继续遵循 <a href="https://platform.claude.com/docs/en/test-and-evaluate/strengthen-guardrails/mitigate-jailbreaks">Mitigate jailbreaks and prompt injections</a>。</li>
</ul>
<h2 id="related">Related</h2>
<table>
	<thead>
			<tr>
					<th>文档</th>
					<th>说明</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching">Prompt caching</a></td>
					<td>Caching 如何工作、breakpoint 放在哪里，以及如何读取 cache usage 字段。</td>
			</tr>
			<tr>
					<td><a href="https://platform.claude.com/docs/en/build-with-claude/cache-diagnostics">Cache diagnostics</a></td>
					<td>当预期的 cache hit 没有发生时，精确定位两次请求从哪里开始分叉。</td>
			</tr>
			<tr>
					<td><a href="https://platform.claude.com/docs/en/build-with-claude/working-with-messages">Using the Messages API</a></td>
					<td>Message 结构、多轮对话，以及 <code>system</code> 字段。</td>
			</tr>
			<tr>
					<td><a href="https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/claude-prompting-best-practices">Prompting best practices</a></td>
					<td>如何写有效的 prompt 与 system 指令。</td>
			</tr>
			<tr>
					<td><a href="https://platform.claude.com/docs/en/agents-and-tools/tool-use/overview">Tool use with Claude</a></td>
					<td><code>tool_use</code> 与 <code>tool_result</code> block 在 <code>messages</code> 数组中的结构。</td>
			</tr>
	</tbody>
</table>
]]></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/claude_context_management/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/claude_context_management/prompt-caching/</guid>
      <description>Prompt Caching相关学习笔记与实践要点。</description>
      <content:encoded><![CDATA[<h1 id="prompt-caching">Prompt Caching</h1>
<p>使用cache_control来缓存提示词前缀,使用自动缓存或者使用显示缓存断点:具有5分钟或者1h的存活时间的断点</p>
<p>Prompt caching允许你从提示词中的特定前缀继续处理,来优化API的使用</p>
<ul>
<li>
<p><strong><a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#automatic-caching">Automatic caching</a></strong>: Add a single <code>cache_control</code> field at the top level of your request. The system automatically applies the cache breakpoint to the last cacheable block and moves it forward as conversations grow. Best for multi-turn conversations where the growing message history should be cached automatically.</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-fallback" data-lang="fallback"><span class="line"><span class="cl">client = anthropic.Anthropic()
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">response = client.messages.create(
</span></span><span class="line"><span class="cl">    model=&#34;claude-opus-5&#34;,
</span></span><span class="line"><span class="cl">    max_tokens=1024,
</span></span><span class="line"><span class="cl">    cache_control={&#34;type&#34;: &#34;ephemeral&#34;},
</span></span><span class="line"><span class="cl">    system=&#34;You are a helpful assistant that remembers our conversation.&#34;,
</span></span><span class="line"><span class="cl">    messages=[
</span></span><span class="line"><span class="cl">        {&#34;role&#34;: &#34;user&#34;, &#34;content&#34;: &#34;My name is Alex. I work on machine learning.&#34;},
</span></span><span class="line"><span class="cl">        {
</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;Nice to meet you, Alex! How can I help with your ML work today?&#34;,
</span></span><span class="line"><span class="cl">        },
</span></span><span class="line"><span class="cl">        {&#34;role&#34;: &#34;user&#34;, &#34;content&#34;: &#34;What did I say I work on?&#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">print(response.usage.model_dump_json())
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p><strong><a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#explicit-cache-breakpoints">Explicit cache breakpoints</a></strong>: Place <code>cache_control</code> directly on individual content blocks for fine-grained control over exactly what gets cached.</p>
</li>
</ul>
<p>其中都有breakpoint的存在,由此可知breakpoint的作用时为显式划分缓存地边界</p>
<p>我刚去学习了一下机制:
首先.
有一个消息队列,在它的最前面有形如:
system prompt,tools,agent.md(项目级别文档,看自己的harness规定)等等(这些是看harness规定地),
然后每次新的对话,就会在消息队列中新增内容,并且在automatic的情况下,就会不断地移动断点来显式标注prompt prefix地边界,这是客户端的内容
然后发送给服务端后,在推理过程中,会从前缀开始一个token一个token地进行比对,命中的部分就会复用KV cache中已有的部分
而未命中的部分就会创建新的KV
Prefix Cache 是连续的：从 Prompt 开头开始匹配；第一个 token mismatch 出现后，该缓存链在这里截断，后续内容需要重新 Prefill</p>
<p>下面有个例子,自己看</p>
<p>上面算是题外话,接下来继续:</p>
<h2 id="how-prompt-caching-works">How prompt caching works</h2>
<h2 id="how-prompt-caching-works-1">How prompt caching works</h2>
<p>When you send a request with prompt caching enabled:</p>
<ol>
<li>The system checks if a prompt prefix, up to a specified cache breakpoint, is already cached from a recent query.</li>
<li>If found, it uses the cached version, reducing processing time and costs.</li>
<li>Otherwise, it processes the full prompt and caches the prefix once the response begins.
但是并不是全面重新cache哦</li>
</ol>
<p>缓存的生命周期是从这条请求的开始就开始计算了,而不是从response开始计算,一般默认是5分钟
那有人就会问了(其实是我):我早上开了一个会话,下午继续问.缓存是不是就失效了?是的
那么还有人就要问:TTL五分钟,我一次会话都不止
实际上,只要你有新的information产生并会先hit 然后创建新的cache内容或者你不断地hit cache,它的生命周期会一直延续下去,比如你不断调用工具之类的,so don&rsquo;t worry
不过如果你觉得5分钟太短了,可以有1h的,不过那是另外的价钱</p>
<h2 id="automatic-caching">Automatic caching</h2>
<h3 id="how-automatic-caching-works-in-multi-turn-conversations">How automatic caching works in multi-turn conversations</h3>
<p>With automatic caching, the cache point moves forward automatically as conversations grow. Each new request caches everything up to the last cacheable block, and previous content is read from cache.</p>
<table>
	<thead>
			<tr>
					<th>Request</th>
					<th>Content</th>
					<th>Cache behavior</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Request 1</td>
					<td>System + User(1) + Asst(1) + <strong>User(2)</strong> ◀ cache</td>
					<td>Everything written to cache</td>
			</tr>
			<tr>
					<td>Request 2</td>
					<td>System + User(1) + Asst(1) + User(2) + Asst(2) + <strong>User(3)</strong> ◀ cache</td>
					<td>System through User(2) read from cache; Asst(2) + User(3) written to cache</td>
			</tr>
			<tr>
					<td>Request 3</td>
					<td>System + User(1) + Asst(1) + User(2) + Asst(2) + User(3) + Asst(3) + <strong>User(4)</strong> ◀ cache</td>
					<td>System through User(3) read from cache; Asst(3) + User(4) written to cache</td>
			</tr>
	</tbody>
</table>
<h3 id="ttl-support">TTL support</h3>
<p>y default, automatic caching uses a 5-minute TTL. You can specify a 1-hour TTL at 2x the base input token price:</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-fallback" data-lang="fallback"><span class="line"><span class="cl">{ &#34;cache_control&#34;: { &#34;type&#34;: &#34;ephemeral&#34;, &#34;ttl&#34;: &#34;1h&#34; } }
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="combining-with-block-level-caching">Combining with block-level caching</h3>
<p>自动缓存与<a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#explicit-cache-breakpoints">显式缓存断点（explicit cache breakpoints）</a>兼容。当两者一起使用时，<strong>自动缓存断点会占用 4 个可用缓存断点槽位中的一个</strong></p>
<h3 id="what-stays-the-same">what stays the same</h3>
<p>自动缓存使用相同的底层缓存基础设施。其<strong>定价、最低 Token 数量要求、上下文顺序要求，以及 20 个 block 的回溯窗口</strong>，都与显式缓存断点的规则相同。</p>
<h3 id="edge-cases">Edge cases</h3>
<ul>
<li>If the last block already has an explicit <code>cache_control</code> with the same TTL, automatic caching is a no-op.</li>
<li>If the last block has an explicit <code>cache_control</code> with a different TTL, the API returns a 400 error.</li>
<li>If 4 explicit block-level breakpoints already exist, the API returns a 400 error (no slots left for automatic caching).</li>
<li>If the last block is not eligible as an automatic cache breakpoint target, the system silently walks backwards to find the nearest eligible block. If none is found, caching is skipped.</li>
</ul>
<h2 id="explicit-cache-breakpoints">Explicit cache breakpoints</h2>
<p>This is useful when you need to cache different sections that change at different frequencies, or need fine-grained control over exactly what gets cached.
适用于你想要控制缓存的block</p>
<h3 id="how-automatic-prefix-checking-works">How automatic prefix checking works</h3>
<h4 id="three-core-principle">Three core principle</h4>
<ul>
<li><strong>Cache writes happen only at your breakpoint.</strong></li>
<li><strong>Cache reads look backward for entries that prior requests wrote</strong></li>
<li><strong>The lookback window is 20 blocks.</strong></li>
</ul>
<p>简言之:只在断点处写入;会向前回溯(指的是在不匹配的情况下,镶向前回溯);回溯窗口为20个Block(最多回溯20个窗口,如果超过了.就会停止检查)</p>
<p><strong>Example: Lookback in a growing conversation</strong></p>
<p>You append new blocks each turn and set <code>cache_control</code> on the final block of each request:</p>
<ul>
<li><strong>Turn 1:</strong> 10 blocks, breakpoint on block 10. No prior cache entries exist. The system writes an entry at block 10.</li>
<li><strong>Turn 2:</strong> 15 blocks, breakpoint on block 15. Block 15 has no entry, so the system walks back to block 10 and finds the turn-1 entry. Cache hit at block 10; the system processes only blocks 11 through 15 fresh and writes a new entry at block 15.</li>
<li><strong>Turn 3:</strong> 35 blocks, breakpoint on block 35. The system checks 20 positions (blocks 35 through 16) and finds nothing. The turn-2 entry at block 15 is one position outside the window, so there is no cache hit. Adding a second breakpoint at block 15 starts a second lookback window there, which finds the turn-2 entry.</li>
</ul>
<p><strong>核心要点：</strong> 将 <code>cache_control</code> 放在<strong>跨请求保持不变的、最后一个 block</strong> 上，这样你希望共享同一个缓存的请求就可以复用该缓存。</p>
<p>在不断增长的对话中，只要每一轮新增的内容少于 <strong>20 个 block</strong>，将缓存断点放在最后一个 block 上就可以正常工作：之前的内容不会发生变化，因此下一次请求的回溯机制能够找到上一次请求写入的缓存。</p>
<p>对于带有<strong>变化后缀</strong>的提示词（例如时间戳、每次请求特有的上下文、用户当前发送的消息），应该将缓存断点放在<strong>静态前缀的末尾</strong>，而不是放在会发生变化的 block 上。</p>
<h4 id="when-to-use-multiple-breakpoints">When to use multiple breakpoints</h4>
<p>最多4个断点,应用情景如下:</p>
<ul>
<li>Cache different sections that change at different frequencies (for example, tools rarely change, but context updates daily)</li>
<li>Have more control over exactly what gets cached</li>
<li>Ensure a cache hit when a growing conversation pushes your breakpoint 20 or more blocks past the last cache write</li>
</ul>
<p>对于一次write,超过20个block会导致`miss</p>
<h3 id="understanding-cache-breakpoints-cost">Understanding cache breakpoints cost</h3>
<p>断点本身不付费
付费的是:缓存读写和常规输入</p>
<h2 id="caching-strategies-and-considerations">Caching strategies and considerations</h2>
<h3 id="limitations">Limitations:</h3>
<p>the minimum cacheable prompt length is:</p>
<table>
	<thead>
			<tr>
					<th>Minimum cacheable length</th>
					<th>模型</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><strong>512</strong></td>
					<td>Claude Fable 5.1、Claude Mythos 5.1、Claude Opus 5、Claude Fable 5、Claude Mythos 5</td>
			</tr>
			<tr>
					<td><strong>1,024</strong></td>
					<td>Claude Opus 4.8、Claude Sonnet 5、Claude Sonnet 4.6、Claude Sonnet 4.5、Claude Opus 4.1、Claude Opus 4、Claude Sonnet 4</td>
			</tr>
			<tr>
					<td><strong>2,048</strong></td>
					<td>Claude Mythos Preview、Claude Opus 4.7、Claude Haiku 3.5</td>
			</tr>
			<tr>
					<td><strong>4,096</strong></td>
					<td>Claude Opus 4.6、Claude Opus 4.5、Claude Haiku 4.5</td>
			</tr>
	</tbody>
</table>
<p>To verify whether a prompt was cached, check the <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#tracking-cache-performance">response usage fields</a>: if both <code>cache_creation_input_tokens</code> and <code>cache_read_input_tokens</code> are 0, the prompt was not cached (likely because it did not meet the minimum length requirement).</p>
<h3 id="what-can-be-cached">what can be cached</h3>
<ul>
<li>Tools: Tool definitions in the <code>tools</code> array</li>
<li>System messages: Content blocks in the <code>system</code> array</li>
<li>Text messages: Content blocks in the <code>messages.content</code> array, for both user and assistant turns</li>
<li>Images &amp; Documents: Content blocks in the <code>messages.content</code> array, in user turns</li>
<li>Tool use and tool results: Content blocks in the <code>messages.content</code> array, in both user and assistant turns</li>
</ul>
<h3 id="what-cannot-be-cached">what cannot be cached</h3>
<ul>
<li>
<p>Thinking blocks cannot be cached directly with <code>cache_control</code>. However, thinking blocks CAN be cached alongside other content when they appear in previous assistant turns. When cached this way, they DO count as input tokens when read from cache.</p>
</li>
<li>
<p>Sub-content blocks (like <a href="https://platform.claude.com/docs/en/build-with-claude/citations">citations</a>) themselves cannot be cached directly. Instead, cache the top-level block.</p>
<p>In the case of citations, the top-level document content blocks that serve as the source material for citations can be cached. This allows you to use prompt caching with citations effectively by caching the documents that citations will reference.</p>
</li>
<li>
<p>Empty text blocks cannot be cached.</p>
</li>
</ul>
<h3 id="what-invalidates-the-cache">What invalidates the cache</h3>
<p>Modifications to cached content can invalidate some or all of the cache.</p>
<table>
	<thead>
			<tr>
					<th>What changes</th>
					<th>Tools cache</th>
					<th>System cache</th>
					<th>Messages cache</th>
					<th>Impact</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><strong>Tool definitions</strong></td>
					<td>✘</td>
					<td>✘</td>
					<td>✘</td>
					<td>Modifying tool definitions (names, descriptions, parameters) invalidates the entire cache</td>
			</tr>
			<tr>
					<td><strong>Web search toggle</strong></td>
					<td>✓</td>
					<td>✘</td>
					<td>✘</td>
					<td>Enabling/disabling web search modifies the system prompt</td>
			</tr>
			<tr>
					<td><strong>Citations toggle</strong></td>
					<td>✓</td>
					<td>✘</td>
					<td>✘</td>
					<td>Enabling/disabling citations modifies the system prompt</td>
			</tr>
			<tr>
					<td><strong>Speed setting</strong></td>
					<td>✓</td>
					<td>✘</td>
					<td>✘</td>
					<td>Switching between <a href="https://platform.claude.com/docs/en/build-with-claude/fast-mode"><code>speed: &quot;fast&quot;</code> and standard speed</a> invalidates system and message caches</td>
			</tr>
			<tr>
					<td><strong>Tool choice</strong></td>
					<td>✓</td>
					<td>✓</td>
					<td>✘</td>
					<td>Changes to <code>tool_choice</code> parameter only affect message blocks</td>
			</tr>
			<tr>
					<td><strong>Images</strong></td>
					<td>✓</td>
					<td>✓</td>
					<td>✘</td>
					<td>Adding/removing images anywhere in the prompt affects message blocks</td>
			</tr>
			<tr>
					<td><strong>Thinking parameters</strong></td>
					<td>Model-specific</td>
					<td>Model-specific</td>
					<td>✘</td>
					<td>The thinking configuration (mode, and <code>budget_tokens</code> in extended mode) is rendered into the prompt, so changing it always invalidates message blocks; tool and system caches are also invalidated on models that render the configuration ahead of them. See <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 setting</strong></td>
					<td>Model-specific</td>
					<td>Model-specific</td>
					<td>✘</td>
					<td>Changing the <a href="https://platform.claude.com/docs/en/build-with-claude/effort"><code>output_config.effort</code></a> value always invalidates message blocks, with the same model-specific effect on tool and system caches as thinking parameters. Setting effort explicitly to the model&rsquo;s default is equivalent to omitting it and does not invalidate. On models that support <a href="https://platform.claude.com/docs/en/build-with-claude/effort#change-effort-mid-conversation-beta">per-message effort</a>, an effort change carried in a <code>role: &quot;system&quot;</code> message inside <code>messages</code> leaves the cached prefix intact.</td>
			</tr>
			<tr>
					<td><strong>Non-tool results passed to extended thinking requests</strong></td>
					<td>✓</td>
					<td>✓</td>
					<td>Model-specific</td>
					<td>On Opus 4.5+ and Sonnet 4.6+, thinking blocks are preserved by default, so the cache remains valid (✓). On earlier Opus/Sonnet models and all Haiku models, all previously-cached thinking blocks are stripped from context, and any messages that follow those thinking blocks are removed from the cache (✘). For more details, see <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>Dropped thinking blocks</strong></td>
					<td>✓</td>
					<td>✓</td>
					<td>✘</td>
					<td>When the API drops a Claude Fable 5.1 or Claude Mythos 5.1 thinking block that isn&rsquo;t <a href="https://platform.claude.com/docs/en/build-with-claude/thinking#preserved-thinking">preserved</a> on that request (for example, one you replay to an earlier model), the cached prefix changes from that block&rsquo;s position onward on that request. Blocks the receiving model can read, passed back unchanged, keep the cache intact.</td>
			</tr>
	</tbody>
</table>
<h3 id="tracking-cache-preformance">Tracking cache preformance</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></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><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>计费则是在对应的部分乘上price</p>
<h3 id="understanding-the-token-breakdown"><strong>Understanding the token breakdown</strong></h3>
<h3 id="the-input_tokens-field-represents-only-the-tokens-that-come-after-the-last-cache-breakpoint-in-your-request---not-all-the-input-tokens-you-sent">The <code>input_tokens</code> field represents only the tokens that come <strong>after the last cache breakpoint</strong> in your request - not all the input tokens you sent.</h3>
<p>To calculate total input tokens:</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-fallback" data-lang="fallback"><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>Spatial explanation:</strong></p>
<ul>
<li><code>cache_read_input_tokens</code> = tokens before breakpoint already cached (reads)</li>
<li><code>cache_creation_input_tokens</code> = tokens before breakpoint being cached now (writes)</li>
<li><code>input_tokens</code> = tokens after your last breakpoint (not eligible for cache)</li>
</ul>
<p><strong>Example:</strong> If you have a request with 100,000 tokens of cached content (read from cache), 0 tokens of new content being cached, and 50 tokens in your user message (after the cache breakpoint):</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>Total input tokens processed:</strong> 100,050 tokens</li>
</ul>
<p>This is important for understanding both costs and rate limits, as <code>input_tokens</code> will typically be much smaller than your total input when using caching effectively.</p>
<h3 id="caching-with-thinking-blocks">Caching with thinking blocks</h3>
<p>thinking blocks在不同cache策略下的缓存方法:
在auto:alongside other content
不能直接缓存,和其他内容一起,比如tool call</p>
<p>**Input token counting:**当think block在缓存中被读,就会被视为input_token</p>
<h3 id="cache-storage-and-sharin">Cache storage and sharin</h3>
<p>Prompt caching uses <a href="https://platform.claude.com/docs/en/manage-claude/workspaces">workspace</a>-level isolation.
Caches are isolated between organizations.
Caches are also isolated per workspace within an organization
<strong>Exact matching:</strong> Cache hits require 100% identical prompt segments, including all text and images up to and including the block marked with cache control.
<strong>Output token generation:</strong> Prompt caching has no effect on output token generation. The response you receive is identical to what you would get if prompt caching were not used.(显而易见的,只是费用有区别罢了)</p>
<h3 id="best-practices-for-effective-caching">Best practices for effective caching</h3>
<p>To optimize prompt caching performance:</p>
<ul>
<li>Start with <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#automatic-caching">automatic caching</a> for multi-turn conversations. It handles breakpoint management automatically.</li>
<li>Use <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#explicit-cache-breakpoints">explicit block-level breakpoints</a> when you need to cache different sections with different change frequencies.</li>
<li>Cache stable, reusable content like system instructions, background information, large contexts, or frequent tool definitions.</li>
<li>Place cached content at the prompt&rsquo;s beginning for best performance.</li>
<li>Use cache breakpoints strategically to separate different cacheable prefix sections.</li>
<li>Place the breakpoint on the last block that stays identical across requests. For a prompt with a static prefix and a varying suffix (timestamps, per-request context, the incoming message), that is the end of the prefix, not the varying block.</li>
<li>Regularly analyze cache hit rates and adjust your strategy as needed.</li>
</ul>
<h3 id="optimizing-for-different-use-cases泛话懒得看">Optimizing for different use cases(泛话,懒得看)</h3>
<p>对话式智能体（Conversational agents）： 降低长对话的成本和延迟，尤其适用于包含较长指令或上传文档的对话。</p>
<p>编程助手（Coding assistants）： 通过在提示词中保留代码库的相关部分，或代码库的摘要版本，提升代码自动补全和代码库问答的效果。</p>
<p>大型文档处理（Large document processing）： 将完整的长篇材料（包括图片）放入提示词中，而不会增加响应延迟。</p>
<p>详细的指令集（Detailed instruction sets）： 通过共享大量指令、流程和示例，让 Claude 的响应更加符合要求。开发者通常会在提示词中加入一两个示例，但借助提示词缓存，可以通过加入 20 个以上不同的高质量答案示例，获得更好的性能。</p>
<p>智能体工具调用（Agentic tool use）： 提升涉及多次工具调用和迭代式代码修改的场景的性能，因为每一步通常都需要发起一次新的 API 请求。</p>
<p>与书籍、论文、文档、播客文字稿及其他长篇内容对话： 通过将完整文档嵌入提示词，让任何知识库都变得生动，并允许用户向其提问。</p>
<h3 id="troubleshooting-common-issues也是懒得看">Troubleshooting common issues(也是,懒得看)</h3>
<p>If experiencing unexpected behavior:</p>
<p><a href="https://platform.claude.com/docs/en/build-with-claude/cache-diagnostics">Cache diagnostics</a> (beta) has the API compare consecutive requests and report exactly where the prompt prefix diverged, which automatically handles many of the steps in this list.</p>
<ul>
<li>Ensure cached sections are identical across calls. For explicit breakpoints, verify that <code>cache_control</code> markers are in the same locations</li>
<li>Check that calls are made within the cache lifetime (5 minutes by default)</li>
<li>Verify that <code>tool_choice</code>, image usage, the thinking configuration, and <code>output_config.effort</code> remain consistent between calls</li>
<li>Validate that you are caching at least the minimum number of tokens for your model and platform (see <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#cache-limitations">Cache limitations</a>)</li>
<li>Confirm your breakpoint is on a block that stays identical across requests. Cache writes happen only at the breakpoint, and if that block changes (timestamps, per-request context, the incoming message), the prefix hash never matches. The lookback does not find stable content behind the breakpoint; it only finds entries that earlier requests wrote at their own breakpoints</li>
<li>Verify that the keys in your <code>tool_use</code> content blocks have stable ordering as some languages (for example, Swift, Go) randomize key order during JSON conversion, breaking caches</li>
<li>Use <a href="https://platform.claude.com/docs/en/build-with-claude/cache-diagnostics">cache diagnostics</a> to have the API compare consecutive requests and report which part of the prompt diverged</li>
</ul>
<h2 id="1-hour-cache-duration">1-hour cache duration</h2>
<h3 id="mixing-different-ttls">Mixing different TTLs</h3>
<p>You can use both 1-hour and 5-minute cache controls in the same request, but with an important constraint: Cache entries with longer TTL must appear before shorter TTLs (that is, a 1-hour cache entry must appear before any 5-minute cache entries).</p>
<h2 id="pre-warming-the-cache">Pre-warming the cache</h2>
<p>load your system prompt or tool definitions into the prompt cache before a user triggers a real request.</p>
<h3 id="how-it-works">How it works</h3>
<p>在请求中设置 <code>max_tokens: 0</code>。API 会将你的提示词读入模型，并在任何 <code>cache_control</code> 断点处写入缓存，然后立即返回，不生成任何输出。响应中的 <code>content</code> 数组为空，<code>stop_reason</code> 为 <code>&quot;max_tokens&quot;</code>，并且包含完整的 <code>usage</code> 信息。</p>
<p>将 <code>cache_control</code> 断点放在与后续请求共享的最后一个 block 上（通常是系统提示词或工具定义），而不是占位用户消息上。否则，缓存条目会以占位内容作为键，后续请求就无法命中该缓存。</p>
<p>同时，预热请求也应使用与后续请求相同的 <code>thinking</code> 配置和 <code>output_config.effort</code>。这些值会被渲染到提示词中（参见<a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#what-invalidates-the-cache">什么会使缓存失效（What invalidates the cache） </a>），因此，如果预热请求使用了不同的配置，就可能写入一个真实流量永远无法命中的缓存条目。</p>
<p>这意味着应使用**<a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#explicit-cache-breakpoints">显式缓存断点（explicit cache breakpoint） </a>，而不是<a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#automatic-caching">自动缓存（automatic caching） </a>**，因为自动缓存会将断点放在最后一个 block 上，而在这里，最后一个 block 正是占位消息。</p>
<p>占位用户消息可以是任何包含非空白字符的字符串（示例中使用 <code>&quot;warmup&quot;</code>）；其内容会被读入模型，但不会得到回答。</p>
<h3 id="typical-usage-pattern">Typical usage pattern</h3>
<p>Fire a pre-warm request when your application starts (or on a scheduled interval), then send real user requests after the pre-warm completes:</p>
<h3 id="limitation">Limitation</h3>
<p>A <code>max_tokens: 0</code> request is rejected with an <code>invalid_request_error</code> if any of the following are set, since each implies output that a zero-token budget cannot produce:</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> of <code>{&quot;type&quot;: &quot;tool&quot;, ...}</code> or <code>{&quot;type&quot;: &quot;any&quot;}</code></li>
</ul>
<p><code>max_tokens: 0</code> is also rejected inside a <a href="https://platform.claude.com/docs/en/build-with-claude/batch-processing">Message Batches</a> request. Pre-warming targets time-to-first-token, which does not apply to batch processing, and a cache entry written during batch processing would likely expire before the follow-up request runs.</p>
<h3 id="data-retention">Data retention</h3>
<p>Prompt caching (both automatic and explicit) is ZDR eligible. Anthropic does not store the raw text of your prompts or Claude&rsquo;s responses.</p>
<p>KV (key-value) cache representations and cryptographic hashes of cached content are held in memory only and are not stored at rest. Cached entries have a minimum lifetime of 5 minutes (standard) or 1 hour (extended), after which they are promptly, though not immediately, deleted. Cache entries are isolated between organizations and, on the Claude API, Claude Platform on AWS, and Microsoft Foundry, between workspaces within an organization.</p>
<p>符合ZDR(零数据保留),KV cache和加密哈希值仅保存在内存中,不会持久化,最短生命周期为5min或者1h
缓存条目在不同组织上相互隔离</p>
]]></content:encoded>
    </item>
  </channel>
</rss>
