セッション管理の詳細
詳細:セッションストア + トランスクリプト、ライフサイクル、および(自動)圧縮の内部
このドキュメントでは、OpenClaw がセッションをどのようにエンドツーエンドで管理するかを説明します:
- セッションルーティング(受信メッセージが sessionKey にマップされる方法)
- セッションストア(sessions.json)とその追跡内容
- トランスクリプトの永続化(*.jsonl)とその構造
- トランスクリプトの衛生(実行前のプロバイダー固有の修正)
- コンテキストの制限(コンテキストウィンドウ vs 追跡されたトークン)
- 圧縮(手動 + 自動圧縮)と圧縮前の作業をフックする場所
- サイレントな保守(例:ユーザーに見える出力を生成すべきではないメモリ書き込み)
まず高レベルの概要を知りたい場合は、次から始めてください:
- /concepts/session
- /concepts/compaction
- /concepts/session-pruning
- /reference/transcript-hygiene
2つの永続化レイヤー
OpenClaw は 2つのレイヤーでセッションを永続化します:
1. セッションストア(sessions.json)
- キー/値マップ:sessionKey -> SessionEntry
- 小さく、可変で、編集(またはエントリの削除)が安全
- セッションメタデータ(現在のセッション ID、最後のアクティビティ、トグル、トークンカウンターなど)を追跡
2. Transcript (<sessionId>.jsonl)
- ツリー構造を持つ追加のみのトランスクリプト(エントリには id + parentId があります)
- 実際の会話 + ツール呼び出し + 圧縮要約を保存
- 将来のターンのためにモデルコンテキストを再構築するために使用
セッションキー(`sessionKey`)
sessionKey は、どの_会話バケット_にいるかを識別します(ルーティング + 分離)。
一般的なパターン:
- Main/direct chat (per agent): agent:<agentId>:<mainKey> (default main)
- Group: agent:<agentId>:<channel>:group:<id>
- Room/channel (Discord/Slack): agent:<agentId>:<channel>:channel:<id> or ...:room:<id>
- Cron: cron:<job.id>
- Webhook: hook:<uuid> (unless overridden)
正規のルールは /concepts/session に記載されています。
セッションストアスキーマ(`sessions.json`)
ストアの値型は src/config/sessions.ts の src/config/sessions.ts です。
主要なフィールド(網羅的ではありません):
- sessionId:現在のトランスクリプト ID(sessionFile が設定されていない限り、ファイル名はこれから派生)
- updatedAt:最後のアクティビティタイムスタンプ
- sessionFile:オプションの明示的なトランスクリプトパスオーバーライド
- chatType:direct | group | room(UI と送信ポリシーに役立ちます)
- provider、subject、room、space、displayName:グループ/チャンネルラベル付け用のメタデータ
トグル:
- thinkingLevel、verboseLevel、reasoningLevel、elevatedLevel
- sendPolicy(セッションごとのオーバーライド)
モデル選択:
- providerOverride、modelOverride、authProfileOverride
トークンカウンター(ベストエフォート / プロバイダー依存):
- inputTokens、outputTokens、totalTokens、contextTokens
- compactionCount:このセッションキーの自動圧縮が完了した回数
- memoryFlushAt:最後の圧縮前メモリフラッシュのタイムスタンプ
- memoryFlushCompactionCount:最後のフラッシュ実行時の圧縮カウント
ストアは編集しても安全ですが、ゲートウェイが権限です:セッションが実行されると、エントリを書き換えたり再水和したりする場合があります。
コンテキストウィンドウ vs 追跡されたトークン
2つの異なる概念が重要です:
1. モデルコンテキストウィンドウ:モデルごとのハードキャップ(モデルに表示されるトークン)
2. セッションストアカウンター:sessions.json に書き込まれるローリング統計(/status とダッシュボードに使用)
制限を調整する場合:
- コンテキストウィンドウはモデルカタログから来ます(設定でオーバーライドできます)。
- ストアの contextTokens は実行時の推定/報告値です。厳密な保証として扱わないでください。
詳細については、/token-use を参照してください。
自動圧縮がいつ発生するか(Pi ランタイム)
組み込みの Pi エージェントでは、自動圧縮が 2つの場合にトリガーされます:
1. オーバーフローリカバリー:モデルがコンテキストオーバーフローエラーを返す → 圧縮 → 再試行。
2. しきい値の維持:成功したターンの後、次の場合:
contextTokens > contextWindow - reserveTokens
ここで:
- contextWindow はモデルのコンテキストウィンドウです
- reserveTokens はプロンプト + 次のモデル出力のために予約されたヘッドルームです
これらは Pi ランタイムセマンティクスです(OpenClaw はイベントを消費しますが、Pi がいつ圧縮するかを決定します)。
ユーザーに見えるインターフェース
次の方法で圧縮とセッション状態を観察できます:
- /status(任意のチャットセッションで)
- openclaw status(CLI)
- openclaw sessions / sessions --json
- 詳細モード:🧹 Auto-compaction complete + 圧縮カウント
圧縮前の「メモリフラッシュ」(実装済み)
目標:自動圧縮が発生する前に、永続的な状態をディスクに書き込むサイレントなエージェントターンを実行します(例:エージェントワークスペースの memory/YYYY-MM-DD.md)。
OpenClaw は事前しきい値フラッシュアプローチを使用します:
1. セッションコンテキストの使用状況を監視します。
2. それが「ソフトしきい値」(Pi の圧縮しきい値以下)を超えたとき、エージェントにサイレントな「今すぐメモリを書き込む」ディレクティブを実行します。
3. ユーザーに何も見えないように NO_REPLY を使用します。
Config (agents.defaults.compaction.memoryFlush):
- enabled(デフォルト:true)
- softThresholdTokens(デフォルト:4000)
- prompt(フラッシュターンのユーザーメッセージ)
- systemPrompt(フラッシュターン用に追加される追加のシステムプロンプト)
Notes:
- デフォルトのプロンプト/システムプロンプトには、配信を抑制するための NO_REPLY ヒントが含まれています。
- フラッシュは圧縮サイクルごとに 1 回実行されます(sessions.json で追跡)。
- フラッシュは組み込みの Pi セッションに対してのみ実行されます(CLI バックエンドはスキップします)。
- セッションワークスペースが読み取り専用の場合、フラッシュはスキップされます(workspaceAccess: "ro" または "none")。
- ワークスペースファイルレイアウトと書き込みパターンについては、Memory を参照してください。
Pi は拡張 API で session_before_compact フックも公開していますが、OpenClaw のフラッシュロジックは現在ゲートウェイ側にあります。
トラブルシューティングチェックリスト
- セッションキーが間違っていますか?/concepts/session から始めて、/status の /status を確認してください。
- ストアとトランスクリプトが一致しませんか?openclaw status からゲートウェイホストとストアパスを確認してください。
- 圧縮スパム?確認してください:
- モデルコンテキストウィンドウ(小さすぎる)
- 圧縮設定(reserveTokens がモデルウィンドウに対して高すぎると、より早い圧縮を引き起こす可能性があります)
- ツール結果の肥大化:セッションプルーニングを有効化/調整
- サイレントターンが漏れていますか?返信が NO_REPLY(正確なトークン)で始まり、ストリーミング抑制修正を含むビルドを使用していることを確認してください。