セッション管理

OpenClawはエージェントごとに1つの直接チャットセッションをプライマリとして扱います。直接チャットはagent:<agentId>:<mainKey>(デフォルトmain)に折りたたまれ、グループ/チャネルチャットは独自のキーを取得します。session.mainKeyが優先されます。

session.dmScopeを使用して、ダイレクトメッセージのグループ化方法を制御します:

  • main(デフォルト):すべてのDMが連続性のためにメインセッションを共有。
  • per-peer:チャネル間で送信者IDによって分離。
  • per-channel-peer:チャネル + 送信者によって分離(マルチユーザー受信トレイに推奨)。
  • per-account-channel-peer:アカウント + チャネル + 送信者によって分離(マルチアカウント受信トレイに推奨)。 session.identityLinksを使用して、プロバイダー接頭辞付きピアIDを正規のアイデンティティにマッピングし、per-peerper-channel-peer、またはper-account-channel-peerを使用する際に、同じ人がチャネル間でDMセッションを共有できるようにします。

ゲートウェイが信頼の源

すべてのセッション状態はゲートウェイによって所有されています(「マスター」OpenClaw)。UIクライアント(macOSアプリ、WebChatなど)は、ローカルファイルを読み取る代わりに、セッションリストとトークンカウントについてゲートウェイにクエリを実行する必要があります。

  • リモートモードでは、気にするセッションストアはMacではなくリモートゲートウェイホスト上にあります。
  • UIに表示されるトークンカウントは、ゲートウェイのストアフィールド(inputTokensoutputTokenstotalTokenscontextTokens)から取得されます。クライアントはJSONLトランスクリプトを解析して合計を「修正」しません。

状態の場所

  • ゲートウェイホスト上:
    • ストアファイル:~/.openclaw/agents/<agentId>/sessions/sessions.json(エージェントごと)。
  • トランスクリプト:~/.openclaw/agents/<agentId>/sessions/<SessionId>.jsonl(Telegramトピックセッションは.../<SessionId>-topic-<threadId>.jsonlを使用)。
  • ストアはsessionKey -> { sessionId, updatedAt, ... }のマップです。エントリを削除しても安全です。必要に応じて再作成されます。
  • グループエントリには、UIでセッションにラベルを付けるためのdisplayNamechannelsubjectroomspaceが含まれる場合があります。
  • セッションエントリにはoriginメタデータ(ラベル + ルーティングヒント)が含まれ、UIがセッションの由来を説明できるようにします。
  • OpenClawはレガシーのPi/Tauセッションフォルダを読み取りません

セッションプルーニング

OpenClawはデフォルトで、LLM呼び出しの直前にメモリ内コンテキストから古いツール結果をトリミングします。 これはJSONL履歴を書き換えることはありません/concepts/session-pruningを参照してください。

コンパクション前のメモリフラッシュ

セッションが自動コンパクションに近づくと、OpenClawはサイレントメモリフラッシュターンを実行し、モデルに永続的なノートをディスクに書き込むよう促すことができます。これはワークスペースが書き込み可能な場合にのみ実行されます。MemoryおよびCompactionを参照してください。

トランスポート → セッションキーのマッピング

  • 直接チャットはsession.dmScopeに従います(デフォルトmain)。
    • mainagent:<agentId>:<mainKey>(デバイス/チャネル間の連続性)。
      • 複数の電話番号とチャネルが同じエージェントメインキーにマッピングできます。1つの会話へのトランスポートとして機能します。
    • per-peeragent:<agentId>:dm:<peerId>
    • per-channel-peeragent:<agentId>:<channel>:dm:<peerId>
    • per-account-channel-peeragent:<agentId>:<channel>:<accountId>:dm:<peerId>(accountIdはデフォルトでdefault)。
    • session.identityLinksがプロバイダー接頭辞付きピアID(例:telegram:123)に一致する場合、正規のキーが<peerId>を置き換え、同じ人がチャネル間でセッションを共有します。
  • グループチャットは状態を分離:agent:<agentId>:<channel>:group:<id>(ルーム/チャネルはagent:<agentId>:<channel>:channel:<id>を使用)。
    • Telegramフォーラムトピックは分離のためにグループIDに:topic:<threadId>を追加します。
    • レガシーgroup:<id>キーは移行のために引き続き認識されます。
  • インバウンドコンテキストは引き続きgroup:<id>を使用する場合があります。チャネルはProviderから推測され、正規のagent:<agentId>:<channel>:group:<id>形式に正規化されます。
  • その他のソース:
    • Cronジョブ:cron:<job.id>
    • Webhook:hook:<uuid>(フックによって明示的に設定されていない限り)
    • ノード実行:node-<nodeId>

