Sessions and memory

セッション状態の認識

複数のセッションが同じ問題に取り組む場合(マネージャーが子セッションに委任する、人間がワーカーセッションに直接参加する、2つのエージェントが sessions_send を介して連携するなど)、各セッションはほかのセッションについて前提を形成します。別のアクターが介入した瞬間、それらの前提は古くなります。セッション状態認識は、その介入を検出し、影響を受けるセッションに一度だけ通知し、行動する前に低コストで最新状態に追いつく手段を提供する仕組みです。

3つの要素が連携します。

  1. 永続シグナルログは、セッションごとに選択された状態変更を記録します。
  2. ウォッチャーはターゲットごとのカーソルを保持し、集約された古い状態の通知を1件受け取ります。
  3. 調整は、changesSince を指定した session_status により正確な差分を取得します。

シグナルログ

監視対象のセッションに重要な変更が発生すると、OpenClaw は共有状態データベース(session_state_events)に型付きイベントを追加します。イベントにはメタデータと1行の概要が含まれますが、メッセージ内容は決して含まれません。

種類 記録されるタイミング ウォッチャーへの通知
human_direct_message 人間が監視対象セッションに直接ターンを送信したとき あり
upstream_missing 採用されたセッションのアップストリームソースが消失したとき あり
goal_changed セッションのゴール状態が作成、更新、またはクリアされたとき あり
child_spawned サブエージェントまたは ACP 子セッションが作成されたとき なし(カーソルを初期化)
run_completed 子の実行が正常に終了したとき なし(ログのみ)
run_failed 子の実行が失敗、タイムアウト、またはキャンセルされたとき なし(ログのみ)
compacted セッションの履歴が Compaction されたとき なし(ログのみ)
adopted カタログセッションが OpenClaw に採用されたとき なし(ログのみ)

各イベントには、そのアクター(humanagent、または system)が記録されます。キャンセルまたはタイムアウトした子の実行は失敗として記録され、正確な結果(cancelledtimeout、または error)がイベントペイロードに保持されます。

セッションの状態バージョンは、そのログ内で最も大きいシーケンス番号です。これは、プルーニング後も存続するセッションごとの永続ヘッドで追跡されます。セッションに記録済みの変更がある場合、sessions_list の行には stateVersion が含まれます。session_status は常にこれを報告します。

ログのみの種類は通知ではなく調整履歴のために存在します。通常の子実行完了の配信は引き続きサブエージェントの通知が管理し、シグナルログが重複して配信することはありません。

ウォッチャー

ウォッチャーとは、ターゲット上のカーソル(session_watch_cursors)を保持するセッションです。カーソルは2つの方法で作成されます。

  • 暗黙的(生成エッジ)。 セッションがサブエージェントまたは ACP 子セッションを生成すると、親のカーソルは子の生成時のバージョンで自動的に初期化されます。親が手動で購読することはありません。
  • 明示的(sessions_send watch: true)。 任意のコーディネーターが、生成したものではないターゲットを監視できます。sessions_sendwatch: true を渡すと、送信が正常にディスパッチされた後、送信元が実際にメッセージを受信したセッションのウォッチャーとして登録されます。登録はターゲットの現在の状態バージョンから開始され、それ以前の履歴によって通知が生成されることはありません。パラメーターが設定されていた場合、ツールの結果に watched: true|false が含まれます。

ウォッチャーの識別子には、エージェントで修飾されたセッションキーが必要です。session.scope="global" では、共有される global キーがエージェント間で曖昧になるため、そのようなセッションには永続ログと changesSince は提供されますが、能動的な通知は提供されません。

監視は自動的にクリーンアップされます。カーソル行はシグナルログの保持期間に合わせて期限切れになり、ウォッチャーセッションがリセットされると削除され、どちらかのセッションが削除された場合にも削除されます。v1 には監視解除の操作はありません。

セッションカタログから採用された監視対象セッションでは、アップストリームで人間が直接操作していないかが一定間隔で確認されます。検出された操作は、ほかの人間による直接ターンと同じシグナルログおよびウォッチャーフローに入ります。

採用されたセッションのアップストリームソースが外部で削除された場合、3回連続で存在しないことが確認されると(モニターの約3ティック分)、ウォッチャーに upstream_missing シグナルが1件送信され、アップストリームリンクが削除されます。カタログセッションを再び継続すると、新しいリンクが作成されます。

通知:多数ではなく1件

通知対象のイベントが記録され、ウォッチャーのカーソルが遅れている場合、ウォッチャーは次のターンでシステム通知を1件受け取ります。

