◉CLAUDE LABEN
●2.1.312 — 巨大な CLAUDE.md の上書きや、cd のあとにスキルが見つからない問題を修正しました●API — Messages API の最大リクエストサイズが 32MB から 128MB に拡大されました(10/28)●SONNET 4.5 — Claude API での提供終了は 11/30、残り31日。移行先は Sonnet 5.5●WINDOWS — 日本語の環境でだけフックが黙って壊れる報告があり、文字コードの確認が呼びかけられています●API — 新しい API バージョン 2026-10-21 では temperature・top_p・top_k を渡すと 400 になります●NEW — Cowork に渡したフォルダの先頭に、十行の約束ファイルを置いてみました●2.1.312 — 巨大な CLAUDE.md の上書きや、cd のあとにスキルが見つからない問題を修正しました●API — Messages API の最大リクエストサイズが 32MB から 128MB に拡大されました(10/28)●SONNET 4.5 — Claude API での提供終了は 11/30、残り31日。移行先は Sonnet 5.5●WINDOWS — 日本語の環境でだけフックが黙って壊れる報告があり、文字コードの確認が呼びかけられています●API — 新しい API バージョン 2026-10-21 では temperature・top_p・top_k を渡すと 400 になります●NEW — Cowork に渡したフォルダの先頭に、十行の約束ファイルを置いてみました
記事一覧/API & SDK
⬡ API & SDK/2026-08-01上級

会話の途中でツールを差し替える — プロンプトキャッシュを守るツールレジストリの設計

ターン間でツールを追加・削除できるようになった一方、ツール定義はキャッシュプレフィックスの最前列にあります。12種類の変更を指紋で実測し、安定コアと揮発テールに分けるレジストリ設計とガード実装をまとめました。

Claude API139プロンプトキャッシュ4Tool Use6アーキテクチャ7コスト最適化26

✦ プレミアム記事

長時間のセッションで、使っていないツールを外そうとしたときのことでした。

ツールが12本ぶら下がったまま会話が進んでいて、明らかに後半では使わないものが混ざっておりました。ターン間でツールを追加・削除できるベータが来ていましたので、素直に4本ほど削りました。入力トークンが減るはずでした。

減りませんでした。むしろ増えました。

cache_read_input_tokens がゼロに落ちて、それまで積み上がっていた会話履歴が丸ごと再送されていたのです。ツールを削って節約したつもりが、キャッシュを壊して全部払い直していたのです。手が止まりました。

ツール定義はプレフィックスの最前列にいる

プロンプトキャッシュは接頭辞(プレフィックス)の一致で効きます。リクエストの先頭から一致している範囲までがキャッシュヒットの対象で、どこか一箇所でも変われば、そこから後ろは全部ミスになります。

問題は、ツール定義がその最前列に置かれることです。Claude API のリクエストは、おおよそ次の順序で直列化されます。

順序ブロック変更頻度下流への影響
1tools本来は低いはずsystem・messages のすべて
2system低いmessages のすべて
3messages(過去ターン)追記のみ以降のターン
4messages(最新ターン)毎回なし

つまりツール配列は、リクエスト全体で最も影響半径の大きい場所にいます。会話が100ターン積み上がっていようと、ツールを1本入れ替えた瞬間に、その100ターン分のキャッシュが道連れになります。

ターン間のツール変更がベータで解禁されたことと、その変更がキャッシュにとって安全であることは、別の話でした。API が変更を受け付けてくれることと、プレフィックスが保たれることは、同じではありません。

ここを取り違えていました。私自身、ベータの告知文にある「プロンプトキャッシュを維持したまま」という一節を、どんな変更でも維持されるという意味に読んでいたのです。機能が解禁されたという知らせを、費用が下がるという知らせと重ねて読んでしまう癖があるのかもしれません。

12種類の変更を指紋で測る

感覚で語っても仕方がないので、測ることにしました。ツール配列を先頭から1本ずつ足していったときの累積ハッシュ列を作り、変更前後でどこまで一致するかを見ます。

# toolprefix.py — ツールブロックのプレフィックス指紋を測る
import hashlib
import json
 
def canon(obj):
    """決定論的シリアライズ: キーをソートし、区切りを固定する"""
    return json.dumps(obj, sort_keys=True, separators=(",", ":"), ensure_ascii=False)
 
def prefix_chain(tools):
    """ツール配列を先頭から1本ずつ足したときの累積ハッシュ列を返す"""
    chain, h = [], hashlib.sha256()
    for t in tools:
        h = h.copy()               # copy しないと以降の update が混ざる
        h.update(canon(t).encode())
        chain.append(h.hexdigest())
    return chain
 
