コンテンツにスキップ

OpenClawセッション管理と圧縮:データ構造と自動メンテナンスを解説

信頼の唯一の情報源(Source of Truth):Gateway

Section titled “信頼の唯一の情報源(Source of Truth):Gateway”

OpenClawは、セッションの状態を管理する単一の Gateway プロセスを中心に設計されています。

  • macOSアプリ、Web Control UI、TUIなどの各UIは、セッション一覧やトークン数を Gateway に問い合わせる必要があります。
  • リモートモードで使用している場合、セッションファイルはリモートホスト上に保存されます。そのため、ローカルのMac内のファイルを確認しても、Gateway が実際に使用している状態は反映されません。

OpenClawは、セッションを以下の2つのレイヤーで永続化します。

  1. セッションストア (sessions.json)

    • sessionKey -> SessionEntry という形式のキー/バリューマップです。
    • 軽量で変更可能なファイルであり、直接エントリを編集したり削除したりしても安全です。
    • 現在のセッションID、最終アクティビティ、各種設定のトグル、トークンカウンターなどのセッションメタデータを追跡します。
  2. トランスクリプト (<sessionId>.jsonl)

    • 各エントリが id と parentId を持つツリー構造を採用した、追記型のトランスクリプトです。
    • 実際の会話内容、tool calls、compaction のサマリーが保存されます。
    • 今後のターンのためにモデルのコンテキストを再構築する際に使用されます。

Gateway ホスト上のエージェントごとに、以下の場所に保存されます。

  • ストア: ~/.openclaw/agents/<agentId>/sessions/sessions.json
  • トランスクリプト: ~/.openclaw/agents/<agentId>/sessions/<sessionId>.jsonl(Telegramのトピックセッションの場合は .../<sessionId>-topic-<threadId>.jsonl となります)

OpenClawは、これらを src/config/sessions.ts を通じて解決します。

ストアのメンテナンスとディスク制御

Section titled “ストアのメンテナンスとディスク制御”

セッションの永続化には、sessions.json やトランスクリプトの成果物を管理するための自動メンテナンス機能(session.maintenance)が備わっています。

  • mode: warn(デフォルト)または enforce
  • pruneAfter: 古くなったエントリを削除するまでの期間(デフォルト 30d)
  • maxEntries: sessions.json に保存するエントリの最大数(デフォルト 500)
  • rotateBytes: sessions.json が制限を超えた場合にローテーションするサイズ(デフォルト 10mb)
  • resetArchiveRetention: *.reset.<timestamp> 形式のトランスクリプトアーカイブの保持期間(デフォルトは pruneAfter と同じ。false でクリーンアップ無効)
  • maxDiskBytes: セッションディレクトリに使用するオプションのディスク予算
  • highWaterBytes: クリーンアップ後の目標サイズ(デフォルトは maxDiskBytes の 80%)

ディスク予算をクリーンアップする際の実行順序(mode: "enforce" の場合)は以下の通りです。

  1. まず、最も古いアーカイブ済み、または孤立したトランスクリプトの成果物を削除します。
  2. それでも目標値を超えている場合は、最も古いセッションエントリとそのトランスクリプトファイルを順次破棄し、使用量が highWaterBytes 以下になるまで継続します。

mode: "warn" の場合、OpenClawは破棄される可能性のある項目を報告するだけで、ストアやファイルの内容は変更しません。

必要に応じて、以下のコマンドでメンテナンスを手動実行できます。

Terminal window
openclaw sessions cleanup --dry-run
openclaw sessions cleanup --enforce

独立したCronの実行でもセッションのエントリやログが作成されます。これらには専用の保持期間の設定があります。

  • cron.sessionRetention (デフォルト 24h) は、セッションストアから古い独立したCron実行セッションを削除します(falseで無効化)。
  • cron.runLog.maxBytes + cron.runLog.keepLines は、~/.openclaw/cron/runs/<jobId>.jsonl ファイルを整理します(デフォルト:2_000_000 バイト、2000 行)。

sessionKeyは、どの会話のバケット(ルーティングと分離の単位)に属しているかを識別するものです。

共通のパターン:

  • メイン/ダイレクトチャット(エージェントごと): agent:<agentId>:<mainKey> (デフォルト main)
  • グループ: agent:<agentId>:<channel>:group:<id>
  • ルーム/チャンネル (Discord/Slack): agent:<agentId>:<channel>:channel:<id> または ...:room:<id>
  • Cron: cron:<job.id>
  • Webhook: hook:<uuid> (オーバーライドされない限り)

正式なルールは /concepts/session に記載されています。


各sessionKeyは、現在のsessionId(会話を継続するためのログファイル)を指し示します。