Code
セッション "agent:main:subagent:child" が変更されました(別のアクター)。行動する前に調整してください: session_status sessionKey "agent:main:subagent:child" changesSince 12.

メインセッションのウォッチャーは Heartbeat のウェイクによって即座に起動されます。ネストされたサブエージェントのウォッチャーは、次のターンで通知を受け取ります。

このプロトコルは意図的にスパムを防止します。

  • ウォッチャーとターゲットの組み合わせごとに保留中の通知は1件。 保留中は通知テキストがバイト単位で不変であり、システムイベントキューがそれを重複排除するため、同じターゲットに20件の変更が立て続けに発生しても、ウォッチャーのプロンプトには1行だけ表示されます。
  • 固定されたウォーターマーク。 通知がキューに追加されると、カーソルは通知済みの位置で固定されます。それ以降の重要なイベントは重要イベントのウォーターマークのみを進め、再通知は行いません。
  • ドレイン時に確認し、処理が割り込んだ場合のみ再オープン。 ウォッチャーのターンが通知を消費すると、カーソルが進みます。キューへの追加からドレインまでの間にさらに重要なイベントが届いた場合、残りのイベントについて新しい通知がちょうど1件作成されます。
  • 自己抑制。 ウォッチャーには、自身が発生させたイベントについて通知されることはありません。
  • 再起動からの復旧。 保留中の通知はメモリ内キューに存在します。Gateway の再起動後、起動時のスイープによって永続カーソルから通知が再生成されます。

調整

通知は、ウォッチャーが何をすべきかを正確に示します。changesSince: <version> を指定した session_status は、カーソルを進めることなく、そのバージョン以降の型付きイベントを最大200件返します。

json
{  "stateVersion": 19,  "stateChanges": {    "events": [      {        "sequence": 14,        "kind": "human_direct_message",        "actorType": "human",        "summary": "telegram 経由の人間のメッセージ"      },      { "sequence": 19, "kind": "goal_changed", "actorType": "human", "summary": "ゴールが更新されました" }    ],    "historyGap": false  }}

historyGap: true は、要求されたバージョンが保持されている履歴より前であることを意味します。応答を正確な差分として扱うのではなく、セッション状態全体(sessions_historysession_status)を更新してください。ギャップシグナルは正確です。シーケンスの算術から推測されるのではなく、セッションごとのプルーニング済みウォーターマークに基づきます。

ストレージと制限

履歴は共有状態データベースに保存され、30日および50,000行に制限されます。セッションごとのヘッドは、プルーニング後も単調に増加します。記録はベストエフォートです。追加に失敗した場合はログに記録されますが、元のターンが失敗することはありません。そのため、stateVersion はシグナルログのヘッドであり、トランザクション型の変更データキャプチャーバージョンではありません。

現在の制限事項:

  • 通知の配信では、1つの Gateway プロセスが共有状態データベースを所有することを前提としています。複数の Gateway は永続ログと changesSince を共有しますが、v1 ではプロセス間で通知をプッシュしません。
  • Compaction イベントは組み込みランタイムの Compaction 所有者を対象とします。ネイティブハーネスのみの Compaction は完全には記録されません。
  • キャンセル結果の詳細なペイロードは、現在 ACP 子実行によって生成されます。ネイティブサブエージェントのキャンセルは、汎用的な失敗として示されます。
  • アップストリームの自己エコー検出では、正規化されたユーザーテキストを比較します。セッションの直近10件の OpenClaw 側ユーザーメッセージのいずれかと一致する外部プロンプトは、自己エコーとして扱われます。
  • 単一のローカル Claude JSONL 行が1回の走査上限である 1 MiB を超える場合、v1 ではそのセッションのカーソルがブロックされます。未分類のバイトがスキップされることはありません。
  • ペアリングされた Node の Claude チェックは、1回の実行につき最新50件のトランスクリプト項目を分類します。それを超える大量の項目は、v1 の走査ウィンドウ外になる可能性があります。
  • ペアリングされた Node の Claude 履歴読み取りでは、スレッドが存在しないことを示す確定的な結果が公開されないため、リモートの Claude での削除は v1 では upstream_missing として分類されません。
  • 採用されていないカタログセッションは、v1 では認識レイヤーの対象外です。
  • この機能より前に採用されたセッションにはアップストリームリンクがありません。アップストリーム監視を開始するには、カタログからそのセッションを一度継続してください。
  • アップストリームリンクでは、採用された各セッションキーが1つの所有エージェントに対応することを前提としています(採用にはデフォルトのストアエージェントが使用されます)。同じ外部スレッドを複数のエージェントが採用した場合、v1 では監視されません。

関連項目

Was this useful?
On this page

On this page