Fundamentals
エージェントループ
エージェントループは、メッセージをアクションと応答に変換する、セッションごとに直列化された実行です。受信、コンテキストの組み立て、モデル推論、ツール実行、ストリーミング、永続化で構成されます。
エントリーポイント
- Gateway RPC:
agentとagent.wait。 - CLI:
openclaw agent。
実行シーケンス
agentRPC はパラメータを検証し、セッション(sessionKey/sessionId)を解決してセッションメタデータを永続化し、直ちに{ runId, acceptedAt }を返します。agentCommandはターンを実行します。モデルと thinking/verbose/trace のデフォルトを解決し、Skills スナップショットを読み込み、runEmbeddedAgentを呼び出します。埋め込みループがまだ発行していない場合は、フォールバックの ライフサイクル終了/エラー を発行します。runEmbeddedAgent:セッションごとおよびグローバルのキューを介して実行を直列化し、モデルと認証プロファイルを解決し、OpenClaw セッションを構築してランタイムイベントを購読し、アシスタント/ツールの差分をストリーミングし、実行タイムアウトを適用して(期限切れ時に中止)、ペイロードと使用量メタデータを返します。Codex app-server のターンでは、受理後、終端イベントの前に app-server の進行が止まったターンも中止します。subscribeEmbeddedAgentSessionは、ランタイムイベントをagentストリームに橋渡しします。ツールイベントはstream: "tool"、アシスタントの差分はstream: "assistant"、ライフサイクルイベントはstream: "lifecycle"(phase: "start" | "end" | "error")として送られます。agent.wait(waitForAgentRun)は、runIdに対する ライフサイクル終了/エラー を待ち、{ status: ok|error|timeout, startedAt, endedAt, error? }を返します。
キューイングと並行処理
実行はセッションキーごと(セッションレーン)に直列化され、必要に応じてグローバルレーンも通るため、ツールやセッションの競合を防ぎます。メッセージングチャネルは、このレーンシステムに投入するキューモード(steer/followup/collect/interrupt)を選択します。コマンドキューを参照してください。
トランスクリプトへの書き込みは、さらにセッションファイルに対するセッション書き込みロックで保護されます。このロックはプロセスを認識するファイルベースのロックであるため、プロセス内キューを迂回する書き込みや、別プロセスからの書き込みも検出します。書き込み側は、セッションがビジーであると報告するまで、最大 session.writeLock.acquireTimeoutMs(デフォルトは 60000 ms、環境変数 OPENCLAW_SESSION_WRITE_LOCK_ACQUIRE_TIMEOUT_MS で上書き可能)待機します。
セッション書き込みロックは、デフォルトでは再入可能ではありません。同一の論理的な書き込み主体を維持しながら、意図的に同じロックの取得をネストするヘルパーは、allowReentrant: true で明示的にオプトインする必要があります。
セッションとワークスペースの準備
- ワークスペースを解決して作成します。サンドボックス化された実行では、サンドボックスのワークスペースルートにリダイレクトされる場合があります。
- Skills を読み込み(またはスナップショットから再利用し)、環境変数とプロンプトに注入します。
- ブートストラップ/コンテキストファイルを解決し、システムプロンプトに注入します。
- ストリーミング開始前にセッション書き込みロックを取得し、セッショントランスクリプトの保存先を準備します。その後のトランスクリプトの書き換え、Compaction、切り詰めの各パスも、SQLite のトランスクリプト行を変更する前に同じロックを取得する必要があります。
プロンプトの組み立て
システムプロンプトは、OpenClaw のベースプロンプト、Skills プロンプト、ブートストラップコンテキスト、実行ごとの上書きから構築されます。モデル固有の制限と Compaction 用の予約トークンが適用されます。モデルが参照する内容については、システムプロンプトを参照してください。
フック
OpenClaw には、2 つのフックシステムがあります。
- 内部フック(Gateway フック):コマンドおよびライフサイクルイベント用のイベント駆動スクリプト。
- Plugin フック:エージェント/ツールのライフサイクルおよび Gateway パイプライン内の拡張ポイント。
内部フック(Gateway フック)
agent:bootstrap:システムプロンプトが確定する前のブートストラップファイル構築時に実行されます。ブートストラップコンテキストファイルの追加や削除に使用します。- コマンドフック:
/new、/reset、/stop、その他のコマンドイベント(フックのドキュメントを参照)。
セットアップと例については、フックを参照してください。
Plugin フック
これらは、エージェントループまたは Gateway パイプライン内で実行されます。
| フック | 実行タイミング |
|---|---|
before_model_resolve |
セッション前(messages なし)。解決前にプロバイダー/モデルを決定論的に上書きします。 |
before_prompt_build |
セッション読み込み後(messages あり)。送信前に prependContext、systemPrompt、prependSystemContext、または appendSystemContext を注入します。ターンごとの動的テキストには prependContext を使用し、システムプロンプト領域に属する安定したガイダンスにはシステムコンテキストフィールドを使用します。 |
before_agent_start |
どちらのフェーズでも実行される可能性があるレガシー互換性フックです。上記の明示的なフックを優先してください。 |
before_agent_reply |
インラインアクションの後、LLM 呼び出しの前に実行されます。Plugin がターンを引き受け、合成応答を返すか、応答を完全に抑制できます。 |
agent_end |
完了後、最終メッセージリストと実行メタデータを伴って実行されます。 |
before_compaction / after_compaction |
Compaction サイクルを監視または注釈付けします。 |
before_tool_call / after_tool_call |
ツールのパラメータ/結果をインターセプトします。 |
before_install |
オペレーターのインストールポリシー実行後、現在のプロセスに Plugin フックが読み込まれている場合に、ステージング済みの Skills/Plugin インストール素材に対して実行されます。 |
tool_result_persist |
OpenClaw が所有するセッショントランスクリプトに書き込まれる前に、ツール結果を同期的に変換します。 |
message_received / message_sending / message_sent |
受信および送信メッセージのフックです。 |
session_start / session_end |
セッションライフサイクルの境界です。 |
gateway_start / gateway_stop |
Gateway のライフサイクルイベントです。 |
送信/ツールガードに関するフックの判定ルール:
before_tool_call:{ block: true }は終端判定となり、優先度の低いハンドラーを停止します。{ block: false }は何もせず、先行するブロックを解除しません。before_install:上記と同じ終端/無操作のセマンティクスです。CLI のインストールおよび更新パスを対象とする、オペレーター所有のインストール許可/ブロック判定には、before_installではなくsecurity.installPolicyを使用してください。message_sending:{ cancel: true }は終端判定となり、優先度の低いハンドラーを停止します。{ cancel: false }は何もせず、先行するキャンセルを解除しません。
フック API と登録の詳細については、Plugin フックを参照してください。
ハーネスは、これらのフックを適合させることができます。Codex app-server ハーネスは、文書化されたミラーサーフェスの互換性契約として OpenClaw Plugin フックを維持します。Codex ネイティブフックは、別の低レベルな Codex メカニズムです。
ストリーミング
- アシスタントの差分は、エージェントランタイムから
assistantイベントとしてストリーミングされます。 - ブロックストリーミングは、
text_endまたはmessage_endで部分的な応答を発行できます。 - 推論ストリーミングは、独立したストリームにすることも、ブロック応答にすることもできます。
- チャンク分割とブロック応答の動作については、ストリーミングを参照してください。
ツール実行
- ツールの開始/更新/終了イベントは、
toolストリームで発行されます。 - ツール結果は、ログ記録/発行の前にサイズと画像ペイロードについてサニタイズされます。
- メッセージングツールによる送信は、重複するアシスタント確認を抑制するために追跡されます。
応答の整形
最終ペイロードは、アシスタントのテキスト(および任意の推論)、インラインツールの要約(verbose が有効で許可されている場合)、モデルでエラーが発生した場合のアシスタントエラーテキストから組み立てられます。
- 完全一致するサイレントトークン
NO_REPLYは、送信ペイロードから除外されます。 - メッセージングツールによる重複は、最終ペイロードリストから削除されます。
- レンダリング可能なペイロードが残っておらず、かつツールでエラーが発生した場合、メッセージングツールがすでにユーザーに表示される応答を送信していない限り、フォールバックのツールエラー応答が発行されます。
Compaction と再試行
自動 Compaction は compaction ストリームイベントを発行し、再試行をトリガーすることがあります。再試行時には、出力の重複を避けるため、メモリ内バッファとツール要約がリセットされます。Compactionを参照してください。
イベントストリーム
lifecycle:subscribeEmbeddedAgentSessionによって発行されます(フォールバックとしてagentCommandからも発行されます)。assistant:エージェントランタイムからストリーミングされる差分です。tool:エージェントランタイムからストリーミングされるツールイベントです。
Gateway は、ライフサイクルイベントおよびツールの開始/終端イベントを、サイズ制限がありメタデータのみを保持する監査台帳に投影します。この投影は、プロンプト、メッセージ、ツール引数、ツール結果、生のエラーをトランスクリプト/ランタイムのパス外へコピーすることなく、出所と結果コードを記録します。
チャットチャネルの処理
アシスタントの差分は、チャットの delta メッセージにバッファリングされます。チャットの final は、ライフサイクル終了/エラー 時に発行されます。
タイムアウト
| タイムアウト | デフォルト | 注記 |
|---|---|---|
agent.wait |
30s | 待機のみ。timeoutMs パラメーターで上書きできます。基盤となる実行は停止しません。 |
エージェント実行時間(agents.defaults.timeoutSeconds) |
172800s (48h) | runEmbeddedAgent の中止タイマーによって適用されます。実行時間の上限を無制限にするには 0 を設定します。ただし、モデルストリームの生存監視は引き続き適用されます。 |
| Cron の隔離されたエージェントターン | Cron が所有 | スケジューラーは実行開始時に独自のタイマーを開始し、設定された期限に達すると実行を中止します。その後、古い子セッションによってレーンが停止したままにならないよう、タイムアウトを記録する前に制限付きのクリーンアップを実行します。 |
| モデルのアイドルタイムアウト | クラウド 120s、セルフホスト 300s | アイドル時間枠内に応答チャンクが到着しない場合、OpenClaw はモデルリクエストを中止します。models.providers.<id>.timeoutSeconds は、低速なローカルまたはセルフホストのプロバイダー向けに、このアイドル監視時間を延長します。ただし、より短い有限値の agents.defaults.timeoutSeconds または実行固有のタイムアウトがある場合、それらはエージェント実行全体を管理するため、その範囲内に制限されます。実行時間の上限が無制限でも、プロバイダークラスのアイドル監視は維持されます。明示的なモデルまたはエージェントのタイムアウトがない Cron トリガーのクラウドモデル実行にも同じデフォルトが適用されます。明示的な Cron 実行タイムアウトがある場合は、設定済みのモデルフォールバックを外側の Cron 期限までに実行できるよう、クラウドモデルストリームの停止は最大 60s に制限されます。実際にローカルなエンドポイント(ループバックまたはプライベートの baseUrl)で Cron によってトリガーされた実行では、ローカルのアイドル監視無効化が維持されます。ネットワーク上の baseUrl を使用するセルフホストプロバイダーには、暗黙の 300s 監視が適用されます。明示的な Cron 実行タイムアウトがある場合、ローカルまたはセルフホストの停止時間はそのタイムアウトを上限とします。低速なローカルプロバイダーには models.providers.<id>.timeoutSeconds を設定してください。 |
| プロバイダー HTTP リクエストタイムアウト | models.providers.<id>.timeoutSeconds |
接続、ヘッダー、本文、SDK リクエストタイムアウト、保護された fetch の中止処理、およびそのプロバイダーのモデルストリームのアイドル監視を対象とします。エージェント全体の実行時間タイムアウトを引き上げる前に、低速なローカルまたはセルフホストのプロバイダー(Ollama など)に使用してください。モデルリクエストをより長く実行する必要がある場合は、エージェントまたは実行時間のタイムアウトも少なくとも同じ長さにしてください。 |
停止したセッションの診断
診断を有効にすると、diagnostics.stuckSessionWarnMs(デフォルトは 120000 ms)は、応答、ツール、ステータス、ブロック、または ACP の進行が観測されないまま長時間 processing 状態にあるセッションを分類します。
- アクティブな埋め込み実行、モデル呼び出し、ツール呼び出しは
session.long_runningとして報告されます。所有者がいる無応答のモデル呼び出しは、低速または非ストリーミングのプロバイダーが早すぎる段階で停止と判定されないよう、diagnostics.stuckSessionAbortMsまではsession.long_runningのままになります。 - 最近進行がないアクティブな処理は
session.stalledとして報告されます。所有者がいるモデル呼び出しは、中止しきい値以降にsession.stalledに切り替わります。所有者がいない古いモデルまたはツールのアクティビティが長時間実行中として隠されることはありません。 session.stuckは、所有者がいない古いモデルまたはツールのアクティビティがある、アイドル状態のキュー済みセッションなど、復旧可能な古いセッション管理情報のために予約されています。
diagnostics.stuckSessionAbortMs のデフォルトは、少なくとも 5 分、かつ警告しきい値の 3 倍です。古いセッション管理情報は、復旧ゲートを通過すると影響を受けたセッションレーンを直ちに解放します。一方、停止した埋め込み実行は中止しきい値を超えた後にのみ中止およびドレインされるため、単に低速な実行を打ち切ることなく、キュー済みの処理を再開できます。復旧では、要求済みおよび完了済みの構造化された結果が発行されます。診断状態がアイドルとしてマークされるのは、同じ処理世代が引き続き現在のものである場合だけです。また、セッションが変化しない間は、繰り返される session.stuck 診断の間隔が段階的に延長されます。
処理が早期終了する可能性がある箇所
- エージェントタイムアウト(中止)
- AbortSignal(キャンセル)
- Gateway の切断または RPC タイムアウト
agent.waitタイムアウト(待機のみ。エージェントは停止しません)
関連項目
- ツール - 利用可能なエージェントツール
- フック - エージェントのライフサイクルイベントによってトリガーされるイベント駆動型スクリプト
- Compaction - 長い会話が要約される仕組み
- 実行承認 - シェルコマンドの承認ゲート
- 思考 - 思考および推論レベルの設定