基本的なルール:

  • リセット (/new, /reset): そのsessionKeyに対して新しいsessionIdを作成します。
  • デイリーリセット (Gateway ホストのローカル時間でデフォルト午前4:00): リセットの境界時間を過ぎた後の最初のメッセージで、新しいsessionIdを作成します。
  • アイドルタイムアウト (session.reset.idleMinutes または以前の session.idleMinutes): アイドル期間を過ぎてからメッセージが届いた際に、新しいsessionIdを作成します。デイリーリセットとアイドルタイムアウトの両方が設定されている場合は、先に期限が来た方が適用されます。
  • スレッド親フォークガード (session.parentForkMaxTokens, デフォルト 100000): 親セッションがすでに大きすぎる場合、親のログのフォークをスキップします。新しいスレッドはクリーンな状態で開始されます。0に設定すると無効になります。

実装の詳細:この判定は src/auto-reply/reply/session.ts の initSessionState() で行われます。


セッションストアのスキーマ (sessions.json)

Section titled “セッションストアのスキーマ (sessions.json)”

ストアの値の型は、src/config/sessions.ts にある SessionEntry です。

主要なフィールド(一部抜粋):

  • sessionId: 現在のログID(sessionFileが設定されていない限り、ファイル名はこのIDから派生します)
  • 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: 最終フラッシュ実行時のコンパクション回数

ストアは直接編集可能ですが、Gateway が優先権を持ちます。セッションの実行に伴い、エントリが書き換えられたり再構成されたりすることがあります。

トランスクリプトの構造 (*.jsonl)

Section titled “トランスクリプトの構造 (*.jsonl)”

トランスクリプトは、@mariozechner/pi-coding-agent の SessionManager によって管理されています。

ファイル形式は JSONL で、以下のような構成になっています。

  • 1行目:セッションヘッダー(type: "session"。id、cwd、timestamp、およびオプションの parentSession を含みます)
  • 2行目以降:id と parentId を持つセッションエントリ(ツリー構造)

主なエントリの種類は以下の通りです。

  • message: user、assistant、toolResult のメッセージ
  • custom_message: 拡張機能によって挿入されるメッセージ。これはモデルの Context に入ります(UI 上で非表示に設定することも可能です)
  • custom: 拡張機能の状態。モデルの Context には入りません
  • compaction: 保存された Compaction の要約。firstKeptEntryId と tokensBefore を含みます
  • branch_summary: ツリーのブランチを移動する際に保存される要約

OpenClaw は意図的にトランスクリプトの「修正」を行いません。Gateway は SessionManager を使用して、これらの読み書きを行います。

Context window と追跡されるトークンの違い

Section titled “Context window と追跡されるトークンの違い”

ここでは、2つの異なる概念を理解しておくことが大切です。

  1. Model context window: モデルごとのハードリミット(モデルが一度に認識できるトークン数)
  2. Session store counters: sessions.json に書き込まれる統計情報(/status やダッシュボードで使用されます)

制限を調整する場合は、以下の点に注意してください。

  • Context window は Model catalog から取得されます(設定により上書きも可能です)。
  • ストア内の contextTokens は実行時の推定値、あるいはレポート用の値です。これを厳密な制限値として扱わないようにしてください。

詳細については、/token-use を確認してください。

Compactionは、古い会話を要約して、トランスクリプト内の永続的な compaction エントリにまとめつつ、直近のメッセージはそのまま保持する仕組みです。

Compactionが行われた後、それ以降のやり取りでは以下の内容が参照されます。

  • Compactionによる要約
  • firstKeptEntryId 以降のメッセージ

Compactionは(session pruningとは異なり)永続的なものです。詳細は /concepts/session-pruning を確認してください。

auto-compaction が実行されるタイミング (Pi runtime)

Section titled “auto-compaction が実行されるタイミング (Pi runtime)”

組み込みの Pi agent では、auto-compaction は次の2つのケースで実行されます。

  1. Overflow recovery: モデルがコンテキストのオーバーフローエラーを返した場合。このとき、Compactionを実行してから処理を再試行します。
  2. Threshold maintenance: やり取りが正常に完了した際、以下の条件を満たす場合。

contextTokens > contextWindow - reserveTokens

ここで:

  • contextWindow はモデルのコンテキストウィンドウです
  • reserveTokens はプロンプトや次のモデル出力のために確保されている余裕分(headroom)です

これらは Pi runtime の仕様です。OpenClaw はイベントを消費しますが、いつ Compaction を行うかの決定は Pi が行います。

コンパクション設定 (reserveTokens, keepRecentTokens)

Section titled “コンパクション設定 (reserveTokens, keepRecentTokens)”

Piのコンパクション設定は、Pi settingsの中で管理されています。

{
compaction: {
enabled: true,
reserveTokens: 16384,
keepRecentTokens: 20000,
},
}

