Agent Loop(エージェントループ)(OpenClaw)
エージェンティックループ(agentic loop)は、エージェント(agent)の完全な「実際の」実行です:入力の受け取り → コンテキスト(context)の組み立て → モデル(model)の推論 → ツール(tool)の実行 → ストリーミング(streaming)応答 → 永続化。これは、メッセージをアクションと最終応答に変換しながら、セッション(session)の状態を一貫性のあるものに保つ権威あるパスです。
OpenClaw では、ループはセッションごとに単一のシリアライズされた実行であり、モデルが思考し、ツールを呼び出し、出力をストリーミングする際にライフサイクル(lifecycle)とストリーム(stream)イベント(event)を発行します。このドキュメントでは、この本格的なループがエンドツーエンドでどのように配線されているかを説明します。
エントリポイント
- Gateway RPC: agent と agent.wait
- CLI: agent コマンド
動作の仕組み(高レベル)
- agent RPC はパラメータを検証し、セッション(sessionKey/sessionId)を解決し、セッションメタデータを永続化し、すぐに { runId, acceptedAt } を返します。
- agentCommand がエージェントを実行します:
- モデル + thinking/verbose のデフォルトを解決
- スキル(skills)のスナップショットをロード
- runEmbeddedPiAgent(pi-agent-core ランタイム)を呼び出し
- 埋め込みループが発行しない場合、lifecycle end/error を発行
- runEmbeddedPiAgent:
- セッションごと + グローバルキュー(queue)を介して実行をシリアライズ
- モデル + 認証プロファイル(auth profile)を解決し、pi セッションを構築
- pi イベントにサブスクライブし、assistant/tool のデルタをストリーム
- タイムアウトを強制 -> 超過した場合は実行を中止
- ペイロード(payload)+ 使用状況メタデータを返す
- subscribeEmbeddedPiSession は pi-agent-core イベントを OpenClaw の agent ストリームにブリッジします:
- tool イベント => stream: "tool"
- assistant デルタ => stream: "assistant"
- lifecycle イベント => stream: "lifecycle" (phase: "start" | "end" | "error")
- agent.wait は waitForAgentJob を使用します:
- runId の lifecycle end/error を待機
- { status: ok|error|timeout, startedAt, endedAt, error? } を返す
キューイング + 同時実行
- 実行はセッションキーごと(セッションレーン)にシリアライズされ、オプションでグローバルレーンを経由します。
- これにより、ツール/セッションの競合を防ぎ、セッション履歴の一貫性を保ちます。
- メッセージングチャネルは、このレーンシステムにフィードするキューモード(collect/steer/followup)を選択できます。 Command Queue を参照してください。
セッション + ワークスペースの準備
- ワークスペース(workspace)が解決および作成されます。サンドボックス化された実行は、サンドボックスワークスペースルートにリダイレクトされる場合があります。
- スキルがロード(またはスナップショットから再利用)され、環境とプロンプト(prompt)に注入されます。
- ブートストラップ/コンテキストファイルが解決され、システムプロンプト(system prompt)レポートに注入されます。
- セッション書き込みロックが取得されます。SessionManager はストリーミング前に開かれて準備されます。
プロンプトの組み立て + システムプロンプト
- システムプロンプトは、OpenClaw のベースプロンプト、スキルプロンプト、ブートストラップコンテキスト、および実行ごとのオーバーライドから構築されます。
- モデル固有の制限とコンパクション(compaction)予約トークンが適用されます。
- モデルが見るものについては、System prompt を参照してください。
フックポイント(インターセプト可能な場所)
OpenClaw には 2 つのフック(hook)システムがあります:
- 内部フック(Gateway hooks):コマンドとライフサイクルイベントのためのイベント駆動スクリプト。
- プラグインフック(Plugin hooks):エージェント/ツールライフサイクルとゲートウェイパイプライン内の拡張ポイント。
内部フック(Gateway hooks)
- agent:bootstrap:システムプロンプトが確定する前に、ブートストラップファイルを構築する際に実行されます。 これを使用して、ブートストラップコンテキストファイルを追加/削除します。
- コマンドフック:/new、/reset、/stop、およびその他のコマンドイベント(Hooks ドキュメントを参照)。
セットアップと例については、Hooks を参照してください。
プラグインフック(エージェント + ゲートウェイライフサイクル)
これらはエージェントループまたはゲートウェイパイプライン内で実行されます:
- before_agent_start:実行が開始される前にコンテキストを注入するか、システムプロンプトをオーバーライドします。
- agent_end:完了後に最終メッセージリストと実行メタデータを検査します。
- before_compaction / after_compaction:コンパクションサイクルを観察または注釈します。
- before_tool_call / after_tool_call:ツールパラメータ/結果をインターセプトします。
- tool_result_persist:ツール結果がセッショントランスクリプトに書き込まれる前に、同期的に変換します。
- message_received / message_sending / message_sent:受信 + 送信メッセージフック。
- session_start / session_end:セッションライフサイクルの境界。
- gateway_start / gateway_stop:ゲートウェイライフサイクルイベント。
フック API と登録の詳細については、Plugins を参照してください。
ストリーミング + 部分応答
- Assistant デルタは pi-agent-core からストリームされ、assistant イベントとして発行されます。
- ブロック(block)ストリーミングは、text_end または message_end のいずれかで部分応答を発行できます。
- 推論(reasoning)ストリーミングは、別のストリームとして、またはブロック応答として発行できます。
- チャンキング(chunking)とブロック応答の動作については、Streaming を参照してください。
ツール実行 + メッセージングツール
- ツールの start/update/end イベントは tool ストリームで発行されます。
- ツール結果は、ログ記録/発行の前にサイズと画像ペイロードに対してサニタイズされます。
- メッセージングツールの送信は追跡され、重複する assistant 確認を抑制します。
応答の整形 + 抑制
- 最終ペイロードは以下から組み立てられます:
- assistant テキスト(およびオプションの推論)
- インラインツールサマリー(verbose + 許可されている場合)
- モデルエラー時の assistant エラーテキスト
- NO_REPLY はサイレントトークンとして扱われ、送信ペイロードからフィルタリングされます。
- メッセージングツールの重複は最終ペイロードリストから削除されます。
- レンダリング可能なペイロードが残っておらず、ツールがエラーになった場合、フォールバックツールエラー応答が発行されます (メッセージングツールがすでにユーザーに表示される応答を送信している場合を除く)。
コンパクション + リトライ
- 自動コンパクションは compaction ストリームイベントを発行し、リトライをトリガーできます。
- リトライ時には、重複出力を避けるために、インメモリバッファとツールサマリーがリセットされます。
- コンパクションパイプラインについては、Compaction を参照してください。
イベントストリーム(現在)
- lifecycle: subscribeEmbeddedPiSession(および agentCommand によるフォールバック)によって発行
- assistant: pi-agent-core からストリームされたデルタ
- tool: pi-agent-core からストリームされたツールイベント
チャットチャネルの処理
- Assistant デルタはチャット delta メッセージにバッファリングされます。
- チャット final は lifecycle end/error で発行されます。
タイムアウト
- agent.wait デフォルト:30s(待機のみ)。timeoutMs パラメータでオーバーライド。
- エージェントランタイム:agents.defaults.timeoutSeconds デフォルト 600s。runEmbeddedPiAgent の中止タイマーで適用。
早期終了する可能性がある場所
- エージェントタイムアウト(中止)
- AbortSignal(キャンセル)
- Gateway 切断または RPC タイムアウト
- agent.wait タイムアウト(待機のみ、エージェントは停止しない)