# clear_atで作るターン限定リマインダー設計

> Claude APIのclear_at:next_user_messageは、ツールループの毎ターンリマインダーをプロンプトキャッシュとPreserved Thinkingを壊さず挿入するベータ機能だ。5つの実装制約を解説する。

- Canonical: https://kuucorp.com/blog/claude-turn-scoped-system-message-clear-at-design/
- Date: 2026-09-12
- Last modified: 2026-09-12
- Publisher: Kuu株式会社 (https://kuucorp.com)

---
長時間の[エージェントハーネス](/glossary/agent-harness/)で「独立した読み取りはまとめて要求して」「残りトークン予算が少ない」といった運用上の注意を毎ターン差し込みたい場面は多い。だが会話履歴の末尾に足すだけでは、前のターンで挿入したリマインダーがそのまま残り続け、ターンを重ねるほど同じ文言が積み上がっていく。

## なぜ毎ターンのリマインダーは積み上がるのか

> `role: "system"`メッセージは会話履歴に残り続けるため、削除せずに追加し続けると同じ指示が何度も重複してコンテキストを圧迫する。

[Mid-conversation system messages](/blog/claude-mid-conversation-tool-changes-cache-design/)は、トップレベルの`system`フィールドを書き換えずに会話途中で指示を追加する仕組みだ。`tools`→`system`→`messages`の順でハッシュ化される[プロンプトキャッシュ](https://platform.claude.com/docs/en/build-with-claude/prompt-caching)を壊さずに済むため、エージェントハーネスの定番パターンになっている。ただし素朴に使うと、ツール実行後に毎回リマインダーを追記する運用では、古いコピーを消さない限り履歴に同じ文言が並び続ける。かといって古いメッセージを後から削除・書き換えれば、それより後のキャッシュはすべて失効し、Claude Fable 5.1では[Preserved Thinking](/blog/claude-preserved-thinking-append-only-conversation-design/)の会話検証にも違反して400エラーになる。

## clear_atはどう動くか

> `clear_at: "next_user_message"`を付けた`system`メッセージは、次のuserメッセージが現れた時点で描画されなくなり入力トークンも消費しない。

Turn-scoped system messagesはこの矛盾を解く機能で、`role: "system"`メッセージに`clear_at`フィールドを追加する。値は2種類で、`"never"`（デフォルト、常に描画）と`"next_user_message"`（ターン限定）を取る。後者を指定すると、そのメッセージは自分より後に`role: "user"`メッセージが存在しない間だけ描画され、一度userメッセージが挟まるとクリアされる。クリアされたメッセージは配列から削除されるわけではなく、「履歴には残るが描画されず、トークンも消費しない」状態になる。この機能はベータで、`mid-conversation-system-clear-at-2026-08-21`ベータヘッダーが必須。ヘッダーを付けずに`clear_at`を送ると未知フィールドとして拒否される。対応モデルはClaude Fable 5.1・Claude Mythos 5.1・Claude Fable 5・Claude Opus 4.8・Claude Opus 5で、Claude Sonnet 5では使えない。

## 実装時に守るべき制約

> クリア済みメッセージは書き換え禁止・テキストのみ・`cache_control`不可という3つの制約を守らないとAPIエラーか会話破壊につながる。

制約は主に3つある。第一に、クリアされたメッセージは会話履歴の一部であり続けるため、次回リクエストでも**そのまま再送**しなければならない。トークン数やタイムスタンプを最新化して送り直す、冗長だから削るといった操作は「過去メッセージの編集」と同じ扱いになり、その時点からキャッシュが失効し、Claude Fable 5.1では後続の思考ブロックがすべて検証エラーになる。第二に、`clear_at`付きメッセージの`content`はテキストブロックのみで、`tool_addition`・`tool_removal`・`output_config`を含めると400エラーになる。ツール入替が必要なら`clear_at`なしの別メッセージに分離する。第三に、クリアされたメッセージは絶対にキャッシュキーの対象にならないため、そのブロックに`cache_control`を置くことはできない。ブレークポイントは直前のuserターンの最後のブロックに置く。配置ルール自体は他のmid-conversation system messagesと同じで、userターン（またはサーバーツール結果で終わるassistantターン）の直後、かつassistantターンの手前か配列末尾でなければならない。

## Preserved Thinkingとの関係をどう使うか

> クリア済みメッセージは履歴上そのまま残るため会話の内容が変わらず、Claude Fable 5.1のPreserved Thinking検証を壊さずに済む。

ここがこの機能の核心にある設計判断だ。単純にメッセージを都度削除する実装は、それより後にある思考ブロックの「直前までの会話が変わっていないこと」を要求するPreserved Thinkingの検証を壊す。`clear_at`はメッセージを削除せず「描画されない」状態に変えるだけなので、会話そのものは変化しない。ツール実行結果の後に同じリマインダーを`clear_at: "next_user_message"`付きで積み重ねていけば、Claudeが目にするのは直近のuserメッセージより後にある最新のコピーだけになり、履歴上の見た目もキャッシュ整合性も両立する。エンタープライズで複数チームがハーネスを共有する構成では、この再送ルールをSDKラッパー側で強制しておくと、個別チームの実装差でキャッシュヒット率がばらつく事故を防げる。ハーネス基盤の設計・運用は[RDE](https://kuucorp.com/services/rde/)の対象領域でもある。

## 参考

- [Mid-conversation system messages and tool changes](https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages)
- [Prompt caching](https://platform.claude.com/docs/en/build-with-claude/prompt-caching)
- [Thinking](https://platform.claude.com/docs/en/build-with-claude/thinking)

## まとめ

`clear_at: "next_user_message"`は、ツールループの毎ターンリマインダーをキャッシュ整合性とPreserved Thinkingの検証を保ったまま実装するための専用機構だ。再送必須・テキストのみ・`cache_control`不可という3制約を守れば、コンテキストを圧迫せずに運用上の注意事項をClaudeへ確実に届けられる。自社ハーネスへの組み込み方や既存実装の見直しについては、Kuuまでお問い合わせください。
