- セッション ルーティング (受信メッセージを
sessionKeyにマッピングする方法) - セッション ストア (
sessions.json) とその追跡内容 - トランスクリプトの永続性 (
*.jsonl) とその構造 - トランスクリプトの衛生管理 (実行前のプロバイダー固有の修正)
- コンテキストの制限 (コンテキスト ウィンドウと追跡されたトークン)
- 圧縮 (手動 + 自動圧縮) および圧縮前の作業をフックする場所
- サイレント ハウスキーピング (例: ユーザーに表示される出力を生成すべきではないメモリ書き込み)
真実の情報源: ゲートウェイ
OpenClaw は、セッション状態を所有する単一の ゲートウェイ プロセスを中心に設計されています。- UI (macOS アプリ、Web コントロール UI、TUI) は、ゲートウェイにセッション リストとトークン数をクエリする必要があります。
- リモート モードでは、セッション ファイルはリモート ホスト上にあります。 「ローカル Mac ファイルの確認」には、ゲートウェイが使用している内容は反映されません。
2 つの永続化レイヤー
OpenClaw はセッションを 2 つのレイヤーで永続化します。1. セッション ストア (sessions.json)
- キー/値マップ:
sessionKey -> SessionEntry - 小さく、変更可能で、安全に編集 (またはエントリを削除)
- セッションのメタデータ (現在のセッション ID、最後のアクティビティ、トグル、トークン カウンターなど) を追跡します。
- トランスクリプト (
<sessionId>.jsonl)- ツリー構造の追加専用トランスクリプト (エントリには
id+parentIdがあります) - 実際の会話 + ツール呼び出し + 圧縮サマリーを保存します
- 将来のターンに向けてモデル コンテキストを再構築するために使用されます
- ツリー構造の追加専用トランスクリプト (エントリには
ディスク上の場所
ゲートウェイ ホスト上のエージェントごと:- ストア:
~/.openclaw/agents/<agentId>/sessions/sessions.json - トランスクリプト:
~/.openclaw/agents/<agentId>/sessions/<sessionId>.jsonl- テレグラムトピックセッション:
.../<sessionId>-topic-<threadId>.jsonl
- テレグラムトピックセッション:
src/config/sessions.ts を通じてこれらを解決します。
ストアのメンテナンスとディスク制御
セッション永続性には、sessions.json およびトランスクリプト アーティファクトの自動メンテナンス制御 (session.maintenance) があります。- mode: warn (デフォルト) または enforce
pruneAfter: 古いエントリの年齢カットオフ (デフォルト30d)maxEntries:sessions.jsonのエントリを制限します (デフォルト500)rotateBytes: サイズが大きい場合にsessions.jsonを回転します (デフォルト10mb)resetArchiveRetention:*.reset.<timestamp>トランスクリプト アーカイブの保持 (デフォルト:pruneAfterと同じ。falseはクリーンアップを無効にします)maxDiskBytes: オプションのセッション ディレクトリの予算highWaterBytes: クリーンアップ後のオプションのターゲット (デフォルトの80%またはmaxDiskBytes)
mode: "enforce"):
- 最も古いアーカイブされた成果物または孤立したトランスクリプト成果物を最初に削除します。
- まだ目標を超えている場合は、最も古いセッション エントリとそのトランスクリプト ファイルを削除します。
- 使用量が
highWaterBytes以下になるまで続行します。
mode: "warn" では、OpenClaw はエビクションの可能性を報告しますが、ストア/ファイルは変更しません。
オンデマンドでメンテナンスを実行します。
Cron セッションと実行ログ
分離された cron 実行ではセッション エントリ/トランスクリプトも作成され、専用の保持制御が行われます。-cron.sessionRetention (デフォルト 24h) は、分離された古い cron 実行セッションをセッション ストアから削除します (false は無効になります)。
cron.runLog.maxBytes+cron.runLog.keepLines~/.openclaw/cron/runs/<jobId>.jsonlファイルを削除します (デフォルト:2_000_000バイトおよび2000行)。
セッションキー (sessionKey)
sessionKey は、現在いる会話バケットを識別します (ルーティング + 分離)。
よくあるパターン:
- メイン/ダイレクト チャット (エージェントごと):
agent:<agentId>:<mainKey>(デフォルトmain) - グループ:
agent:<agentId>:<channel>:group:<id> - ルーム/チャンネル (Discord/Slack):
agent:<agentId>:<channel>:channel:<id>または...:room:<id> - クロン:
cron:<job.id> - Webhook:
hook:<uuid>(オーバーライドされない限り)
セッション ID (sessionId)
各 sessionKey は、現在の sessionId (会話を継続するトランスクリプト ファイル) を指します。
経験則:- リセット (/new、/reset) は、その sessionKey に対して新しい sessionId を作成します。
- 毎日リセット (デフォルトはゲートウェイ ホストの現地時間午前 4 時) は、リセット境界後の次のメッセージで新しい
sessionIdを作成します。 - アイドル有効期限 (
session.reset.idleMinutesまたはレガシーsession.idleMinutes) は、アイドル ウィンドウの後にメッセージが到着すると、新しいsessionIdを作成します。 Daily + Idle の両方が設定されている場合は、先に期限切れになった方が優先されます。 - スレッド親フォーク ガード (
session.parentForkMaxTokens、デフォルト100000) は、親セッションがすでに大きすぎる場合、親トランスクリプトのフォークをスキップします。新しいスレッドは新しく始まります。0を無効に設定します。
src/auto-reply/reply/session.ts の initSessionState() で行われます。
セッション ストア スキーマ (sessions.json)
ストアの値の型は src/config/sessions.ts の SessionEntry です。
主要なフィールド (すべてではありません):- sessionId: 現在のトランスクリプト ID (sessionFile が設定されていない限り、ファイル名はこれから派生します)
updatedAt: 最後のアクティビティのタイムスタンプsessionFile: オプションの明示的なトランスクリプト パスのオーバーライドchatType:direct | group | room(UI とポリシーの送信に役立ちます)provider、subject、room、space、displayName: グループ/チャネルのラベル付けのメタデータ- トグル:
thinkingLevel、verboseLevel、reasoningLevel、elevatedLevelsendPolicy(セッションごとの上書き)
- モデルの選択:
providerOverride、modelOverride、authProfileOverride
- トークンカウンター (ベストエフォート型 / プロバイダー依存):
inputTokens、outputTokens、totalTokens、contextTokens
compactionCount: このセッション キーの自動圧縮が完了する頻度memoryFlushAt: 最後の圧縮前のメモリフラッシュのタイムスタンプmemoryFlushCompactionCount: 最後のフラッシュが実行されたときの圧縮数
トランスクリプト構造 (*.jsonl)
トランスクリプトは @mariozechner/pi-coding-agent の SessionManager によって管理されます。
ファイルは JSONL です。- 最初の行: セッションヘッダー (type: "session"、id、cwd、timestamp、オプションの parentSession を含む)
- 次に:
id+parentIdのセッション エントリ (ツリー)
message: ユーザー/アシスタント/ツール結果メッセージcustom_message: モデル コンテキストに do 入る拡張機能によって挿入されたメッセージ (UI から非表示にすることができます)custom: モデル コンテキストに「入らない」拡張状態compaction:firstKeptEntryIdおよびtokensBeforeによる永続化圧縮の概要branch_summary: ツリー ブランチを移動するときに持続される概要
SessionManager を使用してそれらの読み取り/書き込みを行います。
コンテキスト ウィンドウと追跡されたトークン
2 つの異なる概念が重要です。- モデル コンテキスト ウィンドウ: モデルごとのハード キャップ (モデルに表示されるトークン)
- セッション ストア カウンター:
sessions.jsonに書き込まれるローリング統計 (/status およびダッシュボードに使用)
- コンテキスト ウィンドウはモデル カタログから取得されます (構成によってオーバーライドできます)。
- ストア内の
contextTokensは実行時の推定値/レポート値です。厳密な保証として扱わないでください。
圧縮: 圧縮とは何か圧縮により、古い会話がトランスクリプト内の永続化された compaction エントリに要約され、最近のメッセージはそのまま保持されます
圧縮後、今後のターンでは次のようになります。
- 圧縮の概要
firstKeptEntryId以降のメッセージ
自動圧縮が行われる場合 (Pi ランタイム)
埋め込み Pi エージェントでは、次の 2 つの場合に自動圧縮がトリガーされます。- オーバーフロー回復: モデルはコンテキスト オーバーフロー エラーを返し、→ 圧縮→ 再試行します。
- 閾値メンテナンス: ターンが成功した後、次の場合:
contextTokens > contextWindow - reserveTokens
場所:
contextWindowはモデルのコンテキスト ウィンドウですreserveTokensは、プロンプト + 次のモデル出力用に予約されたヘッドルームです。
圧縮設定 (reserveTokens、keepRecentTokens)
Pi の圧縮設定は Pi 設定に反映されます。
compaction.reserveTokens < reserveTokensFloorの場合、OpenClaw はそれをバンプします。- デフォルトのフロアは
20000トークンです。 agents.defaults.compaction.reserveTokensFloor: 0を設定してフロアを無効にします。- すでにそれより高い場合、OpenClaw はそれをそのままにします。
src/agents/pi-settings.ts の ensurePiCompactionReserveTokens()
(src/agents/pi-embedded-runner.ts から呼び出されます)。
ユーザーに見える表面
次の方法で圧縮とセッションの状態を観察できます。/status(チャット セッション中)openclaw status(CLI)openclaw sessions/sessions --json- 詳細モード:
🧹 Auto-compaction complete+ 圧縮カウント
サイレントハウスキーピング (NO_REPLY)
OpenClaw は、ユーザーが中間出力を表示しないバックグラウンド タスクの「サイレント」ターンをサポートします。
規約:
- アシスタントは出力を
NO_REPLYで開始し、「ユーザーに応答しない」ことを示します。 - OpenClaw は、配信層でこれを削除/抑制します。
2026.1.10 以降、OpenClaw は、部分チャンクが NO_REPLY で始まる場合、ドラフト/タイピング ストリーミングも抑制するため、サイレント操作によってターン中に部分的な出力が漏洩することはありません。
圧縮前の「メモリフラッシュ」(実装)
目標: 自動圧縮が行われる前に、永続的な書き込みを行うサイレント エージェント ターンを実行します。 状態をディスクに保存するため (例: エージェント ワークスペースのmemory/YYYY-MM-DD.md)、圧縮はできません。
重要なコンテキストを消去します。
OpenClaw は 事前しきい値フラッシュ アプローチを使用します。
- セッションコンテキストの使用状況を監視します。
- 「ソフトしきい値」(Pi の圧縮しきい値を下回る) を超えると、サイレント メソッドを実行します。 「今すぐメモリに書き込む」という指示をエージェントに送信します。
- ユーザーには何も表示されないように、
NO_REPLYを使用します。
agents.defaults.compaction.memoryFlush):- enabled (デフォルト: true)
softThresholdTokens(デフォルト:4000)prompt(フラッシュターンのユーザーメッセージ)systemPrompt(フラッシュ ターン用に追加された追加のシステム プロンプト)
- デフォルトのプロンプト/システム プロンプトには、配信を抑制するための
NO_REPLYヒントが含まれています。 - フラッシュは圧縮サイクルごとに 1 回実行されます (
sessions.jsonで追跡されます)。 - フラッシュは埋め込み Pi セッションに対してのみ実行されます (CLI バックエンドはフラッシュをスキップします)。
- セッション ワークスペースが読み取り専用 (
workspaceAccess: "ro"または"none") の場合、フラッシュはスキップされます。 - ワークスペースファイルのレイアウトと書き込みパターンについては、メモリを参照してください。
session_before_compact フックも公開しますが、OpenClaw の
現在、フラッシュ ロジックはゲートウェイ側に存在します。
トラブルシューティングのチェックリスト
- セッションキーが間違っていますか? /concepts/session から始めて、
/statusのsessionKeyを確認します。 - ストアとトランスクリプトの不一致?
openclaw statusからゲートウェイ ホストとストア パスを確認します。 - 圧縮スパム?確認してください:
- モデル コンテキスト ウィンドウ (小さすぎる)
- 圧縮設定 (
reserveTokensがモデル ウィンドウに対して高すぎると、圧縮が早まる可能性があります) - ツール結果の肥大化: セッション プルーニングの有効化/調整
- サイレントターンが漏れていませんか?応答が
NO_REPLY(正確なトークン) で始まり、ストリーミング抑制修正を含むビルドを使用していることを確認します。