OpenClawでは、組み込み実行(embedded runs)向けにセーフティフロア(最低制限)を設けています。

  • compaction.reserveTokens < reserveTokensFloor の場合、OpenClawが値を自動的に引き上げます。
  • デフォルトのフロアは 20000 tokens です。
  • この制限を無効にするには、agents.defaults.compaction.reserveTokensFloor: 0 を設定してください。
  • すでに設定値がフロアより高い場合は、OpenClawは何もせずそのままの値を維持します。

なぜこれが必要なのか:コンパクションが避けられなくなる前に、メモリへの書き込みといったマルチターンの「ハウスキーピング(内部処理)」用のヘッドルームを十分に確保しておくためです。

実装の詳細:src/agents/pi-settings.ts 内の ensurePiCompactionReserveTokens() で処理されています(src/agents/pi-embedded-runner.ts から呼び出されます)。


ユーザーが確認できるインターフェース

Section titled “ユーザーが確認できるインターフェース”

コンパクションの状況やセッションの状態は、以下の方法で確認できます。

  • /status (任意のチャットセッション内)
  • openclaw status (CLI)
  • openclaw sessions / sessions --json
  • Verbose モード: 🧹 Auto-compaction complete というメッセージとコンパクション回数が表示されます。

サイレント・ハウスキーピング (NO_REPLY)

Section titled “サイレント・ハウスキーピング (NO_REPLY)”

OpenClawは、ユーザーに中間出力を表示させたくないバックグラウンドタスク向けに「サイレント」なターンをサポートしています。

慣例:

  • アシスタントは、ユーザーに返信を届けないことを示すために、出力の冒頭に NO_REPLY を付けて開始します。
  • OpenClawは、配信レイヤーでこれを削除または抑制します。

2026.1.10 以降、OpenClawは一部のチャンクが NO_REPLY で始まる場合に ドラフトやタイピングのストリーミング も抑制するようになりました。これにより、サイレントな操作の途中で部分的な出力が漏れるのを防ぎます。


コンパクション前の「メモリフラッシュ」(実装済み)

Section titled “コンパクション前の「メモリフラッシュ」(実装済み)”

目標:自動コンパクションが実行される前に、サイレントなエージェントターンを実行して永続的な状態をディスク(例:エージェントのワークスペース内の memory/YYYY-MM-DD.md)に書き込みます。これにより、コンパクションによって重要なコンテキストが消去されるのを防ぎます。

OpenClawは プレしきい値フラッシュ(pre-threshold flush) アプローチを採用しています:

  1. セッションのコンテキスト使用量を監視します。
  2. 「ソフトしきい値」(Piのコンパクションしきい値より低い値)を超えると、エージェントに対してサイレントな「今すぐメモリを書き込む」指令を実行します。
  3. NO_REPLY を使用するため、ユーザーには何も表示されません。

設定 (agents.defaults.compaction.memoryFlush):

  • enabled (デフォルト: true)
  • softThresholdTokens (デフォルト: 4000)
  • prompt (フラッシュターンのためのユーザーメッセージ)
  • systemPrompt (フラッシュターンのために追加されるシステムプロンプト)

注意点:

  • デフォルトのプロンプトとシステムプロンプトには、配信を抑制するための NO_REPLY ヒントが含まれています。
  • フラッシュはコンパクションサイクルごとに1回実行されます(sessions.json で追跡されます)。
  • フラッシュは埋め込みの Pi セッションでのみ実行されます(CLI バックエンドではスキップされます)。
  • セッションのワークスペースが読み取り専用(workspaceAccess: "ro" または "none")の場合は、フラッシュはスキップされます。
  • ワークスペースのファイルレイアウトと書き込みパターンについては、Memory を参照してください。

Pi は拡張 API で session_before_compact フックも公開していますが、現在の OpenClaw のフラッシュロジックは Gateway 側に実装されています。


トラブルシューティング・チェックリスト

Section titled “トラブルシューティング・チェックリスト”
  • セッションキーが間違っていませんか? /concepts/session を確認し、/status で sessionKey を確かめてください。
  • ストアとトランスクリプトが一致しませんか? openclaw status から Gateway のホストとストアのパスを確認してください。
  • コンパクションが頻発しますか? 以下を確認してください:
    • モデルのコンテキストウィンドウ(小さすぎないか)
    • コンパクション設定(モデルのウィンドウに対して reserveTokens が高すぎると、早い段階でコンパクションが発生することがあります)
    • ツール実行結果の肥大化:セッションのプルーニング(pruning)を有効にするか調整してください
  • サイレントターンが漏れていますか? 返信が NO_REPLY(正確なトークン)で始まっていること、およびストリーミング抑制の修正が含まれているビルドを使用していることを確認してください。
OpenClaw

OpenClaw Expert

まだ解決しませんか?

このページで解決しない場合は、OpenClaw Expertに直接質問してください。