履歴管理
ランタイムは各エージェントセッションの会話履歴を保持し、プロバイダー向けの作業履歴をモデルに送信します。2つの補完的な制限が、異なる表現に対して機能します。
- トークンバジェットのトリミングは、プロバイダー向けの
ChatMessage作業履歴に作用し、推定コンテキストがトークンバジェットに収まるまで、最も古いターンを丸ごと削除します。 - ターン単位の保持は、ランタイムプロファイルに設定された履歴上限を、構造化された
Agent::history(ConversationMessage)と、レガシーなエージェントループで使われるプロバイダー向けのChatMessage履歴の両方に適用します。
どちらの上限も、ターン単位で不可分に保持します。ターンは実際のユーザーメッセージから始まり、次のユーザーメッセージまでのアシスタントの応答、ツール呼び出し、ツール結果をすべて含みます。したがって、トリミングによってツール呼び出しとその結果が分断されることはありません。テキストが偶然 [Tool results] で始まるユーザーメッセージは、新しいターンではなく、直前のターンの一部として扱われます。
ターン全体の保持
history_trim::trim_to_recent_turns は トークン予算を適用します。history_trim::trim_to_recent_turn_count と history_trim::trim_conversation_to_recent_turns は、2つの履歴表現それぞれに対して設定されたターン数の上限を適用します。いずれも、設定値が 0 であっても最新の完全なターンを1つ残します。これは意図的な動作です。現在のターンの途中のメッセージを削除したりツールのやり取りを壊したりするより、完全なターンを保持する方が安全だからです。
先頭のシステムメッセージは保持されます。トリミングが不要な場合、メッセージの順序と形状は変更されません。
トークン予算
トークン予算は ResolvedRuntime::effective_context_budget() から取得されます:
- 既存のプロファイルでは、
max_context_tokensとcontext_compact_ratioのどちらも設定されていない場合、従来の 32,000 トークンの予算が維持されます。選択したモデルに設定された容量のほうが小さい場合は、その容量が上限になります。 max_context_tokensは引き続き絶対的な予算です。明示的に0を指定すると、事前のトークン予算によるトリミングは無効になります。context_compact_ratioを設定すると、モデル相対の予算を使うようになります。この予算は、選択されたプロバイダーエイリアス/モデルのcontext_window(容量が不明な場合は 32,000 のフォールバック)にその比率を掛けた値です。(0.0, 1.0]の範囲外の値は未設定として扱われます。両方の設定がある場合、max_context_tokensは比率から導出された予算を引き下げる上限になります。history_pruning.enabledが設定され、history_pruning.max_tokensが正の値の場合、その値によって予算が引き下げられ(引き上げられることはありません)、オペレーターはより早い段階で削減できます。- いずれの正の有効予算も、選択されたモデルの_設定済み_容量を上限とします。32,000 はフォールバック用の互換性スタブであり、モデルの実際の値ではありません。プロバイダープロファイルで
context_windowが宣言されておらず、ランタイムプロファイルで正のmax_context_tokensが設定されている場合は、その予算がそのまま尊重され、ウィンドウ側の演算値としても使用されます(比率はこの値に対して適用されます)。32,000 に引き下げられることはありません。明示的なゼロのセンチネル値はゼロのまま維持され、引き続き事前トリミングを無効にします。
有効予算は、積極的なトリミングの目標値であり、ハードなリクエスト上限ではありません。対象となる古いターンをすべて削除した後も、ランタイムは、その目標値を超えていても最新の完全なターンを保持します。準備されたメッセージ、画像、フック、ツールスキーマが解決済みのモデルのコンテキストウィンドウに収まる場合にリクエストを送信します。それでもその容量を超えるリクエストは、プロバイダーへの送信前に失敗します。積極的なトリミングの目標値を引き上げるだけでは、そのリクエストが収まるようにはなりません。この容量チェックは、積極的なトリミングが無効な場合(max_context_tokens = 0)にも適用され、ツールの反復回数上限に達した後の最終要約リクエストにも適用されます。
Capacity と budget は、有効な provider/model ルートに対して一緒に解決されます。分類器のヒントと明示的なセッション切り替えは、provider dispatch と同じルート選択を使うため、次のモデル呼び出し、事前トリミング、オーバーフロー診断、コスト計上、クライアントのコンテキストメーターはすべて、選択された provider/model とその解決済みのペアを使用します。選択されたモデルがプロファイルに設定されたモデルと一致しない場合、そのプロファイルのメタデータを別のモデルに流用するのではなく、capacity は不明として扱われます。内部の 32,000 互換フォールバックは安全性の計算用に引き続き利用できますが、不明な capacity に対しては、ワイヤークライアントに model_context_window の値は一切渡されません。
トークン数は history::estimate_history_tokens で推定されます。おおよそ 1 トークンあたり 4 文字に、メッセージごとに 4 トークンの枠組み分を加えた値です。これは経験則によるヒューリスティックであり、プロバイダーのトークナイザーによる正確な計算ではありません。読み込み可能な [IMAGE:...] マーカーには、画像が送信されるメッセージ、つまりユーザーのターンと現在のユーザーターンのツール結果にのみ、画像 1 枚あたりの固定コストが適用されます。ツール結果の画像は、ツールの出力に含まれるマーカーテキストではなく、ツールが宣言した添付ファイルです。古いツール結果はメッセージのバイト数として計算され、システムメッセージとアシスタントのテキストはテキストとして計算されます。
トークン予算によるトリミングは、履歴が実効予算をすでに超えている場合は、ターンの最初のプロバイダー呼び出しの前に実行されます。また、ツールループの反復の間のプロバイダー呼び出し境界でも実行されます。プロバイダーがコンテキストウィンドウのオーバーフローを報告した場合、既存のリアクティブな回復パスが、現在の推定履歴サイズの3分の2までトリミングした後に再試行します。モデルの容量から新しい回復目標を導出することはありません。どちらのパスも、ターン単位で履歴を保持するため、ツールのやり取りを分割することはありません。
ターン全体の上限
max_history_messages は、エージェントのランタイムプロファイルにおける履歴設定の旧名称です。構造化エージェントおよびレガシーなエージェントループでは、その単位は個々のメッセージ行ではなく、完全なユーザーターンです。ツール呼び出しとツール結果は、それを含むターンの一部のまま残り、独立したスロットを消費することはありません。
デフォルトは50ターンです。明示的に設定された値は権威を持ち、0を含みます。その場合でも、最新の完全なターンは保持されます。このフィールド名はスキーマの互換性のために維持されており、将来のスキーマバージョンで変更される可能性があります。
チャンネル送信者キャッシュは別の例外であり、個々のメッセージ行を数え、0 をデフォルト値の指定とみなす既存の動作を維持します。
表示のトリミング
Whenever token-budget trimming or the whole-turn limit drops older turns, the runtime:
- モデルが以前のコンテキストが省略されたことを認識できるよう、最初の保持されたターンの前にパンくずリストを挿入します。
HistoryTrimmedを発行します。発行時には、削除されたメッセージ数、保持されたターン数、およびトークン予算またはターン数上限のいずれが理由かを示す reason を含みます。
イベントは、アクティブなクライアントトランスポートを通じて、およびダッシュボードやイベントサブスクライバーが使用するオブザーバーパスを通じて表面化されます。したがって、トリミングはログのみに限定されず、モデルにも接続されたクライアントにも通知されないわけではありません。
従来の agent::run パスは、loop_.rs において件数ベースの履歴トリミングをログにのみ出力し、ブレッドクラムや HistoryTrimmed イベントは発行しません。このパスは、対話型の利用に加え、ワンショット実行、非対話型のデーモン、cron、サブエージェント、SOP の呼び出し元にも使われています。
ペアリングの安全性
ターン全体の保持は、ツールのペアリングに関する主要な保証です。ツール呼び出しとその結果は同じターンに属し、一緒に保持されるか破棄されます。孤立要素のスイープは、復元されたセッションや外部で変更されたセッションなど、すでに不整合だった履歴に対する最後のセーフティネットとして残ります。
ツール結果の長さ制限は別途扱われます。max_tool_result_chars は個々の結果が記録される際にそのサイズを制限しますが、会話履歴をトリミングするものではありません。プロバイダー側のコンテキスト制限も別途扱われますが、プロバイダーのオーバーフローによってランタイムの事後的なトークンバジェットのトリミングがトリガーされる場合があります。