ライフサイクル

  • リセットポリシー:セッションは有効期限が切れるまで再利用され、有効期限は次のインバウンドメッセージで評価されます。
  • 毎日のリセット:デフォルトではゲートウェイホストのローカル時間で午前4時。セッションは、最後の更新が最新の毎日のリセット時間より前の場合、古くなります。
  • アイドルリセット(オプション):idleMinutesはスライディングアイドルウィンドウを追加します。毎日とアイドルの両方のリセットが設定されている場合、どちらか先に期限切れになった方が新しいセッションを強制します。
  • レガシーアイドルのみ:session.reset/resetByType設定なしでsession.idleMinutesを設定すると、OpenClawは後方互換性のためにアイドルのみモードのままになります。
  • タイプごとのオーバーライド(オプション):resetByTypeを使用すると、dmgroupthreadセッションのポリシーをオーバーライドできます(thread = Slack/Discordスレッド、Telegramトピック、コネクタが提供する場合のMatrixスレッド)。
  • チャネルごとのオーバーライド(オプション):resetByChannelはチャネルのリセットポリシーをオーバーライドします(そのチャネルのすべてのセッションタイプに適用され、reset/resetByTypeより優先されます)。
  • リセットトリガー:正確な/newまたは/reset(およびresetTriggersの追加分)は新しいセッションIDを開始し、メッセージの残りを通過させます。/new <model>はモデルエイリアス、provider/model、またはプロバイダー名(ファジーマッチ)を受け入れて、新しいセッションモデルを設定します。/newまたは/resetが単独で送信された場合、OpenClawはリセットを確認するための短い「こんにちは」挨拶ターンを実行します。
  • 手動リセット:ストアから特定のキーを削除するか、JSONLトランスクリプトを削除します。次のメッセージで再作成されます。
  • 分離されたcronジョブは、実行ごとに常に新しいsessionIdを作成します(アイドル再利用なし)。

送信ポリシー(オプション)

個々のIDをリストアップせずに、特定のセッションタイプの配信をブロックします。

{
  session: {
    sendPolicy: {
      rules: [
        { action: "deny", match: { channel: "discord", chatType: "group" } },
        { action: "deny", match: { keyPrefix: "cron:" } }
      ],
      default: "allow"
    }
  }
}

ランタイムオーバーライド(所有者のみ):

  • /send on → このセッションを許可
  • /send off → このセッションを拒否
  • /send inherit → オーバーライドをクリアして設定ルールを使用 これらをスタンドアロンメッセージとして送信して登録します。

設定(オプションのリネーム例)

// ~/.openclaw/openclaw.json
{
  session: {
    scope: "per-sender",      // グループキーを分離
    dmScope: "main",          // DM連続性(共有受信トレイにはper-channel-peer/per-account-channel-peerを設定)
    identityLinks: {
      alice: ["telegram:123456789", "discord:987654321012345678"]
    },
    reset: {
      // デフォルト:mode=daily、atHour=4(ゲートウェイホストのローカル時間)。
      // idleMinutesも設定すると、どちらか先に期限切れになった方が優先されます。
      mode: "daily",
      atHour: 4,
      idleMinutes: 120
    },
    resetByType: {
      thread: { mode: "daily", atHour: 4 },
      dm: { mode: "idle", idleMinutes: 240 },
      group: { mode: "idle", idleMinutes: 120 }
    },
    resetByChannel: {
      discord: { mode: "idle", idleMinutes: 10080 }
    },
    resetTriggers: ["/new", "/reset"],
    store: "~/.openclaw/agents/{agentId}/sessions/sessions.json",
    mainKey: "main",
  }
}

検査

  • openclaw status — ストアパスと最近のセッションを表示。
  • openclaw sessions --json — すべてのエントリをダンプ(--active <minutes>でフィルタリング)。
  • openclaw gateway call sessions.list --params '{}' — 実行中のゲートウェイからセッションを取得(リモートゲートウェイアクセスには--url/--tokenを使用)。
  • チャットでスタンドアロンメッセージとして/statusを送信して、エージェントが到達可能かどうか、セッションコンテキストのどれだけが使用されているか、現在のthinking/verbose切り替え、WhatsApp web認証情報が最後に更新された時期を確認します(再リンクの必要性を見つけるのに役立ちます)。
  • /context listまたは/context detailを送信して、システムプロンプトと注入されたワークスペースファイルの内容(および最大のコンテキスト貢献者)を確認します。
  • スタンドアロンメッセージとして/stopを送信して、現在の実行を中止し、そのセッションのキューイングされたfollowupをクリアし、そこからスポーンされたサブエージェント実行を停止します(返信には停止カウントが含まれます)。
  • スタンドアロンメッセージとして/compact(オプションの指示)を送信して、古いコンテキストを要約し、ウィンドウスペースを解放します。/concepts/compactionを参照してください。
  • JSONLトランスクリプトを直接開いて、完全なターンを確認できます。

ヒント

  • プライマリキーは1対1のトラフィック専用にします。グループには独自のキーを保持させます。
  • 自動クリーンアップを行う場合、他の場所のコンテキストを保持するために、ストア全体ではなく個々のキーを削除します。

セッションオリジンメタデータ

各セッションエントリは、originにどこから来たか(ベストエフォート)を記録します:

  • label:人間のラベル(会話ラベル + グループサブジェクト/チャネルから解決)
  • provider:正規化されたチャネルID(拡張機能を含む)
  • from/to:インバウンドエンベロープからの生のルーティングID
  • accountId:プロバイダーアカウントID(マルチアカウントの場合)
  • threadId:チャネルがサポートする場合のスレッド/トピックID オリジンフィールドは、ダイレクトメッセージ、チャネル、グループに対して入力されます。コネクタが配信ルーティングのみを更新する場合(例:DMメインセッションを新鮮に保つため)、セッションがその説明メタデータを保持するように、インバウンドコンテキストを提供する必要があります。拡張機能は、インバウンドコンテキストでConversationLabelGroupSubjectGroupChannelGroupSpaceSenderNameを送信し、recordSessionMetaFromInboundを呼び出す(または同じコンテキストをupdateLastRouteに渡す)ことでこれを実行できます。