履歴管理
ランタイムは各エージェントセッションの会話履歴を保持し、プロバイダー向けの作業履歴をモデルに送信します。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() から取得されます:
-
Existing profiles retain the historical 32,000-token budget when neither
max_context_tokensnorcontext_compact_ratiois set, capped by the selected model’s configured capacity when that capacity is smaller.Wait, I need to correct myself. The source is in English and needs translation into Japanese, so here is the translation:
既存のプロファイルでは、
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는 비율에서 도출된 예산에 대한 하향 상한값으로 작동합니다. -
When
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を含みます。その場合でも、最新の完全なターンは保持されます。このフィールド名はスキーマの互換性のために維持されており、将来のスキーマバージョンで変更される可能性があります。
Channel sender キャッシュは別の例外であり、個々のメッセージ行を数え、既存の 0-means-default の動作を維持します。
表示のトリミング
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 は個々の結果が記録される際にそのサイズを制限しますが、会話履歴をトリミングするものではありません。プロバイダー側のコンテキスト制限も別途扱われますが、プロバイダーのオーバーフローによってランタイムの事後的なトークンバジェットのトリミングがトリガーされる場合があります。