def shared_prefix_len(a, b):
    """2つのハッシュ列が先頭から何要素一致しているか"""
    n = 0
    for x, y in zip(a, b):
        if x != y:
            break
        n += 1
    return n

h.copy() を挟んでいるのは、各段の途中経過を別々に取り出すためです。ここを省くと同じオブジェクトを更新し続けてしまい、全段が最終値になります。最初これで丸一晩、意味のない100%一致を眺めていました。

ベースになるツール配列は、実際の構成に近い5本にしました。

def mk(name, props):
    return {
        "name": name,
        "description": f"{name} tool",
        "input_schema": {
            "type": "object",
            "properties": props,
            "required": sorted(props.keys()),
        },
    }
 
BASE = [
    mk("search_docs", {"query": {"type": "string"}, "top_k": {"type": "integer"}}),
    mk("read_file",   {"path": {"type": "string"}}),
    mk("write_file",  {"path": {"type": "string"}, "body": {"type": "string"}}),
    mk("run_tests",   {"suite": {"type": "string"}}),
    mk("post_report", {"channel": {"type": "string"}, "text": {"type": "string"}}),
]
 
base_chain = prefix_chain(BASE)
for label, mutate in CASES:
    n = shared_prefix_len(base_chain, prefix_chain(mutate(BASE)))
    print(f"{label:<26} {n}/{len(BASE)}  {n / len(BASE):.0%}")

手元で12パターンを流した結果です。

変更パターン共有プレフィックス保全率判定
末尾に1本追加5/5100%安全
内容は同一・再構築のみ5/5100%安全
末尾の1本を削除4/580%部分
末尾ツールの説明文を修正4/580%部分
末尾ツールに任意項目を追加4/580%部分
中間に1本挿入2/540%部分
中間の1本を削除2/540%部分
中間ツールを改名2/540%部分
2番目と3番目を入れ替え1/520%部分
先頭に1本追加0/50%全損
先頭の1本を削除0/50%全損
先頭ツールの説明文を修正0/50%全損

完全保全は12件中2件、平均保全率は48%でした。

そして、この表の「部分」という判定こそが落とし穴です。プレフィックスが4/5まで一致していても、cache_control のブレークポイントを置いていない位置での一致には何の価値もありません。キャッシュの単位はブレークポイントで区切られた区間であって、ツール1本ごとではないからです。

ブレークポイントをツール配列の最後尾にだけ置いている構成では、上の12パターンのうち実際に救われるのは「安全」の2件だけです。残り10件は、保全率が80%だろうと20%だろうと、等しくゼロとして扱われます。

自分が壊していたのは、まさにこれでした。使わないツールを削るとき、配列の中ほどにいた post_report を抜いていたのです。

✦

ここまでお読みいただきありがとうございます。

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
✦ツール変更12パターンを指紋で実測。完全にプレフィックスを保てたのは2/12、平均保全率48%という内訳
✦論理的に同一のツール定義36通りが、素の JSON シリアライズでは36種の異なる指紋になる(偽の無効化100%)
✦分割ではコアの保全が動いた総量の3.69%にとどまる実測。ツールブロックを不変にする構成と、拮抗点が15ターンに1回であることまで測った内訳つき
Stripe による安全な決済 · いつでもキャンセル可能
✦

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

お読みいただきありがとうございます

Claude Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • ✦コピー&ペーストで使える実装コード付き
  • ✦毎日新しい上級ガイドを追加
  • ✦¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

関連記事

⬡ API & SDK2026-06-13
Claude Vision API 実装パターン — 画像解析・PDF 処理・OCR を本番品質で動かすまで
Claude API のビジョン機能を本番投入するための実装パターンをまとめました。Base64・URL・Files API の使い分け、ネイティブ PDF 処理、Tool Use による壊れない構造化抽出、Batch API でのコスト削減、エラー対処まで動くコードで解説します。
⬡ API & SDK2026-05-14
Claude API でアプリ内 AI チャットを実装して踏んだ6つの罠 — 本番投入までの設計記録
Claude APIをアプリ内チャットに組み込んで本番で直面した6つの設計ミスを、個人開発での実運用経験から解説。コンテキスト設計、ストリーミング、セッション管理、コスト監視の実装パターンを動くコード付きで紹介します。
⬡ API & SDK2026-05-12
Haiku 4.5・ストリーミング・プロンプトキャッシングを組み合わせて個人開発アプリのAPIコストを抑えた記録
個人開発アプリのAI機能で膨らむAPIコストを、Haiku 4.5への移行・ストリーミング・プロンプトキャッシングの3つの組み合わせで抑えた記録です。各ステップの実装と落とし穴、統合パターン、実装前後のコスト比較、キャッシュの損益分岐を先に計算する考え方までまとめました。