3. エージェントランタイム(PI Embedded)

メッセージ処理ループ、ツール呼び出し、ストリーミング、コンパクション

概要

PI Embedded Agent Runtimeは、OpenClawの中核エンジンです。 @mariozechner/pi-agent-core および @mariozechner/pi-coding-agent SDKを ラップし、プロセス内で動作するステートフルなストリーミングエージェントループを実現しています。

「Embedded」の意味:外部APIサービスではなく、OpenClawプロセス内でエージェントが動作します。 これにより、永続セッション、統合ツール実行、リアルタイムストリーミング、マルチチャンネル統合が可能になります。

メッセージ処理の全体フロー

メッセージ入力 │ ▼ Phase 1: セットアップ (run.ts:174-305) ├── レーンキューイング(セッション単位 + グローバル) ├── モデル解決(フック: before_model_resolve, before_agent_start) ├── コンテキストウィンドウガード(最小16Kトークン) └── 認証プロファイル解決(ローテーション対応) │ ▼ Phase 2: 実行試行 (attempt.ts:222-1282) ├── ワークスペース・サンドボックスセットアップ ├── ツール生成 → createOpenClawCodingTools() ├── システムプロンプト構築 ├── セッション作成 → createAgentSession() ├── 履歴サニタイズ │ ├── validateAnthropicTurns() / validateGeminiTurns() │ ├── limitHistoryTurns() │ └── sanitizeToolUseResultPairing() ├── サブスクリプション設定 → subscribeEmbeddedPiSession() ├── アクティブラン登録 ├── プロンプト送信 → activeSession.prompt(effectivePrompt) ├── コンパクション待機 └── 結果収集(assistantTexts, toolMetas, usage) │ ▼ Phase 3: リトライ・エラー処理 (run.ts:480-1074) ├── コンテキストオーバーフロー → 自動コンパクション(最大3回) ├── 認証失敗 → プロファイルローテーション ├── 思考レベル非対応 → フォールバック ├── レート制限 / 課金エラー → FailoverError └── タイムアウト → 中断

Phase 1: セットアップの詳細

レーンキューイング

src/agents/pi-embedded-runner/run.ts:177-183

メッセージはセッション固有レーンとグローバルレーンの両方にキューイングされ、 セッションごとの逐次処理を保証します。4種類のレーンがあります:

レーン用途
Mainメインセッションの処理
Cronスケジュールタスクの処理
Subagentサブエージェントの処理
Nestedネストされたサブエージェント

認証プロファイル解決

src/agents/pi-embedded-runner/run.ts:307-471

マルチプロファイル認証をサポートし、クールダウン/ローテーション機能があります。 あるプロファイルが失敗した場合、自動的に次のプロファイルに切り替わります。

Phase 2: 実行試行の詳細

ツール生成

src/agents/pi-embedded-runner/run/attempt.ts:291-329

createOpenClawCodingTools() がフルツールセットを生成します。 ツールは builtInToolscustomTools に分割され、 マルチレイヤーのポリシーフィルタリングを通過します。

セッション管理

src/agents/pi-embedded-runner/run/attempt.ts:490-589

メッセージステアリング

activeSession.steer(text) により、実行中のストリーミングランにメッセージを注入できます。 これにより、エージェントの処理中にも追加の指示を送ることが可能です。

ストリーミング / サブスクリプションモデル

src/agents/pi-embedded-subscribe.ts:33-717

サブスクリプションシステムは、SDKイベントとユーザー向け出力の橋渡しを行います。

イベントハンドラディスパッチ

イベントハンドラ実行モード
message_starthandleMessageStart同期
message_updatehandleMessageUpdate同期
message_endhandleMessageEnd同期
tool_execution_starthandleToolExecutionStart非同期 (best-effort)
tool_execution_updatehandleToolExecutionUpdate同期
tool_execution_endhandleToolExecutionEnd非同期 (best-effort)
auto_compaction_starthandleAutoCompactionStart同期
auto_compaction_endhandleAutoCompactionEnd同期

テキスト処理パイプライン

生ストリーム │ ▼ stripBlockTags() ← <think>タグ除去、<final>タグ処理 ▼ stripDowngradedToolCallText() ← 履歴アーティファクト除去 ▼ メッセージングツール重複チェック ▼ EmbeddedBlockChunker ← 配信可能なチャンクに分割 ▼ emitBlockChunk() ← onBlockReply()コールバック ▼ リプライディレクティブ解析(メディアURL、音声フラグ、reply-to ID)

状態管理(EmbeddedPiSubscribeState)

ツールループ検出

src/agents/tool-loop-detection.ts

エージェントが無限ループに陥ることを防ぐ洗練されたシステムです。 直近30回のツール呼び出しをスライディングウィンドウで追跡します。

検出器閾値アクション
汎用リピート検出10回で警告、20回でクリティカル警告メッセージ注入
ポーリング無進展検出ポーリングツールの状態変化なし停止促進
ピンポン検出交互呼び出しパターンパターン通知
グローバル回路遮断器30回同一無進展呼び出し強制停止

SHA-256ハッシュ(ツール名 + 安定シリアライズされたパラメータ)でパターンマッチングを行います。

コンパクション(コンテキストウィンドウ管理)

src/agents/compaction.tssrc/agents/pi-embedded-runner/compact.ts

2つのモード

モードトリガー詳細
自動コンパクションSDKがコンテキスト上限接近時に発動auto_compaction_start/endイベントで観測
明示コンパクションオーバーフロー回復時に呼び出しcompactEmbeddedPiSessionDirect()

コンパクションアルゴリズム

オーバーフロー回復フロー

コンテキストオーバーフロー検出 │ ▼ 試行が既に自動コンパクション済み? │ ├── はい → コンパクションなしでリトライ │ └── いいえ ↓ ▼ 明示コンパクション実行 │ ├── 成功 → リトライ │ └── 失敗 ↓ ▼ ツール結果の切り詰め │ ├── 成功 → リトライ │ └── 失敗 ↓ ▼ エラー返却「/resetを使ってください」

エラー処理とリトライ

多層エラー戦略

  1. L1 認証プロファイルローテーション — 失敗プロファイルにクールダウンを設定し次に切り替え
  2. L2 思考レベルフォールバック — サポートされていない思考レベルを段階的にフォールバック
  3. L3 モデルフェイルオーバー — 全プロファイル枯渇時に代替モデルへ切り替え(FailoverError)
  4. L4 コンテキストオーバーフロー回復 — 最大3回のコンパクション試行
  5. L5 タイムアウト処理 — AbortControllerによるキャンセル

「Embedded」ならではの特徴

単純なAPI呼び出しと異なる点:

  1. プロセス内実行 — 同一Node.jsプロセスで動作し、状態を共有
  2. 永続セッション — JSONLファイルに完全なセッション状態を永続化
  3. 並行ラン管理 — グローバル ACTIVE_EMBEDDED_RUNS マップでアクティブランを追跡
  4. レーンベース並行制御 — セッションレーン + グローバルレーンで競合を防止
  5. セッション書き込みロック — ファイルレベルのロック
  6. 統合ツール実行 — ワークスペース・サンドボックス・ファイルシステムへのフルアクセス
  7. ストリーミング統合 — WebSocket経由のリアルタイムイベント発行
  8. プラグイン/フックシステム — 全ステージにライフサイクルフック
  9. マルチチャンネルサポート — 同一ランタイムで全チャンネルを処理
  10. サンドボックス分離 — ツール呼び出しのオプショナルサンドボックス実行