Web interfaces
WebChat
状態: macOS/iOS の SwiftUI チャット UI は Gateway WebSocket と直接通信します。埋め込みブラウザーも、ローカルの静的サーバーも使用しません。
概要
- Gateway 用のネイティブチャット UI です。
- 他のチャネルと同じセッションおよびルーティングルールを使用します。
- 決定論的ルーティング: 返信は常に WebChat に返されます。
- 履歴は常に Gateway から取得されます(ローカルファイルの監視は行いません)。Gateway に到達できない場合、WebChat は読み取り専用になります。
クイックスタート
- Gateway を起動します。
- WebChat UI(macOS/iOS アプリ)または Control UI のチャットタブを開きます。
- 有効な Gateway 認証経路が構成されていることを確認します(loopback 上でも、デフォルトでは共有シークレットを使用します)。
仕組み
- UI は Gateway WebSocket に接続し、
chat.history、chat.send、chat.inject、およびchat.message.getRPC メソッドを使用します。 chat.historyは安定性を確保するために制限されています。Gateway は長いテキストフィールドを切り詰め、容量の大きいメタデータを省略し、サイズ超過のエントリを[chat.history omitted: message too large]に置き換える場合があります。API クライアントはリクエストごとにmaxCharsを送信し、1 回の呼び出しに限ってデフォルトの上限を上書きできます。chat.historyで表示可能なアシスタントメッセージが切り詰められた場合、Control UI はサイドリーダーを開き、デフォルトの履歴ペイロードを増やさずに、chat.message.getを通じて表示用に正規化された完全なエントリをオンデマンドで取得できます。chat.message.getはchat.historyと同じトランスクリプトブランチおよび表示ルールを使用しますが、messageIdで 1 件のエントリを対象とし、完全な内容を返せなくなった場合はその旨を正確に示す利用不可理由を返します。chat.historyは追記専用セッションファイルのアクティブなトランスクリプトブランチに従うため、放棄された書き換えブランチや置き換え済みのプロンプトコピーは WebChat に表示されません。- Compaction エントリは「圧縮済みの履歴」という区切りとして表示され、圧縮されたトランスクリプトがチェックポイントとして保持されていることを説明します。また、セッションチェックポイントを開くためのアクション(権限が許可する場合はブランチ作成または復元)も表示されます。
- Control UI は
chat.historyが返した基盤となる Gateway のsessionIdを記憶し、後続のchat.send呼び出しに含めます。そのため、ユーザーがセッションを開始またはリセットしない限り、再接続やページの再読み込み後も保存済みの同じ会話が継続されます。 - フォアグラウンド送信には、レンダリングされた履歴に表示されているブランチのリーフも
expectedLeafEntryIdとして含まれます。別のクライアントが先にブランチを切り替えていた場合、Control UI はメッセージを新しいブランチへ投稿せず、確認用に保留してトランスクリプトを更新します。再接続時および復元された送信トレイの再送では、現在の履歴との整合後、この事前条件を意図的に省略します。 chat.sendは冪等性キーを受け取ります(Control UI は実行 ID を使用します)。Gateway は同じキーを再利用する反復リクエストを重複排除するため、同じセッション、メッセージ、添付ファイルに対する再試行または処理中の重複送信によって 2 回目の実行が作成されることはありません。- 特定のメッセージへの返信(右クリック → Reply)では、対象のトランスクリプト ID が
chat.sendのreplyToIdとして送信されます。Gateway はセッション履歴からそのメッセージを解決し、Discord の返信で使用されるものと同じ、チャネルに依存しない返信コンテキストメタデータを設定します。エージェントにはhas_reply_contextに加え、送信者ラベルと本文を含む信頼されていない「現在のユーザーメッセージの返信先」ブロックが渡されます。(既存の直接 WebChat セッション向けバイト安定プロンプトポリシーに従い、WebChat プロンプトではreply_to_idのような揮発性の会話 ID は引き続き抑制されます。)永続化されたトランスクリプト ID がない返信先(送信待ちなど)は、メッセージ本文内のインライン引用にフォールバックします。 - ワークスペース起動ファイルと保留中の
BOOTSTRAP.md指示は、WebChat のユーザーメッセージにコピーされるのではなく、エージェントシステムプロンプトの# Project Contextセクションを通じて提供されます。ブートストラップ内容が切り詰められた場合、代わりに短い「ブートストラップコンテキスト通知」がシステムプロンプトに追加されます。詳細な件数と構成オプションは診断画面にのみ表示されます。 chat.historyの表示正規化では、ランタイム専用の OpenClaw コンテキスト、受信エンベロープラッパー、[[reply_to_current]]、[[reply_to:<id>]]、[[audio_as_voice]]などのインライン配信ディレクティブタグ、プレーンテキストのツール呼び出し XML ペイロード(切り詰められたブロックを含む<tool_call>、<function_call>、<tool_calls>、<function_calls>)、および漏出した ASCII/全角のモデル制御トークンが除去されます。表示されるテキスト全体がサイレントトークンNO_REPLYのみであるアシスタントエントリは、大文字と小文字を区別せずに省略されます。- 推論フラグ付き返信ペイロード(
isReasoning: true)は、WebChat のアシスタントコンテンツ、トランスクリプト再生テキスト、および音声コンテンツブロックから除外されるため、思考のみのペイロードが表示可能なアシスタントメッセージや再生可能な音声として現れることはありません。 chat.injectはアシスタント注記をトランスクリプトへ直接追記し、UI にブロードキャストします(エージェント実行は行いません)。- 中止された実行では、アシスタントの部分的な出力が UI に表示されたままになる場合があります。バッファー済みの出力が存在する場合、Gateway はその部分的なテキストをトランスクリプト履歴へ永続化し、エントリに中止メタデータを付けます。
トランスクリプトと配信モデル
WebChat には 2 つの独立したデータ経路があります。
- SQLite のトランスクリプト行は、永続的なモデル/ランタイムトランスクリプトです。通常のエージェント実行では、組み込みの OpenClaw ランタイムがセッションアクセサーを通じて、モデルから参照可能な
user、assistant、およびtoolResultメッセージを永続化します。WebChat は任意の配信、状態、または補助テキストをそのトランスクリプトへ書き込みません。 - Gateway の
ReplyPayloadイベントは、ライブ配信の投影です。WebChat/チャネル表示、ブロックストリーミング、ディレクティブタグ、メディア埋め込み、TTS/音声フラグ、および UI のフォールバック動作向けに正規化されます。それ自体が正規のセッションログではありません。 tools.messageを通じて表示可能な返信を必要とするハーネスでは、現在の実行における内部の送信元返信先として引き続き WebChat を使用します。そのアクティブな WebChat 実行からの送信先なしのmessage.sendは、同じチャットに投影されてセッショントランスクリプトへ複製されます。WebChat が再利用可能な送信チャネルになることはなく、lastChannelを継承することもありません。- WebChat がアシスタントのトランスクリプトエントリを挿入するのは、Gateway が通常の組み込みエージェントターン外の表示メッセージを所有する場合に限られます。対象は
chat.inject、エージェントを使用しないコマンド返信、中止された部分出力、および WebChat が管理するメディア用トランスクリプト補足です。 - 実行中にライブのアシスタントテキストが表示されるものの、履歴の再読み込み後に消える場合は、次の順に確認します。SQLite トランスクリプトにアシスタントテキストが含まれているか、
chat.historyの表示投影によって除去されたか、Control UI の楽観的末尾マージによってローカル配信状態が永続化済みスナップショットに置き換えられたかを確認します。
通常のエージェント実行による最終回答は、組み込みランタイムがアシスタントの message_end を書き込むため、永続化される必要があります。配信済みの最終ペイロードをトランスクリプトへ複製するフォールバックでは、組み込みランタイムがすでに書き込んだアシスタントターンを重複させないよう、先に確認する必要があります。
Control UI のエージェントツールパネル
- Control UI の
/agentsTools パネルには、tools.effective(sessionKey=...)に基づく「現在利用可能」ビューがあります。これは、コア、Plugin、チャネル所有、および検出済みの MCP サーバーツールを含む、現在のセッションのツール一覧について、サーバーが生成する読み取り専用の投影です。 - 別の構成編集ビュー(
tools.catalogに基づく)では、プロファイル、エージェントごとの上書き、およびカタログのセマンティクスを扱います。 - ランタイムの可用性はセッション単位です。同じエージェント上でもセッションを切り替えると、「現在利用可能」リストが変わる場合があります。構成済みの MCP サーバーが未接続である場合、または最後の検出以降に変更されている場合、パネルは読み取り経路から暗黙に MCP トランスポートを起動するのではなく、通知を表示します。
- 構成エディターはランタイムの可用性を保証するものではありません。実効アクセスには、引き続きポリシーの優先順位(
allow/deny、エージェントごと、およびプロバイダー/チャネルの上書き)が適用されます。
リモート利用
- リモートモードでは、Gateway WebSocket を SSH/Tailscale 経由でトンネリングします。
- 別個の WebChat サーバーを実行する必要はありません。
構成リファレンス(WebChat)
完全な構成については、構成を参照してください。
WebChat には永続化される構成セクションがありません。Gateway は組み込みの chat.history 表示上限を使用します。API クライアントはリクエストごとに maxChars を送信し、1 回の呼び出しに限って上限を上書きできます。従来の channels.webchat および gateway.webchat 構成は廃止されています。削除するには openclaw doctor --fix を実行してください。
関連するグローバルオプション:
gateway.port、gateway.bind: WebSocket のホスト/ポート。gateway.auth.mode、gateway.auth.token、gateway.auth.password: 共有シークレットによる WebSocket 認証。gateway.auth.allowTailscale: 有効にすると、ブラウザーの Control UI チャットタブで Tailscale Serve ID ヘッダーを使用できます。gateway.auth.mode: "trusted-proxy": ID を認識する 非 loopback プロキシ送信元の背後にあるブラウザークライアント向けのリバースプロキシ認証(信頼済みプロキシ認証を参照)。gateway.remote.url、gateway.remote.token、gateway.remote.password: リモート Gateway の接続先。session.*: セッションストレージおよびメインキーのデフォルト。
関連項目
Was this useful?