Work: 分離ワークスペース
Work は Libre WebUI に組み込まれたコーディングエージェント画面です。各 Work タスクは、永続的な会話、明示的なモデルプロバイダー経路、/workspace にある専用ファイルシステムをまとめて扱います。選択されたモデルはファイルの確認と編集、タスク単位の Docker コンテナまたは Kubernetes Pod でのコマンド実行、ブラウザプレビューの起動を行えます。
Work は Libre WebUI に直接実装されています。Libre Claw や別のエージェントデーモンは必要ありません。
すべての Work API では、Work アクセス権を持つ認証済みアカウントが必要です。デフォルトでは管理者だけが該当します。管理者は、設定のユーザー管理タブからすべての有効なユーザーへ Work を開放できます(ホストフォルダーのワークスペースはサーバーパスをバインドマウントするため、常に管理者専用です)。Work では、モデルがサンドボックス内で任意のシェルコマンドを実行できます。選択した名前付きランタイムポリシーで無効にしない限り、タスクは外部ネットワークへアクセスできます。Work アクセスを付与する全員を、単なるチャットユーザーではなく、信頼できるランタイム運用者として扱ってください。
リリースの主な変更
このリリースでは、完全なタスクワークフローとして Work が導入されます。
- メインサイドバーにWorkとChatを別々の操作として表示し、現在のモードを明確に選択表示。
- 別のタスクレールではなく、通常のサイドバーへ Work タスクを表示。実行の更新中も既存タスクの位置は安定し、選択中のタスクを直接削除可能。
- タスクごとに専用のサンドボックス ID と、永続 Docker ボリュームまたは Kubernetes PVC を割り当て。タスクファイルを削除せずにサンドボックスを停止または再作成可能。
- Libre WebUI のデータベースに、会話、実行状態、ツールアクティビティ、モデル選択、タスク所有者を永続化。
- アシスタントのテキスト、プロバイダーが公開する推論、ツール呼び出しと結果、使用量、ワーカースキル、状態変化を対象とする、リアルタイムで認証済みの実行ストリーム。
- プロジェクトへ制御ファイルを書き込まず、選択されたモデルへ効率的な確認、編集、検証、プレビュー方法を教える、サーバー管理のワーカースキル。
- ツール対応のローカル Ollama モデル、Ollama Cloud モデル、設定済みの補完/チャット用プロバイダープラグイン。
- デスクトップではドラッグとキーボードでサイズを変えられる、応答性の高い会話/ワークスペース分割。小さい画面では、表示面を 1 つに絞る切り替えを提供。
- ファイル、アクティビティ、Git、ターミナル、プレビュー、画面ビューを統合。「画面」ビューが、見守りながら指導できる Work Computer デスクトップ。
- ダーク/ライトモードの構文強調、ブラウザ側のコード整形、保存競合の検出、一時的な未保存下書き。
- リモートモデルプロバイダー選択時に、ユーザーごとに閉じられる情報開示。
- 対応する 25 言語すべてで完全な Work 翻訳を提供。アラビア語では右から左のネイティブレイアウトを採用しつつ、コード、パス、モデル ID、コマンド出力は左から右のまま表示。
永続的な単位は、常時実行中のコンテナではなくタスクワークスペースです。Libre WebUI は必要に応じてタスクのコンテナを起動、停止、再作成できますが、名前付きボリュームは保持します。
アーキテクチャ
モデルやブラウザではなく Libre WebUI が、サンドボックス名とワークスペース名、イメージ、マウント、ユーザー、上限、ネットワークモード、プレビューポートを決定します。モデルに与えられるツールは次のものだけです。
list_filesread_filewrite_filedelete_filemove_filesearch_filesrun_commandstart_previewstop_preview
delete_file と move_file には、他のファイルツールと同様にパス保護があります。ワークスペース外への移動を拒否し、シンボリックリンクを決してたどらず、ディレクトリ削除には明示的な再帰フラグを要求し、移動先を上書きしません。シェルではなくファイルヘルパー経路で実行されるため、プレビュー実行中に run_command がブロックされていても利用できます。
モデルへのリクエストは Libre WebUI バックエンドから送信されます。Work コンテナから発信されるものではなく、コンテナのネットワークポリシーにも依存しません。
要件
Work には、設定済みのサンドボックスバックエンドが必要です。
- デフォルトバックエンドでは Docker をインストールし、到達可能なデーモンと、バックエンドプロセスが
docker(またはWORK_DOCKER_COMMANDで設定した実行ファイル)を呼び出す権限が必要です。 - Kubernetes バックエンドでは、API 資格情報に加え、
work.enabled=trueのとき Helm チャートが作成する名前空間単位の Role、RoleBinding、サンドボックス名前空間、NetworkPolicies が必要です。
すべてのバックエンドで、次の要件も満たす必要があります。
- 次のいずれかで公開される、ツール対応モデル:
- 正常な Ollama サービス。Ollama Cloud 経由のモデルを含む。
- 有効な補完/チャットプラグイン。正確なモデルと、現在の管理者用資格情報が設定済みであること。
- イメージ、生成プロジェクト、プロジェクトローカルの依存関係に十分なランタイムストレージ。
- Work アクセス権を持つ認証済みアカウント。Work はデフォルトで管理者専用ですが、管理者はすべての有効なユーザーへ開放できます。
Libre WebUI は実行作成前に、Ollama が公開するモデル機能を確認し、tools を公開していない Ollama モデルを拒否します。プラグイン経由のモデルは、そのプロバイダーのツール呼び出しプロトコルに対応している必要があります。選択したリモートモデルがツールを拒否した場合、実行は失敗します。Work が別のモデルやプロバイダーへ黙って切り替えることはありません。
ローカルで開始する
最も簡単な対応 Work 構成では、Libre WebUI と Docker を、ブラウザと同じコンピューターで実行します。
docker info
npx libre-webui@latest
http://localhost:8080 を開いて管理者としてサインインし、サイドバーでWorkを選び、互換モデルを選択して、作成したいプロジェクトまたは変更内容を説明します。
Docker がない、停止している、アクセスできない場合、Work はバックエンドの理由とともにランタイムを利用できませんと表示し、「実行」入力欄を無効にします。Libre WebUI がホスト上で Work コマンドを直接実行するようフォールバックすることはありません。
ランタイムイメージは初回使用時に検査され、存在しない場合は自動的に取得されます。そのため、最初の操作は以降より時間がかかることがあります。
Work 画面を使う
タスクを作成して再開する
サイドバーで Chat の隣にある Work を選択します。指示を入力し、モデルを選んで実行を選択します。最初のメッセージによって、タスク、最初の実行、プロバイダー経路、永続ワークスペースが作成されます。
各タスクはメインサイドバーに残ります。再度開くと、最近の会話、ファイルビュー、現在のプロバイダー/モデル選択、ワークスペースが復元されます。古い会話メッセージはページ単位で読み込めます。タイトルからタスク名を変更でき、選択中タスクのメニューまたはサイドバーから完全に削除できます。
1 つのタスクで同時に有効にできる実行は 1 つだけです。後から指示を送ると、同じ会話とファイルシステムを対象に別の実行が作成されます。
入力欄では音声入力を利用できます。マイクボタンは、利用可能ならブラウザの音声 API を使用し、それ以外では設定済みの音声認識プロバイダーモデルをフォールバックとして使います。文字起こしは、すでに入力されている内容の後へ追加されます。会話では、実行によって作成または移動されたファイルが、その処理を行ったツールアクティビティの下にクリック可能なチップとして表示されます。クリックすると、ワークスペースのファイルエディターで開きます(狭い画面ではワークスペース表示へ切り替わります)。チップは変更を行うツールだけから生成されるため、20 個のファイルを読み取って 1 個だけ書き込んだ実行では、その 1 個だけが表示されます。
エージェントを雇う
ペルソナがある場合、ランディング画面にエージェントとして雇うが表示されます。ペルソナを選ぶと、作成されるタスクは 1 回限りのタスクではなく、永続的な名前付きエージェントになります。エージェントは実行をまたいでペルソナを保持します。ペルソナの名前とシステムプロンプトが Work のシステムプロンプトの前に追加されますが、サンドボックスのランタイムコントラクトが常に優先されます。サイドバーでは、エージェントが臨時タスクより上の専用エージェントグループに固定され、ペルソナのアバター、アクティビティ表示、1 行の状態が付きます。サイドバーをコンパクト表示にすると、レールに残るのは固定されたエージェントのアバターだけになり、1 回限りの Work タスクはサイドバーを展開すると再び表示されます。
状態表示には 2 段階があります。雇用済みエージェントでは、実行終了時にツールを使わない低コストのモデルリクエストを 1 回行い、約 8 語の状態(「Inbox at zero. 2 replies ready.」など)を求めます。返答は 90 文字の 1 行に制限され、失敗またはタイムアウトすると決定論的な段階、すなわち最後のアシスタントメッセージの先頭行へフォールバックします。臨時タスクと失敗した実行では、決定論的な段階だけを使います。WORK_STATUS_BLURB_MODEL=0 でモデルリクエストを完全に無効化できます。エージェントには未読表示もあります。タスクを開くとタスク単位の閲覧済みマーカーが前進し(単調増加し、デバイス間で同期)、そのマーカー以降に実行が最終状態へ達すると、サイドバーに点が表示されます。
エージェントの進行状況は、通知でも報告されます。アプリ内通知に加え、有効なら Web Push も使用します。実行完了時は work-run-finished、入力待ちで停止または失敗したときは work-run-attention、エージェントが画面の引き継ぎを人へ求めた瞬間は work-takeover です。画面上のバナーは「画面」タブを開いている間しか見えないため、別の場所にいるユーザーへはプッシュ通知が届きます。各通知は該当エージェントへ直接リンクします。
自分が所有するペルソナでも、共有されたペルソナでも雇用できます。共有ビューが所有者のペルソナメモリを公開することはありません。後でペルソナが削除されても、エージェントはペルソナなしで動き続け、警告がログに記録されます。API はタスク作成時に personaId と isAgent を受け付けます。ペルソナ付きで作成したタスクは自動的にエージェントになります。
エージェントタブ
エージェントのワークスペースペインには、最初の追加タブとしてエージェント、すなわちエージェント自身のページが表示されます。
- ID: ペルソナのアバター、名前、アクティビティ表示、最新の状態行。
- 画面: タスクのポリシーが Work Computer を許可している場合、エージェント画面の小さなリアルタイム閲覧専用サムネイルを表示します。これは実際のビューアーであり、タスクごとのビューアー上限に計上されます。クリックすると完全な「画面」タブが開き、引き継ぎ、指導、音声を利用できます。
- ルーティン: このタスクに関連付けられたオートメーション。各発火は新しいタスクではなく、エージェント自身のモデルとランタイムを使い、エージェント固有のワークスペースと会話内で実行されます。そのため、朝のブリーフィング用ルーティンなどが 1 か所へ蓄積されます。各行にスケジュールが言葉で表示され、一時停止/再開スイッチがあります。インラインの + ルーティンフォームは、あらかじめエージェントへ関連付けられています。エージェントが処理中に発火した回はキューに入らず、
work-task-busyとして明確に失敗します。 - 自動レビュー: エージェント単位の承認スイッチと、そのエージェントが集めた「常に許可」ルール(ルールを削除すれば、その範囲を再び閉じられます)。タスクのポリシーがレビューを強制している場合、スイッチはオンのまま固定されます。
- 教えたスキル: 指導モードで実演した手順。スキルごとに有効/無効を切り替えられます。
接続済みツール(MCP と OpenAPI サーバー)
Work エージェントは、チャット用に設定されたものと同じツールサーバー(MCP または OpenAPI で、管理者が Settings → Tools から登録します)を呼び出せます。ツールは名前空間付きの名称(server__tool)でエージェントに提示され、呼び出しは Libre WebUI のバックエンドから、堅牢化されたツールゲートウェイ(SSRF を防いだ外向き通信、利用者ごとの認証情報、サイズと時間の上限)を通じて実行されます。サンドボックス内部から実行されることはありません。
自律実行が実際に使えるものだけを、正直に提示します。
- オフラインのタスクには何も提示されません。バックエンドが外部へ出られるかどうかにかかわらず、ネットワークアクセスのないタスクはオフラインのままです。
web_searchと同じ理由です。 - 利用者が保存していない個人の認証情報を必要とするサーバーは、提示の時点で除外されます。自律実行は、認証情報を尋ねるために一時停止できないからです。Settings → Tools で認証情報を追加すれば、次の実行からそのサーバーが提示されます。
- ツールのアクセスモード(管理者のみ、または全ユーザー)とサーバーごとの可視性は、チャットとまったく同じように適用されます。さらに、ペルソナのツールサーバー割り当てによって、雇用したエージェントに見えるサーバーが絞り込まれます。
- 承認が有効な場合、サーバーが副作用ありと分類した接続済みツールは、他のゲート対象アクションと同様にあなたの判断を待って一時停止します。読み取り専用ツールは確認なしで実行されます。
エージェント間の委任(@ メンション)
雇用したエージェントは、互いに作業を引き渡せます。Work のコンポーザーで @ を入力すると、自分の他のエージェントをメンションできます。現在のエージェントは指示の中で仲間の一覧(名前と状態行)を把握し、該当する依頼を message_agent ツールで委任します。委任はメッセージによる連携であり、コンピューターの共有ではありません。これは意図的な設計です。各エージェントは独自の隔離されたワークスペースとサンドボックスを保ち、委任先は委任元の会話を見られないため、依頼そのものが必要な文脈を含んでいる必要があります。
委任は非同期です。ツールはすぐに戻り、委任先のエージェントは自分のタスクとして実行します(その会話には、送信元から委任された依頼として表示されます)。完了、入力待ち、失敗、キャンセルのいずれで終わっても、その最終応答は委任元の会話へ、そのエージェントからのレポートとして届きます。委任元がまだ実行中なら、レポートは次のラウンドでモデルに渡ります。アイドルなら、レポートは会話の中でそのまま待機します。レポートが実行を自動的に開始することはないため、2 つのエージェントが延々と応酬することはありません。委任された実行はさらに委任できません。委任先が処理中の場合はキューに入れず、その試行が明確に失敗します。また承認が有効なときは、message_agent も他の副作用を伴うアクションと同じようにレビューを待って一時停止します(「常に許可」ルールは、その 1 つの委任先エージェントだけに限定されます)。
アクションの承認(自動レビュー)
副作用を伴うアクションは、実行前に一時停止してあなたの判断を待てます。タスクで承認が有効なとき(Work ポリシーで副作用を伴うアクションに承認を必須にするが設定されているか、エージェントの自動レビュースイッチがオンのとき)、実行は run_command、computer_act、delete_file、move_file、message_agent を実行する前に停止し、会話に判断カードを表示します。選べるのは、1 回のみ許可、常に許可、拒否です。
- 1 回のみ許可は、この呼び出しだけを実行し、次回はまた確認します。
- 常に許可は呼び出しを実行し、タスクにルールを保存します。ファイル操作とコンピューター操作はツール単位、
run_commandはコマンドのプログラム名(先頭のトークン)単位です。npm run buildを承認すると、シェル全体ではなく以後のnpmコマンドが事前承認されます。message_agentは、その 1 つの委任先エージェントに限定されます。ルールはエージェントタブの「自動レビュー」セクションに一覧表示され、そこから削除できます。 - 拒否は呼び出しを拒みます。モデルには、利用者がそのアクションを拒否したこと、そのまま再試行してはならないことが伝えられ、実行はその回答を受けて続きます。
保留中の承認は通知(アプリ内、有効にしていれば Web プッシュ)も発行します。ゲートに達した時点で、実行はすでに数分間の無人作業に入っている可能性があるからです。5 分以内に誰も判断しなければ、リクエストは期限切れとなり、アクションは実行されず、実行は予算を使い切るのではなく、通常の引き継ぎとともに入力が必要として終了します。
承認がゲートするのはアクションであって、可視性ではありません。write_file と読み取り専用ツールはゲートされず、すべての判断はセキュリティ監査ログに残ります。
タスクの状態を理解する
画面では、永続的なバックエンド状態を、より小さなユーザー向けの集合へ対応付けます。
| 画面の状態 | バックエンド状態 | 表示色 |
|---|---|---|
| 待機中 | idle | rgb(255, 255, 255) |
| 考え中 | preparing または running | rgb(48, 121, 255) |
| 完了 | completed | rgb(76, 212, 117) |
| 入力が必要 | needs_input または cancelled | rgb(255, 204, 0) |
| エラー | failed | rgb(255, 61, 129) |
有効な実行を停止すると入力が必要へ変わり、ファイルは保持されます。ラウンド数またはツール呼び出し数の安全予算を使い切った場合も、ツールなしの最終引き継ぎ後に入力が必要で終了します。未完了の作業が完了と表示されることはありません。
有効な実行中も、会話はロックされません。エージェントの作業中に送ったメッセージはすぐ会話へ加わり、次のラウンドでモデルへ届きます。実行を停止せずに方向修正、訂正、コンテキストの追加ができます。停止ボタンは送信ボタンの横で引き続き利用できます。
ワークスペースのサイズを変える
xl デスクトップブレークポイントでは、会話とワークスペースがドラッグ可能な分割表示を共有します。
- 会話のデフォルト幅は 45%。
- 推奨範囲は 30%~70%。ただし各コンテンツの最小幅が優先。
- 保存した比率は、そのブラウザでサインインしているユーザー単位。
- 矢印キーで区切りを 2% ずつ移動。Shift を押しながらなら 10%。
- Home と End で利用可能な最小値と最大値を選択。
- Enter またはダブルクリックで分割をリセット。
操作は現在の書字方向に従います。アラビア語では会話が右、ワークスペースが左にあり、ポインターと矢印キーによるサイズ変更も、見た目どおりの方向で動作します。
小さい画面では、タスクヘッダーにある会話/ワークスペースの操作で表示面を切り替えます。
ファイル
「ファイル」タブでは /workspace の直下項目を閲覧し、厳密に有効な UTF-8 テキストファイルを開いて、変更をタスクボリュームへ保存します。無効なバイト列は、情報を失う代替文字へ置換せず拒否されます。
エディターには次の機能があります。
- 一般的なウェブ、システム、スクリプト、データ、マークアップ言語を対象とする、ライト/ダーク両モードの構文強調。
Cmd/Ctrl+Sで保存。Shift+Alt+Fで対応ファイルを整形。- 楽観的な保存競合検出。古いエディター表示から、その後に変更されたファイルを黙って上書きすることを防止。
- タスクとパスを単位とする未保存下書きを、ブラウザのセッションストレージへ保存。
- 未保存の編集が開いている間の画面移動警告。
編集の応答性を保つため、8,000 文字または 400 行を超えるとリアルタイムの構文強調を停止します。JavaScript/JSX、TypeScript/TSX、JSON の各形式、CSS/SCSS/Less、HTML、Markdown/MDX、YAML では、100,000 文字かつ 4,000 行まで整形できます。
開いているファイルをモデルが変更すると、「ファイル」タブは赤/緑の変更ビューを開き、ターン開始以降に追加または削除された内容を正確に表示します。変更のない長い区間は折りたたまれます。ツールバーのスイッチで差分とエディターを切り替えられ、+added −removed カウンターでターン全体の変更量をひと目で確認できます。比較基準は、そのターンの前にブラウザが最後に確認した内容です。ターン後に初めて開いたファイルには差分が表示されません。
ブラウザの下書きは便宜上の状態であり、バックアップではありません。保存に成功した後またはタスク削除後に消去され、通常はブラウザセッションの終了時にも消えます。
アクティビティ
「アクティビティ」タブには、ツール呼び出し、ツール結果、ファイル操作、コマンド出力、エラーが表示されます。ツールのメタデータは会話内で展開できます。周囲の画面が右から左でも、コマンドとツールの出力は左から右に表示されます。
実行中、Libre WebUI は認証済みの Server-Sent Events ストリームを開き、バックエンドで受信した進行状況を表示します。ストリームには次のイベントが含まれます。
- 最初の
snapshotと、その後のrun_state変更。 - 選択されたプロバイダーが推論を明示的に公開する場合の
reasoning_delta。 assistant_deltaテキスト。tool_callとtool_resultのアクティビティ。usageの計測値。- サーバー提供のワーカーガイダンスに関する
skill_loaded通知。 - 最終的な
errorまたはdoneイベント。
推論の利用可否と粒度は、モデルとプロバイダーによって異なります。Libre WebUI が表示するのは、プロバイダーが API 経由で返した推論内容だけです。非公開の思考過程を復元することはできず、推論ストリームを一切提供しないモデルもあります。推論とは独立して対応している場合、アシスタントテキストとツールアクティビティは引き続きストリーミングされます。
出力には意図的に上限があります。結果が途中で切れていても、コマンドがそれ以上の出力を生成しなかった証拠にはなりません。より狭い結果を調べるか、対象を絞ったコマンドを実行するようモデルへ依頼してください。
Git
「Git」タブは、タスク自身の /workspace を対象に、ローカルのソース管理操作を提供します。
mainブランチを持つリポジトリを初期化。- porcelain status、ahead/behind 数、直近 20 件までのコミットを確認。
- 変更済みパスについて、上限付きのテキスト差分を確認。
- 一度に最大 200 個の、明示的に選択したパスをステージ。
- サインイン中の管理者のユーザー名とメールアドレスで、ステージ済み変更をコミット。アカウントにメールがない場合は、インスタンスローカルの no-reply アドレスを使用。
- 最初のコミット後にローカルブランチを作成。
- ワークツリーがクリーンな場合、既存のローカルブランチへ切り替え。
この画面は意図的にローカル専用です。clone、fetch、pull、push、リモート管理、任意の Git コマンド、トークン、SSH 鍵、プルリクエストの操作はありません。それらの操作には、信頼できる別の資格情報ブローカーが必要です。理想的には、1 つのリポジトリと 1 つの操作に限定された GitHub App または同等のインストールトークンを使用します。長期間有効な Git 資格情報を /workspace、タスクコンテナの環境、リポジトリ設定に置かないでください。
Git の読み取りは、タスクが待機中でも有効でも実行できます。モデル実行、対話型ターミナル、プレビューがタスクコンテナを所有している間、Git の書き込みは拒否されます。ブランチ切り替えにはクリーンなワークツリーも必要です。これにより、同じファイルを対象に UI とモデルまたは長時間実行プロセスが競合するのを防ぎます。
UI の各 Git コマンドは固定の引数配列であり、タスクコンテナ内で UID/GID 1000:1000 として実行されます。ユーザー入力がシェルで評価されることはありません。この画面用のランタイムは、system/global Git 設定、プロンプト、フック、資格情報ヘルパー、コミット署名、サブモジュール再帰、外部 diff ドライバー、textconv、ネットワークプロトコルを無効にします。ワークツリーが正確に /workspace ではない、または Git/common ディレクトリが /workspace 外へ解決されるリポジトリは拒否します。ファイル内容を処理し得る Git 書き込み操作は、リポジトリ設定に実行可能な clean、smudge、process フィルターが定義されている場合もブロックされます。
これらの制御は Libre WebUI の Git API を保護します。管理者はターミナルを使用でき、モデルも run_command を使ってサンドボックス内で通常の Git コマンドを実行できます。そのため、任意コマンドに対するセキュリティ制御は、引き続きサンドボックスとデプロイ境界です。
組み込みワーカースキル
各実行には、サーバー管理のワークスペースガイドが与えられます。永続的な /workspace 境界、読み取り専用のコンテナルート、一時的なプロセスと /tmp の状態、ネットワークポリシー、コマンドと出力の上限、プレビューのライフサイクルを説明します。組み込みスキルは、モデルに次の手順を指示します。
- 編集前に、プロジェクトの指示、マニフェスト、ロックファイル、スクリプト、現在のリポジトリ状態を確認。
- 無関係な作業を保持し、独立した読み取りや検索をまとめて実行。
- 計画だけで停止せず、実装まで続行。
- 広範なチェックより先に、対象を絞った検証を実行。
- やみくもに再試行せず、失敗を診断。
- 最後の長時間実行プロセスとしてプレビューを開始する前に、アプリケーションを検証。
このガイドはモデルのコンテキスト内だけに存在します。Libre WebUI は、ユーザーのワークスペースへ AGENTS.md、スキルディレクトリ、その他の制御ファイルを作成しません。プロジェクトが提供する指示はプロジェクト内のガイダンスであり、コンテナやツールのセキュリティ境界を上書きできません。
ターミナル
「ターミナル」タブは、モデルが作業する同じサンドボックス化コンテナへ対話型シェルを接続します。管理者はブラウザを離れず、状態の確認、手動ビルド、実行後のデバッグを行えます。
シェルは、すべてのモデルツールと同一のコンテナポリシーで動作します。すでに堅牢化され capability を削除したコンテナ内で、非特権 1000:1000 ユーザーとして、作業ディレクトリ /workspace で実行されます。ターミナルによって、モデルの run_command ツールにない権限が与えられることはありません。同じ境界を人間向けに提供する画面であり、境界を回避する方法ではありません。
運用動作:
- 認証 — ブラウザは通常の Authorization ヘッダーを HTTP で交換し、Work ターミナルプロトコルと正確なタスクに紐付いた、短時間だけ有効な 1 回限りのチケットを取得します。
/ws/work-terminalのアップグレード URL に現れるのは、そのチケットとタスク ID だけです。シェル入力のたびに、Libre は現在のアカウント状態、Work アクセス権、タスクの存在、タスク所有権を再確認します。権限を取り消すと、シェルを閉じてランタイムリースを即座に解放します。 - オリジン確認 —
CORS_ORIGINまたはBASE_URLが設定されている場合、ブラウザのアップグレード元はそのいずれかに一致する必要があります。リモートデプロイでは少なくとも 1 つを設定してください。オリジンなしのアップグレードは Electron とブラウザ以外のクライアント向けに引き続き利用できますが、同じタスク限定チケットとリアルタイムの認可確認が必要です。TLS、ファイアウォール、リバースプロキシのポリシーでこれらのクライアントを制御してください。 - 受付 — 開いたターミナルはコマンドやプレビューと同様にランタイムリースを取得し、
WORK_MAX_ACTIVE_RUNTIMES_*に計上されます。 - コンテナの存続期間 — ターミナルが接続されている間はコンテナが実行中に保たれ、アイドル停止処理によるセッション途中の削除を防ぎます。
- 同時実行 —
WORK_TERMINAL_MAX_SESSIONS_PER_TASK(デフォルト 2)で、タスクごとの同時シェル数を制限します。 - アイドルタイムアウト —
WORK_TERMINAL_IDLE_TIMEOUT_MS(デフォルト 15 分)は、操作のないセッションを閉じてリースを解放します。 - 実行中 — タブにはモデルがコンテナを所有していることが表示され、ターン終了後にシェルを開きます。
ターミナルは Docker Engine API を直接使用します。TTY セッションにはハイジャックされた双方向ストリームが必要であり、Docker CLI は実際の制御端末にしかこれを提供しないためです。WORK_DOCKER_SOCKET、なければ DOCKER_HOST(unix:// ソケット、またはソケットプロキシなどの平文 HTTP tcp:// エンドポイント。HTTP 対応の転送が標準の Connection: Upgrade トンネルでハイジャックストリームを運びます)、どちらもなければ /var/run/docker.sock を使用します。このクライアントが扱えない DOCKER_HOST(ssh://、または DOCKER_TLS_VERIFY を設定した tcp://)では、別の場所へ黙って接続せず、理由とともにターミナルを利用不可として報告します。Work の他の機能は引き続き動作します。Kubernetes バックエンドでは、同じセッションが API サーバーを通じて TTY WebSocket として exec サブリソースを利用し、サイズ変更フレームも含めて転送されます。Docker エンドポイントは関与しません。
ターミナルセッションは対話的で、記録されません。入力したコマンドはタスクの「アクティビティ」タイムラインに現れません。
プレビュー
「プレビュー」タブでは、生成されたウェブアプリケーションの起動、停止、埋め込み、別画面表示を行えます。コマンド欄が空の場合、Libre WebUI はワークスペースを調べ、次のいずれかを行います。
- ルートの
package.jsonにあるdevスクリプトを、必要なホストとポートで実行。 - ルートの
index.htmlを、同梱の依存関係ゼロの静的サーバーで配信。 - ネストされたディレクトリに 1 つだけアプリがある場合、同じ規則を使用。
ルートのアプリケーションが優先されます。同じ程度に可能性の高いネスト済みアプリが複数見つかるか、対応するエントリーポイントがない場合、無関係な npm コマンドを試さず、対処可能なエラーを返します。他のプロジェクト構成やサーバーでは、プレビューを開始する前にカスタムコマンドを入力します。カスタムコマンドは /workspace から開始するため、必要に応じて相対ディレクトリを含めます。例: cd apps/web && npm run dev -- --host 0.0.0.0 --port 4173。カスタムプロセスは 0.0.0.0 と設定済みの WORK_PREVIEW_PORT で待ち受ける必要があります。Work はポートが準備完了になるまで最大 15 秒待ちます。
モデルも start_preview ツールでプレビューを開始できます。モデルがプロセスを実行中のまま残せる唯一の対応方法です。通常の run_command 呼び出しでは、コマンド終了時にバックグラウンドの子孫プロセスを消去します。
画面(Work Computer)
デモ全編を見る: Work エージェントが自身の画面で NASA の画像ギャラリーを閲覧し、写真を選んでインタラクティブな Three.js ギャラリーを構築・テストする、編集なしの実際の実行(30 倍速、その後は実時間)。すべて 1 つのプロンプトから行われます。
ポリシーで Work Computer を有効にしたタスクには、「画面」タブが追加されます。同じサンドボックス内で動く仮想デスクトップをリアルタイムに表示し、1280×800 のディスプレイ上でウィンドウマネージャー、ドック、Chromium ブラウザが動作します。エージェントの作業を見守り、マウスとキーボードを引き継ぎ、コンピューターの音声を聞き、実演によってタスクを教えられます。タブを開くと必要に応じて GUI セッションが始まり(誰かが見るまで何も実行されません)、VNC-over-WebSocket ビューアーが接続されます。
管理者は 1 クリックで有効化できます。Work のランディングページにある Work Computer カードで有効化を押すと、デプロイ自身の Docker デーモン上で同梱 GUI イメージをビルドし(最初のビルドには数分かかります)、利用可能な Work Computer ポリシーを作成します。docker build を手動で実行したり、ポリシーフィールドを設定したりする必要はありません。フィルタリング済み Docker API プロキシでは build エンドポイントが意図的に拒否されます。代わりに Docker ホストで公開イメージ(ghcr.io/libre-webui/libre-work-computer、タグ libre-work-computer:latest)を取得するか、deploy/work-computer/ からビルドしてください。その後有効化を押すと、ビルドを省略してポリシーだけを作成します。このポリシーを使うタスクではネットワークアクセスが必要です。画面はプレビューとまったく同じく、コンテナのループバック公開ポート経由で到達するためです。
セキュリティモデル: コンテナ内の VNC サーバーは、セッションごとの 2 つのパスワードの背後で localhost にバインドされます。閲覧専用パスワードは認可されたすべての閲覧者へ渡され、完全操作用パスワードは現在の引き継ぎリース保有者だけへ公開されます。そのため、VNC サーバー自身が他の全員からの入力を無効に保ちます。WebSocket ブリッジだけが到達可能な面で、Docker ホストのループバック上に公開され、直接外部へ公開されることはありません。各ビューアーは、ターミナルと同じ仕組みで、セッションとタスクに紐付いた 1 回限りのチケットにより認証されます。接続ごとに現在の Work アクセス権を再確認するため、アクセス権を取り消すと画面も即座に切断されます。1 画面を最大 4 人が同時に見られ、閲覧はアイドルスイープ上のタスクアクティビティとして計上されます。閲覧と実行は競合しません。エージェントの実行中に画面を開くと、その実行自身のサンドボックスへ接続します。画面を見ていても次の実行開始を妨げず、実行終了後もセッションは維持されます。実行が別のワーカープロセスで行われるチーム向けデプロイでも同様です。ブラウザプロファイルは /workspace/.browser-profile に永続化されるため、コンピューター内でのサインインはコンテナ再起動後も保持されます。
エージェント操作: Work Computer を持つタスクでは、モデルに 2 つの追加ツールも提供されます。computer_observe は、デスクトップ全体のスクリーンショットとともに、カーソル位置、アクティブウィンドウ ID、ブラウザの現在の URL、ページ(ブラウザ自身の UI ではなく)がキーボードフォーカスを持つか、フォーカス中要素の簡潔な記述、スクリーンショットハッシュを返します。セマンティックなシグナルは、コンテナのループバックにバインドした DevTools エンドポイントから取得され、それが存在する前に作られた GUI イメージでは値なしへ縮退します。computer_act は、最大 24 件のマウス/キーボード操作(移動、クリック、ダブルクリック、右クリック、入力、キーの組み合わせ、スクロール、待機)を 1 バッチで実行し、安定後のスクリーンショットを返します。3 つのランタイム保護により、バッチの正確性を保ちます。type/key 操作には focus アサーションを付けられ、指定したフィールドがキーボードフォーカスを持たなければ安全側に失敗します。そのため、テキストがアドレスバーへ黙って入ることはありません。バッチ中にウィンドウが現れる、タイトルが変わる、フォーカスが移ると、残りの座標は以前の画面を対象としているため早期停止します。バッチには想定結果(タイトル、URL、画面領域の変化)を宣言でき、ランタイムが適応的な期限で検証します。「pending」はまだ観測されていないという意味で、成功とはみなしません。バッチ後は固定時間待つのではなく、画面の変化が止まるまで適応的にポーリングして安定を待ちます。
各結果には、モデルが読むよう指示される証拠も含まれます。明示座標のクリックは周囲のピクセルが変わったかを示すレシートを返し、scroll_until は対象テキストまたはページ端へ向かってスクロールし、表示されたかを報告します。各観測は前回との差分が取られ、画面が変わっていなければ明示されます。バッチには 1 行の subgoal を宣言でき、結果とともにチェックポイントとして保持され、復旧プロンプトにも表示されます。エージェントループは、画面上の根拠が得られない停滞を検出します。変化のない画面に同じ操作を 3 回行うと 1 回の復旧通知を出し、さらに繰り返すと残りラウンドを浪費せず、入力を求めて実行を終了します。検証されない期待が連続する複合的な曖昧さも検出し、1 回の再確認通知を出します。ラウンド数、ツールのレイテンシ、スクリーンショット、保護、期待の判定といったループテレメトリーは、永続化される各ツールレコードへ付与され、実行終了時に要約されます。
スクリーンショットは Ollama、Anthropic、Gemini、OpenAI 互換の chat/Responses プラグインという、すべてのプロバイダー経路で本物の画像コンテンツとしてモデルへ届きます。そのため、タスクを操作するモデルにはビジョンモデルを使ってください。プロバイダーが画像入力を拒否するテキスト専用モデルでも、実行自体は失敗しません。残りの実行ではスクリーンショットを破棄し、テキスト観測に頼るようモデルへ通知し、劣化についてトランスクリプトへ注記します。ただし、画面を見られないモデルは検証能力が大幅に下がるため、コンピュータータスクではビジョンモデルを推奨します。モデルの現在のコンテキストに残るのは最新のスクリーンショットだけで、永続的なタスクトランスクリプトにはテキスト観測だけを保存し、画像バイトは保存しません。
ブラウザにはコンテンツブロック機能が組み込まれています。広告とトラッカーには uBlock Origin Lite(イメージビルド時にバージョンを固定してチェックサムを検証し、管理ポリシーでフィルタリングモードも固定)、Cookie 同意バナーには自動非表示機能を使用します。広告や同意画面は、エージェントのスクリーンショット、トークン、クリックを浪費するためです。広告リクエストは uBlock と同じ方法で無害化されます。既知の広告スクリプトを害のないローカルスタブへ解決し、ページの動作を維持します。エージェントには、資格情報を入力したり CAPTCHA/2FA の課題を完了したりせず、代わりに阻害要因を報告するよう指示されます。信頼できないタスクでは、GUI ポリシーとフィルタリング DNS リゾルバーを組み合わせてください。デスクトップブラウザがあると、ネットワーク外向き通信ポリシーの重要性はさらに高まります。
音声: 画面はデフォルトでミュートされます(音声にはクリックが必要というブラウザ規則によるもの)。「画面」ペインのスピーカーボタンを押すと、コンピューターの音声をリアルタイムにストリーミングします。サンドボックス内では、PulseAudio が null sink へ出力し、そのモニターを raw PCM として取得して、2 本目の認証済みループバック公開 WebSocket ブリッジから配信します。画面と同じチケット、アクセス権の再確認、タスクごとのビューアー上限を使用します。このバージョン以降の deploy/work-computer/ から作成した GUI イメージが必要です。
引き継ぎ: 「画面」ペインの引き継ぐボタンを押すと、サインイン、CAPTCHA の解除、エージェントが行ってはならない手順のためにマウスとキーボードを操作できます。完了で画面を返します。1 つの VNC セッションが両方の役割を提供します。コンテナ内サーバーは完全操作用と閲覧専用のパスワードをセッションごとに生成し、決してログに記録しません。閲覧者には閲覧用だけを渡し、操作用パスワードは操作リースの現在の保有者だけへ公開します。リースには TTL 上限があり、放置された引き継ぎは 2 分以内に失効します。引き継ぎ UI を開いている間は更新され、協調型なので別ユーザーから奪えません。ポリシーで引き継ぎを完全に無効化することもできます(ポリシーエディターの画面の引き継ぎを許可)。対象タスクでは「引き継ぐ」と「教える」が非表示になり、引き継ぎエンドポイントは拒否し、エージェントの request_takeover は操作を渡せる相手がいないと報告します。閲覧は引き続き可能です。人が操作中は、エージェントの computer_observe と computer_act が両方ブロックされます。エージェントは入力を妨害できず、入力内容をスクリーンショットにも残せません。エージェント自身も、request_takeover ツールで理由付きバナーを「画面」ペインへ投稿し、ユーザーが引き継いで返すまで待機できます。引き継ぎ中に入力した資格情報は、キーボードからページへ直接届き、モデルやタスクトランスクリプトを決して通りません。引き継ぎには、このバージョン以降の deploy/work-computer/ から作成した GUI イメージが必要です。古いイメージのセッションは引き続き閲覧できますが、全員が閲覧専用です。
指導モード: 「画面」ペインのタスクを教えるでは、実際の画面をユーザーが操作するデモを記録します。引き継ぎとまったく同じ方法で操作権を取り、目に見える録画表示とともに、ポインター、キーボード、スクロールの操作を画面座標で取得します。各クリックにはアンカーも付きます。読み取り専用プローブが、ポインター下の操作可能要素(タグ、ID、表示ラベル)と現在のページ URL を解決します。そのため、プレイブックの手順は「Click "button#submit (Place order)"」のように対象を名前で示し、座標はデモ時にその操作があった位置のヒントへ格下げされます。
保存時は、モデルを一切介さず、決定論的にプレイブックを作成します。連続したキー入力を文字列としてまとめ、クリックとドラッグを 8 ピクセルのしきい値で判定し、停止時間を明示的な待機手順に変換します。シークレット関連語を含む入力、または資格情報らしい形(8 文字以上で 3 種類の文字クラスを混在)のテキストは秘匿化し、その手順では request_takeover を使うよう置き換えます。プレイブックは自然言語の手順です。アンカー付き対象を優先し、座標はヒントとして、computer_observe で再解釈します。使用場面、入力、手順、検証、デモで実際に訪れたホストから導出する許可範囲を含みます。再生では、その範囲を出る前に停止して確認する必要があり、教えた手順が実演以上の権限を引き継ぐことはありません。承認境界と、失敗時に停止して確認する処理も含みます。
プレイブックは通常のスキル(スラッグのプレフィックスは taught-)として保存されるため、スキルページに表示され、バージョン管理、編集、共有を利用できます。コンピューター対応の Work 実行では、所有者が有効にした教示済みスキルをシステムプロンプトへ読み込み、実行のスキル一覧にも報告します。教えたタスクの再生は、要求内容が手順に一致する通常の実行にすぎません。実行完了後、スキルチップの 1 クリック評価で成功/失敗を記録できます。日付付きの 1 行がスキルの実績セクションへ新しい順で上限付きに追加され、1 件ずつ通常のスキルバージョンになります。手順の履歴は手順自体とともに保たれます。記録中に実際のパスワードを入力しないでください。サインイン直前までを実演して保存し、再生時は request_takeover で資格情報を処理します。
プロバイダー、ルーティング、データ開示
対応するプロバイダー経路
| 経路 | 検証と動作 |
|---|---|
| ローカル Ollama | Ollama が正常で、正確なモデルがツール対応を公開している必要があります。 |
| Ollama Cloud | Ollama を通じて明示的にルーティング。クラウド用サフィックス付きモデルではリモートプロバイダーの開示を表示します。 |
| 補完/チャットプラグイン | プラグインが有効で、正確なモデルを掲載し、現在の管理者用資格情報を持つ必要があります。 |
| Anthropic プラグイン | Work の Anthropic messages および tool-use アダプターを使用します。 |
| Gemini プラグイン | Work の Gemini contents および function-calling アダプターを使用します。 |
| その他の互換プラグイン | OpenAI 形式の messages、tools、tool-choice のリクエスト形式を使用します。 |
プロバイダー種別とプラグイン ID は、タスクと各実行の両方に保存されます。モデル名だけで経路が選ばれることはありません。Ollama モデルと同じ名前のプラグインを有効化しても、既存タスクを横取りできません。
プロバイダーが受け取る情報
モデルの各ラウンドで、選択されたプロバイダーは次の情報を受け取る場合があります。
- Work のシステムプロンプト。
- 組み込みワーカースキルと現在のランタイム上限。
- 直近 30 件までのユーザー/アシスタント会話メッセージ。上限は 256 KB。
- Work のツール定義。
- アシスタントのツール呼び出し履歴。
- ツール結果。ディレクトリ一覧、要求されたファイル内容、検索結果、コマンド出力、エラーを含む場合があります。
名前付きボリューム全体がアップロードされることはありません。ただし、ツールを通じて返されたファイル内容やコマンド出力はモデル会話の一部となり、選択されたプロバイダーへ送信されます。機密ソースコードを使う前に、リモートプロバイダーの保持、学習、料金、利用ポリシーを確認してください。
デプロイ全体または個別ユーザー用に設定されたプロバイダー資格情報は、Libre WebUI バックエンドに残ります。バックエンドからのモデルリクエストに使用され、Work コンテナへマウントされることはありません。
アプリケーション層の資格情報暗号化は、タスク全体の暗号化ではありません。Work の会話、ツール結果、コマンド出力、タスクメタデータは通常のデータベース内容です。ワークスペースファイルと依存関係は、タスクの Docker ボリュームまたは Kubernetes PVC にある通常のファイルです。保存時暗号化が脅威モデルで必要な場合は、ホストのアクセス制御とディスク暗号化を使用してください。
リモートプロバイダーの開示
Work では、プラグインモデルと、名前が :cloud または -cloud で終わる Ollama モデルを、開示上のリモートモデルとして扱います。選択すると、プロバイダーへのデータフローと、複数回の課金対象呼び出しが発生し得ることを説明する、閉じられる通知が表示されます。閉じた設定は Libre WebUI ユーザーごとに記憶されます。
すべてのプロバイダー経路は同じ WORK_MAX_AGENT_ROUNDS 予算を使い、デフォルトは 48 ラウンドです。プラグイン専用の 12 ラウンド上限はありません。ツール呼び出しの安全予算は、128 回または設定ラウンドあたり 8 回のうち、大きい方です。ラウンド予算を使い切ると、Libre WebUI はモデルに、完了した作業、確認、阻害要因、残りの手順を説明する、ツールなしの最終引き継ぎを 1 回求めます。その後、生のラウンド上限例外を表示したり、未完了の作業を完了扱いしたりせず、最終実行を入力が必要として記録します。後続の実行は同じ永続ワークスペースで続行されます。それでも、1 回の Work 実行で多数の課金対象プロバイダーリクエストが発生する可能性があります。
ホストフォルダーのワークスペース(オプトイン)
Docker バックエンドでは、タスクの /workspace は通常、そのタスクだけに存在する名前付きボリュームなので、モデルは実際のファイルへ到達できません。Docker デプロイでは、代わりにタスクをホスト上の実フォルダーへ関連付けられるよう設定できます。Kubernetes はホストフォルダーのワークスペースを拒否し、タスク所有の PVC を使用します。
両方の変数を設定してから、バックエンドを再起動します。
WORK_HOST_WORKSPACES_ENABLED=true
WORK_HOST_WORKSPACE_ROOTS=/Users/you/Projects
WORK_HOST_WORKSPACE_ROOTS は : 区切りのルート一覧で、デフォルトはサーバーユーザーのホームディレクトリです。この機能を有効にすると、Work のランディング画面に任意のワークスペースフォルダー欄が追加されます。空のままにすれば、タスク固有の分離ボリュームを使う従来どおりの動作になります。
パスを受け入れる前に、絶対パスであり、存在するディレクトリで、すべてのシンボリックリンクを解決した場所が設定済みルートのいずれかに含まれることを確認します。.ssh、.gnupg、.aws、.config、.kube、.docker、.claude、.libre-webui、node_modules という名前のディレクトリは無条件で拒否されます。解決済みパスはタスクとともに保存され、タスクヘッダーへ表示されるため、タスクの操作対象フォルダーを常に確認できます。
ホストワークスペースでは、モデルが実際のファイルを読み書きします。非 root ユーザー、削除済み capability、リソース上限といったコンテナの他の保護も、そのディレクトリとの間を隔てるものではなくなります。必要でない限り無効のままにし、ルートを可能な限り狭くして、バージョン管理下のディレクトリを優先してください。
永続化とランタイムのライフサイクル
Libre WebUI は、永続状態と実行状態を分離します。
| 状態 | 保存場所 | 存続期間 |
|---|---|---|
| タスク所有者、タイトル、プロバイダー、状態 | Libre WebUI データベース | タスクまたは所有ユーザーが削除されるまで |
| 実行、エラー、メッセージ、ツールアクティビティ | Libre WebUI データベース | タスクが削除されるまで |
| ワークスペースファイル | タスク固有 Docker ボリュームまたは K8s PVC | 実行のキャンセル、プレビュー停止、サンドボックス再起動、アプリ再起動後も保持 |
| ルートファイルシステムと一時ファイル | タスク固有コンテナまたは Pod | 使い捨て。停止または再作成される可能性あり |
| プレビュープロセス | 実行中のタスクサンドボックス | 一時的。正常と検証されている間だけ保持 |
| 未保存のエディター下書き | ブラウザのセッションストレージ | ブラウザセッション中の一時的な便宜状態 |
各タスクにはサーバー生成の UUID が割り当てられます。サンドボックス名とワークスペース名はバックエンドで生成し、ブラウザリクエストからは決して受け付けません。Libre WebUI は管理対象ラベルとタスク所有権ラベルを付けてランタイムリソースを作成します。再利用または削除の前にタスク所有権ラベルを確認し、別のタスクに属するラベルを持つリソースを拒否します。
サンドボックスは必要に応じて準備されます。ファイルヘルパー操作は処理後に待機中のサンドボックスを停止し、コマンドは完了後にサンドボックスを停止します。検証済みプレビューは、ユーザーがアプリを確認できるよう実行を続ける場合があります。同じタスクのサンドボックスを再起動または再作成すると、永続ワークスペースが再びマウントされます。
管理者は、設定のユーザー管理タブから名前付きランタイムポリシーを定義できます。ランタイムイメージ、メモリ/CPU/PID 上限、ワークスペースサイズ(Kubernetes)、アイドルタイムアウト、ネットワークのデフォルト、2 つの機能スイッチをまとめたプリセットです。**Work Computer(GUI + ブラウザ)**は、対象タスクへ仮想デスクトップと「画面」タブを提供します。画面の引き継ぎを許可は、画面を人が引き継げるかを決めます。指導は引き継ぎを通じて記録するため、指導モードの利用可否も決まります。ポリシー付きで作成されたタスクは、その設定で実行されます。空のフィールドはデプロイ全体の値を継承し、ポリシーを削除すると、対象タスクは次回のコンテナ再作成時に全体設定へ戻ります。ポリシーが調整できるのはリソースとこれらの機能スイッチだけです。堅牢化プロファイル(非 root、読み取り専用 rootfs、削除済み capability、ネットワーク分離)はポリシーフィールドではなく、タスクごとに弱められません。
WORK_RUNTIME_IDLE_TIMEOUT_MS はプレビュー猶予時間の上限です。設定すると、一定時間アクティビティがないサンドボックスをスイープで停止します。アクティビティには、コマンド完了、ターミナル接続、署名付きプロキシ経由のプレビューリクエストが含まれます。停止すると受付枠が解放されます。停止は低コストでワークスペースは保持されるため、アイドル停止したプレビューは次の使用時に再起動するだけです。デフォルト(0)では、現在の動作どおり、明示的に停止するまでプレビューが動きます。
バックエンド起動時には、有効な実行を失敗として記録し、プレビュー状態を消去します。エージェントループとプレビュープロキシはプロセスとともに停止し、再開できないためです。その後、選択されたドライバーは、管理対象コンテナまたは Pod をラベル指定の 1 回のクエリで一覧表示します。既知タスクが所有する実行中サンドボックスは、中断されたコマンドが監視なしで動き続けている可能性があるため停止します。すでに停止中のサンドボックスは変更せず、対応するタスク行が存在しない管理対象サンドボックスは削除します。所有権はタスクラベルから判定し、リソース名からは決して判定しません。孤立リソースの削除では、1 つの Libre WebUI インスタンスが 1 つのランタイム名前空間または Docker デーモンを所有する前提です。2 つのインスタンスを同じ Work リソースへ向けないでください。ドライバーがクリーンアップを証明できない場合、Work は安全側に閉じ、10 秒ごとに再試行し、ランタイムアクセスが復旧するまで新しい変更操作をブロックします。
ネットワーク動作
名前付きランタイムポリシーのないタスクは、ネットワーク有効で開始します。管理者はネットワークのデフォルトがオフの名前付きポリシーを定義でき、作成者はタスク作成時にそのポリシーを選択できます。タスクごとの独立したネットワークスイッチはなく、後からポリシーを変更した場合、新しいランタイム設定を適用するにはサンドボックスの再作成が必要です。
Docker バックエンドでは、ネットワーク有効のタスクを専用の管理対象ブリッジネットワーク(デフォルトは libre-webui-work、WORK_NETWORK_NAME)へ接続します。コンテナ間通信は無効です(com.docker.network.bridge.enable_icc=false)。その結果、次の制限があります。
- Work サンドボックスから別の Work サンドボックスへ接続できません。
- Work サンドボックスから、Docker の共有デフォルトブリッジ上にあるデプロイ自身のコンテナへ接続できません。意図的に公開していない、同居するデータベースや Ollama コンテナも含まれます。
設定済みの名前を持つネットワークがすでに存在しても、管理対象ネットワークでなければ、Libre WebUI はネットワーク有効タスクの起動を拒否します。運用担当者のネットワークへ黙って接続することはありません。
Kubernetes では、サンドボックス Pod に同じネットワーク有効ラベルが付きます。Helm チャートはデフォルト拒否の NetworkPolicy、プレビュー専用の受信、ネットワーク有効 Pod だけのインターネット向け送信をインストールし、設定済みの work.networkPolicy.blockedEgressCidrs を除外します。NetworkPolicy はクラスタの CNI が適用する場合だけ有効です。Kubernetes ガイドを参照してください。
外部への送信は引き続き許可されます。パッケージのダウンロード、リモート Git 操作、外部 API が Work の有用性を支えるためです。これは外向きファイアウォールではありません。生成されたコードは、デプロイによっては次の場所へ到達できる場合があります。
- Docker ホスト上のサービス。
- ホストのローカルネットワーク上のシステム。
- インターネットサービス。
- インフラストラクチャのメタデータエンドポイント。
外向き通信ポリシーのフック
より厳しい境界には、次を組み合わせて使用します。
WORK_RUNTIME_DNS(Docker) — ネットワーク有効のすべてのサンドボックスへ--dnsで強制する、カンマ区切りの IPv4/IPv6 リゾルバーアドレス。フィルタリングリゾルバーを指定すると、Libre WebUI を変更せず、名前に基づく許可/拒否リストを使えます。アドレス以外の項目は拒否してログに記録するため、値から追加の Docker フラグを注入することはできません。- 管理対象ブリッジのサブネットに対する、ホストまたは上流ファイアウォール規則(Docker)。ネットワークは名前付きで管理されるため、サブネットは安定しています。
- 独自のドライバーオプションで事前作成したネットワークを指定する
WORK_NETWORK_NAME(Docker)。Libre WebUI は管理対象ラベルと ICC 無効オプションを持つことを確認するため、両方を付けて作成してください。
DNS フィルタリングが制限するのは名前解決であり、IP アドレスを直接指定した外向き通信ではありません。直接 IP への送信を確実に禁止する必要があるデプロイでは、ホスト、クラスタ、上流のファイアウォール規則も必要です。
Work にコードを置けばデータ送信を防げるとは考えないでください。Work アクセスは信頼できるユーザーだけに付与します。タスクをオフラインで開始する必要がある場合は、ネットワーク無効の名前付きランタイムポリシーを使用します。デフォルトポリシーを変更するデプロイ全体の環境変数はありません。
ネットワークアクセスを有効にしても、資格情報は追加されません。Libre WebUI は SSH 鍵、クラウド資格情報、ブラウザプロファイル、ホストのホームディレクトリ、Docker ソケットをタスクコンテナへマウントしません。ただし、ユーザーまたはモデルが /workspace に書き込んだ資格情報やシークレットは、コードから送信できます。
このサンドボックスの通信は、モデル通信とは別です。Ollama とプラグインのリクエストは、Libre WebUI バックエンドから明示的に選択されたプロバイダー経路へ常に送信されます。
サンドボックスのセキュリティ境界
Docker の Work コンテナは次のように動作します。
- 非 root の UID/GID
1000:1000で実行。 - 作業ディレクトリは
/workspace。 - 選択したタスクの名前付きボリュームだけを
/workspaceへマウント。 - 読み取り専用ルートファイルシステムと、容量制限付きの
/tmp一時ファイルシステムを使用。 - すべての Linux capability を削除。
no-new-privilegesを有効化。- 非特権で、init プロセスを使用。
- CPU、メモリ、プロセス、コマンド時間、出力の上限を適用。
- swap をメモリ上限へ固定(
--memory-swapと--memoryが同じ)。swap でメモリ上限を回避できません。 - コンテナ間通信を無効にした管理対象サンドボックスネットワークへ接続するか、ネットワークへ一切接続しない。
- 設定済みプレビューポートだけを、Docker が割り当てたホストのループバックポートへ公開。
コンテナを再利用する前に、これらすべてを docker inspect の結果と照合して再検証し、設定全体のハッシュをコンテナラベル ai.libre-webui.policy に入れます。Libre WebUI のアップグレードより古いポリシーを持つコンテナは、再利用せず破棄して再作成します。そのため、堅牢化の変更は既存タスクにも自動的に反映されます。
Kubernetes ドライバーは同等の Pod セキュリティコンテキストを適用します。非 root の UID/GID、読み取り専用ルートファイルシステム、RuntimeDefault seccomp、権限昇格なし、すべての capability の削除、上限付き一時ストレージ、リソース上限、ServiceAccount トークンなし、/workspace のタスク所有 PVC です。Pod または PVC の再利用や削除前に、タスクラベルとポリシーのフィンガープリントを検証します。
パス検証では、絶対パス、トラバーサル要素、バックスラッシュ、NUL 文字、長すぎるパスを拒否します。ファイルヘルパーは実パスを解決し、シンボリックリンクからの逸脱を拒否します。書き込みでは一時ファイルとアトミックな名前変更を使用します。
これらの制御は、意図しないホスト露出を減らしますが、Work を仮想マシンや安全なマルウェア解析環境にするものではありません。コンテナはランタイムホストのカーネルを共有します。Docker、Kubernetes、ランタイム、イメージ、依存関係、カーネルの脆弱性によって、意図した境界を越えられる可能性があります。
Docker の名前付きボリュームには独立したディスククォータがありません。生成プロジェクトやパッケージのインストールで Docker ストレージを使い切る可能性があるため、ボリュームの増加を監視し、ホスト側のストレージ上限を適用してください。Kubernetes では PVC サイズを要求しますが、実際のクォータ適用は選択したストレージプロビジョナーに依存します。
Docker 本番環境の堅牢化チェックリスト
このチェックリストは Docker バックエンド固有です。Kubernetes の運用担当者は、Kubernetes ガイドに従い、チャートの名前空間単位 RBAC、Pod セキュリティコンテキスト、ストレージクラス、CNI による NetworkPolicy の適用も検証してください。
アプリケーションはコンテナフラグの設定、ワークスペースパスの検証、自身の API の保護を行えます。ホストのファイアウォールポリシー、ストレージドライバーのクォータ、与えられた Docker デーモンの権限レベルは適用できません。プライベートなクライアント用インスタンスでは、これらを明示的なデプロイ作業として扱ってください。
1. Docker の制御を分離する
メインの Libre WebUI コンテナは、Work コンテナの作成と検査のため、デーモンを制御する必要があります。したがって、マウントされた Docker ソケットは通常のデータマウントではなく、コントロールプレーンの資格情報です。ウェブアプリケーションが侵害されると、Docker ホストの侵害につながり得ます。
最初の緩和策は、このリポジトリに含まれています。docker-compose.socket-proxy.yml は、ソケットを Libre WebUI コンテナから完全に切り離します。内部ネットワーク上のソケットプロキシが /var/run/docker.sock を保持し、Work が使用する API セクション(containers、images、volumes、networks、exec、info)だけを転送します。swarm、secrets、configs、build、commit、system のエンドポイントは、デーモンへ届く前に拒否されます。Libre WebUI は DOCKER_HOST=tcp://docker-socket-proxy:2375 でプロキシへ向けられ、ソケットのマウントもソケットグループへの所属も不要です。CLI、対話型ターミナル、Docker 診断もすべてこのエンドポイントに従います。プロキシは API の範囲を狭めますが、転送したエンドポイントが及ぼす範囲は狭めません。コンテナを作成できる主体はホストパスをバインドマウントできるため、以下の境界も引き続き重要です。
より強固な本番境界には、Libre WebUI と Work 用デーモンを、無関係なワークロードのない専用 VM で実行します。さらに強固にするには、Work 専用の rootless Docker デーモンまたは別のランタイムホストを用意し、そのデーモンだけを Libre WebUI へ公開します。展開前に、そのデーモンを使ったファイル所有権、プレビューのルーティング、クリーンアップ、ターミナル対応を検証してください。同じ rootful ホストソケットを読み取り専用でマウントするだけでは、Docker API は読み取り専用になりません。
2. サンドボックスからホスト管理機能へのアクセスを遮断する
コンテナ間通信を無効にすると Work サンドボックス同士の通信は防げますが、Docker ホストにバインドされたサービスへの到達は防げません。アドレスを推測せず、実際の管理対象ブリッジとサブネットを確認してください。
docker network inspect libre-webui-work \
--format 'id={{.Id}} subnets={{range .IPAM.Config}}{{.Subnet}} {{end}}'
ss -lntup
ホストの永続ファイアウォール管理機能を使い、そのブリッジからホスト管理サービスへのトラフィックを拒否します。特に SSH、Docker API、データベース、監視/管理ポートを保護してください。libre-webui-work に接続した使い捨てコンテナから規則をテストし、許可するパッケージダウンロードも確認してから、規則を永続化します。Docker の DOCKER-USER チェーンは転送トラフィックを制御します。宛先が Docker ホスト自身のトラフィックには、ブリッジインターフェース上の INPUT/input-hook 規則も必要になる場合があります。
3. 外向きの宛先を制限する
プロジェクトで明示的に必要としない限り、Work サブネットからクラウドメタデータエンドポイント、プライベートインフラストラクチャ範囲、クライアント LAN 範囲へのアクセスを遮断します。WORK_RUNTIME_DNS によるフィルタリングリゾルバーと、ホストまたは上流のファイアウォール規則を組み合わせます。DNS フィルタリングだけでは、IP アドレスの直接指定で回避できます。任意コマンドがネットワークへ直接接続できる状態では、HTTP プロキシだけでも不十分です。ルーティングポリシーをコンテナ外で適用してください。
クライアントごとに異なる動作が必要なら、名前付きランタイムポリシーを分けて維持します。たとえばオフライン/ネットワークなし、パッケージレジストリ専用、外向き通信を開放したランタイムです。名前付きポリシーが Libre によるサンドボックスネットワーク接続の有無を制御し、ネットワーク有効ポリシーの宛先レベル制限は、外部ファイアウォールとプロキシ規則が引き続き適用します。
4. 実効性のあるストレージクォータを適用する
CPU、メモリ、swap、PID の上限は、名前付きボリュームの容量を制限しません。複数のクライアントへ提供する前に、ワークスペースごとのクォータを実際に適用できるストレージバックエンドを選んでください。例として、XFS の project quota、クォータ付き論理ボリューム、サイズ上限を持つボリューム/PVC ドライバーがあります。通常の ext4 ファイルシステム上のデフォルト Docker local ドライバーは、サイズ値を文書化するだけでは信頼できるボリューム単位のクォータを得られません。
各 ai.libre-webui.managed=true ボリュームと Docker データルートの両方を監視し、ファイルシステムが満杯になる前にアラートを出し、失敗時の動作をテストします。UI カウンターや定期的な du チェックは警告には使えますが、適用境界ではありません。確認の合間にコンテナが残りのディスクを消費できるためです。
5. デプロイ済みポリシーを検証する
イメージまたはデーモンポリシーを変更するたびに、使い捨ての Work タスクを作成し、docker inspect で実際の状態を検証します。非 root UID、読み取り専用ルート、すべての capability の削除、no-new-privileges、メモリ/swap/CPU/PID 上限、タスクボリュームだけのマウント、想定ネットワークを確認します。メインの Libre WebUI コンテナにも意図したマウントだけがあり、公開入口が誤って公開された Docker またはプレビューポートではなく、認証済みリバースプロキシまたはトンネルを通じてアプリへ届くことも確認してください。
プレビューのセキュリティと到達性
Docker タスクでは、ドライバーが設定済みプレビューポートを、バックエンドのループバック上で動的に割り当てたポートへ公開します。Kubernetes では、クラスタ内バックエンドがサンドボックス Pod IP を直接対象にします。モデルとブラウザは任意の上流を選べません。Libre WebUI は正確なタスクとエンドポイント用の capability URL に署名し、リクエストごとにプレビューが実行中か確認して、/api/work/previews を通じて HTTP と WebSocket のトラフィックをプロキシします。プレビューを停止または再起動すると、以前の URL は無効になります。
プレビュー応答から Libre WebUI の資格情報と上流 Cookie は取り除かれます。HTML は iframe sandbox と応答 CSP の両方で制限され、same-origin アクセスを許可せずに、スクリプト、フォーム、モーダル、ダウンロードを許可します。CSP は別タブで開いたプレビューも保護します。生成されたアプリケーションコードは信頼できないままで、ネットワーク外向き通信を使って、自身のワークスペースまたはブラウザ入力から読み取れる内容を送信できます。実行中のプレビュー URL は短時間だけ有効なシークレットとして扱い、共有しないでください。
ブラウザは Libre WebUI 自身の公開オリジンからプロキシを読み込むため、Docker ポートや Pod IP を公開せず、mixed-content ブロックを起こさずに、リモートブラウザや HTTPS リバースプロキシで動作します。リバースプロキシは /api/work/previews/ の WebSocket アップグレードを維持する必要があります。付属の Nginx 設定は対応済みです。
メインアプリケーションが frame source として許可するのは、自身のオリジンと Cloudflare Turnstile だけです。プレビュー応答はメインの Helmet ポリシーを迂回し、リクエスト本文をストリーミングして、上記のより狭いサンドボックスポリシーを適用できます。生成された開発サーバーは通常、互換リソースヘッダーを送信しないため、Cross-Origin Embedder Policy は無効のままです。
デプロイマトリクス
Work の利用可否は、ブラウザやデスクトップ画面だけでなく、Libre WebUI バックエンドを実行するマシンとプロセスによって決まります。
| デプロイ | Work の実行とファイル | 埋め込みプレビュー |
|---|---|---|
ローカルコンピューターの npx libre-webui | Docker がインストールされ、実行中で、バックエンドユーザーから呼び出せる場合に対応。 | 署名付きのアプリケーション同一オリジンプロキシを通じて対応。 |
| ローカルコンピューターでのソース開発 | 同じ Docker とプロバイダーの要件で対応。 | ポート 3001 の開発 API オリジンを通じて対応。 |
| Electron デスクトップクライアント | 条件付き。Electron は外部 Libre WebUI バックエンドを使用し、独自の Work ランタイムを提供しません。 | そのバックエンドの署名付きプロキシ URL を通じて対応。 |
| リモートホストのベアメタル/VM バックエンド | そのホストで Docker を利用できる場合、実行、ファイル、プロバイダー呼び出しが動作。 | 公開リバースプロキシが HTTP と WebSocket のトラフィックを維持する場合に対応。 |
| 標準のリポジトリ Docker Compose | Docker Desktop ではデフォルトで対応。イメージに Docker CLI が含まれ、Compose がホストの Docker ソケットをマウントし、Work のポートは host.docker.internal を経由します。ネイティブの Docker Engine では、さらに到達可能で非公開の WORK_PREVIEW_BIND が必要です。 | 同じ公開 Libre WebUI オリジンを通じて対応。 |
| 現在の Kubernetes/Helm デプロイ | --set work.enabled=true で対応。サンドボックスは PVC ワークスペースを持つ Pod として動作し、名前空間単位 Role とデフォルト拒否 NetworkPolicies の下で、実行、ファイル、コマンド、git、対話型ターミナル、Pod IP の Work Computer 画面と音声を提供。Docker ソケットは一切ありません。Kubernetes ガイドを参照。 | バックエンドがクラスタ内で動作する場合に対応。署名付きプロキシがサンドボックス Pod IP を直接対象にします。 |
Libre WebUI 自身が Docker 内で動く場合に Work を実行する
リポジトリのすべての Compose ファイルで Work は有効です。イメージには Docker CLI が含まれ、Compose ファイルは /var/run/docker.sock をマウントします。Docker Desktop では同梱のルーティング既定値のままで動作します。ネイティブの Docker Engine では、さらに後述のとおり、兄弟コンテナから到達できる非公開のホストインターフェースを WORK_PREVIEW_BIND に設定する必要があります。
Work はそのソケットを通じてホストのデーモンを操作するため、タスクコンテナは Libre WebUI コンテナの子ではなく兄弟です。ホストの docker ps に表示され、ネイティブインストールと同じライフサイクル規則でクリーンアップされます。
ウェブアプリケーションへ Docker ソケットをマウントすると、そのコンテナに Docker ホストの root 相当の制御権を与えます。Work はソケットなしでは動作できないため、Libre WebUI は何もせず黙る機能として提供せず、明示的に有効化します。その結果は明確です。すべての Libre WebUI 管理者が、実質的に Docker ホストの管理者になります。 デーモンのセキュリティ、ネットワーク、ライフサイクル、バックアップ、アクセス制御に伴う影響は運用担当者が管理します。Work を無効にするには Compose ファイルから /var/run/docker.sock の行を削除してください。他の機能は依存していません。
ウェブアプリケーションへソケットを渡さずに Work を維持するには、代わりに docker-compose.socket-proxy.yml を使ってデプロイします。内部ネットワーク上のソケットプロキシがソケットを保持し、Work が使う API セクションだけを転送します。Libre WebUI は DOCKER_HOST を通じて接続します。この境界が保護するものと保護しないものは、Docker の制御を分離するを参照してください。
次の 3 条件をすべて満たす必要があり、Work パネルには失敗した条件が表示されます。
- イメージに Docker CLI が存在すること。 公式イメージには含まれています。カスタムイメージには
docker-cli、またはそれを指すWORK_DOCKER_COMMANDが必要です。ない場合:The "docker" CLI is not installed…。 - ソケットがマウントされていること。 ない場合:
No Docker daemon is reachable…。 - バックエンドユーザーがソケットのグループに所属すること。 イメージは
nodejs(uid 1001)で動作し、ソケットの所有者は通常rootまたはdockerです。そのため Compose はgroup_add: ['${DOCKER_GID:-0}']を渡します。デフォルトは Docker Desktop 向けで、Linux ホストでは独自のグループ ID が必要です。ない場合:The Docker socket is mounted but the Libre WebUI user cannot open it…。
# Read the socket's group as seen INSIDE a container. A macOS host reports a
# different value, because Docker Desktop proxies the socket through a VM.
echo "DOCKER_GID=$(docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
alpine stat -c '%g' /var/run/docker.sock)" >> .env
docker compose up -d --force-recreate
タスクのプレビューポートは、Docker ホストのループバックへ引き続きバインドされます。Libre WebUI は、HTTP アセットと WebSocket アップグレードを含め、各実行中プレビューを署名付きの同一オリジンプロキシ URL で公開します。一時的な Docker ポートをネットワークへ開かず、HTTPS やリモートトンネルの背後でも動作します。プレビュードキュメントには制限付きのブラウザサンドボックスポリシーが適用され、停止または再起動すると以前の URL は失効します。
バックエンド自体が Docker 内で動作する場合、公開と接続で異なるアドレスを使うことがあります。一時ポートを外部公開しないよう WORK_PREVIEW_BIND=127.0.0.1 を維持し、バックエンドコンテナから到達できる Docker ホストアドレス(Docker Desktop では host.docker.internal)を WORK_DOCKER_PUBLISHED_HOST に設定します。同梱の Compose プロファイルは両方の値を設定し、このホスト名をマップします。ネイティブ Linux のデプロイでは、WORK_PREVIEW_BIND を Docker ブリッジのゲートウェイ(または明示的に到達可能で非公開の別のホストインターフェース)で上書きする必要があります。host.docker.internal の対応付けだけでは、ホストのループバックリスナーへ到達可能になりません。これらの生の一時ポートを 0.0.0.0 にバインドしないでください。
同時実行には別々の上限があります。WORK_MAX_ACTIVE_RUNTIMES_PER_USER のデフォルトは 2、WORK_MAX_ACTIVE_RUNTIMES_GLOBAL は 3 なので、管理者は 1 つ目のタスク処理中に 2 つ目を実行できます。capabilities 応答は両方の上限と現在の使用枠を報告します。ホストのメモリと CPU に余裕があれば引き上げてください。
Kubernetes では、ノードのランタイムソケットを公開せず、work.enabled=true でチャートをインストールします。チャートは、Kubernetes ガイドに記載された、スコープ付き RBAC、サンドボックス名前空間、ネットワークポリシー、Pod/PVC 設定を作成します。
ランタイム設定
Work はバックエンドプロセスで次の変数を読み取ります。
| 変数 | デフォルト | 用途 |
|---|---|---|
WORK_RUNTIME_BACKEND | docker | サンドボックスドライバー: docker または kubernetes |
WORK_RUNTIME_IMAGE | node:22.22-bookworm@sha256:2d178f2785b96dfbf62a416ca2e40f50e30150b4ff3320d706f0d96e90600eb3 | タスクサンドボックスに使うイメージ |
WORK_DOCKER_COMMAND | docker | Docker バックエンドの CLI 実行ファイル |
WORK_COMMAND_TIMEOUT_MS | 120000 | デフォルトのコマンドタイムアウト |
WORK_MAX_OUTPUT_CHARS | 50000 | 取得するコマンド/検索出力の最大値 |
WORK_MAX_AGENT_ROUNDS | 48 | 実行ごとの、プロバイダーに依存しないモデル/ツールのラウンド予算 |
WORK_MEMORY_LIMIT | 2g | コンテナごとのメモリ上限 |
WORK_CPU_LIMIT | 2 | コンテナごとの CPU 上限 |
WORK_PIDS_LIMIT | 256 | コンテナごとのプロセス上限 |
WORK_PREVIEW_PORT | 4173 | アプリがコンテナ内で待ち受ける必要があるポート |
WORK_PREVIEW_BIND | 127.0.0.1 | プレビューポートを公開するホストインターフェース |
WORK_DOCKER_PUBLISHED_HOST | WORK_PREVIEW_BIND と同じ | Docker が公開した Work ポートへバックエンドが接続するホスト/IP |
WORK_COMPUTER_SCREEN_PORT | 6080 | 画面ブリッジのコンテナ内 WebSocket ポート |
WORK_COMPUTER_AUDIO_PORT | 6081 | 音声ブリッジのコンテナ内 WebSocket ポート |
WORK_RUN_LEASE_WAIT_MS | 60000 | 一時的なランタイムリース保有者を実行が待つ時間 |
WORK_MAX_ACTIVE_RUNTIMES_GLOBAL | 3 | Libre WebUI インスタンスあたりの同時コンテナ型タスク数 |
WORK_MAX_ACTIVE_RUNTIMES_PER_USER | 2 | 管理者あたりの同時コンテナ型タスク数 |
WORK_MAX_TASKS_GLOBAL | 500 | Libre WebUI インスタンスあたりの永続 Work タスク上限 |
WORK_MAX_TASKS_PER_USER | 100 | 管理者あたりの永続 Work タスク上限 |
WORK_NETWORK_NAME | libre-webui-work | ネットワーク有効タスク用の管理対象サンドボックスブリッジ |
WORK_RUNTIME_DNS | 未設定 | ネットワーク有効タスクへ強制する、カンマ区切りのリゾルバー IP |
WORK_DOCKER_SOCKET | DOCKER_HOST が unix:// または tcp:// の場合はその値、それ以外は /var/run/docker.sock | 対話型ターミナルで使う Docker Engine エンドポイント |
WORK_TERMINAL_MAX_SESSIONS_PER_TASK | 2 | タスクごとの同時対話型ターミナル数 |
WORK_TERMINAL_IDLE_TIMEOUT_MS | 900000 | ターミナルセッションを閉じるまでのアイドル時間 |
WORK_RUNTIME_IDLE_TIMEOUT_MS | 0(無効) | この時間操作がなければサンドボックスを停止(プレビューも対象) |
WORK_K8S_NAMESPACE | libre-webui-work | Kubernetes のサンドボックス Pod/PVC 名前空間 |
WORK_K8S_STORAGE_CLASS | クラスタのデフォルト | Kubernetes ワークスペース PVC 用 StorageClass |
WORK_K8S_WORKSPACE_SIZE | 5Gi | タスクごとの Kubernetes PVC のデフォルトサイズ |
WORK_K8S_POD_READY_TIMEOUT_MS | 900000 | サンドボックス Pod の準備完了を待つ最大時間 |
WORK_K8S_POD_GONE_TIMEOUT_MS | 60000 | 削除したサンドボックス Pod が消えるまで待つ最大時間 |
本番環境では、固定のイメージバージョンまたはダイジェストを使用してください。可変イメージタグでは、Libre WebUI を変更しなくても、利用可能なコマンドラインツールとセキュリティ境界の両方が変わる可能性があります。
実行、プレビュー、ファイルヘルパー、コマンド、サンドボックス再作成の操作は、同じプロセス内の容量計算を共有します。すでに計上されたタスク内のネスト操作は、別のタスクとして計上しません。タスクまたはランタイムの受付上限を超えたリクエストには HTTP 429 が返ります。
固定のプロトコルおよび UI 上限
| 項目 | 上限 |
|---|---|
| 新しいタスクまたは実行のメッセージ | 65,536 文字および UTF-8 バイト |
| タスク作成/更新時のモデル ID | 500 文字および UTF-8 バイト |
| プラグインプロバイダー ID | 200 文字 |
| タスクごとの有効な実行 | 1 |
| コマンドテキスト | 20,000 文字 |
| ツールが要求するコマンドタイムアウト | 1~600 秒 |
| プレビューの準備完了 | 15 秒 |
| ファイルの読み書き | 2,000,000 バイトの UTF-8 テキスト |
| 直接のディレクトリ一覧 | 先頭 1,000 項目 |
| メッセージページ | 最大 200 メッセージ、1,000,000 バイト |
| 永続化する個別メッセージ | 100 KB |
| モデルへ送信する会話コンテキスト | 直近 30 件のユーザー/アシスタントメッセージ、最大 256 KB |
| 永続化するツール出力 | 元の約 20,000 文字とマーカー |
| リアルタイムのエディター構文強調 | 8,000 文字、400 行 |
| ブラウザ側の整形 | 100,000 文字、4,000 行 |
| Git status 出力 | 取得文字数 2,000,000 |
| Git diff 出力 | 取得文字数 600,000 |
| Git 履歴 | ローカルコミット 20 件 |
| 1 回の Git stage リクエスト内のパス | 200 |
| Git コミットメッセージ | 4,000 文字 |
| すべてのプロバイダー経路のエージェントループ | デフォルト 48 ラウンド、WORK_MAX_AGENT_ROUNDS で設定 |
| ツール呼び出しの安全予算 | max(128, configured rounds × 8) 回 |
ファイルアクセスは UTF-8 テキスト用です。統合エディターはバイナリファイルエディターではなく、2 MB を超えるファイルは Work ファイル API から開けません。
API の概要
すべてのエンドポイントは /api/work 配下にあり、認証と、データベース上で現在有効な Work アクセス権を必要とします。Work はデフォルトで管理者専用ですが、管理者は通常のタスク操作を有効なユーザーへ開放できます。ホストフォルダーの選択と、管理ポリシー/アクセスのエンドポイントは引き続き管理者専用です。
| メソッド | パス | 用途 |
|---|---|---|
GET | /capabilities | 選択されたランタイム/プロバイダーの利用可否と上限 |
GET | /tasks | 現在の管理者のタスクを一覧表示 |
POST | /tasks | タスクと最初の非同期実行を作成 |
GET | /tasks/:id | タスク状態と最近のメッセージを読み込み |
GET | /tasks/:id/messages | 古いメッセージをページ表示 |
PATCH | /tasks/:id | 名前変更または明示的なモデル経路の変更 |
DELETE | /tasks/:id | タスクと永続ワークスペースを削除 |
POST | /tasks/:id/runs | 後続の実行を開始 |
POST | /tasks/:id/messages | 実行中のエージェントへメッセージを送信 |
GET | /tasks/:taskId/runs/:runId/events | SSE で認証済みのリアルタイム実行イベントをストリーミング |
POST | /tasks/:id/cancel | 有効な実行をキャンセル |
GET | /tasks/:id/approvals | 保留中の承認とタスクの自動レビュー状態 |
PUT | /tasks/:id/approvals | タスク単位の承認オプトインを切り替え |
POST | /tasks/:id/approvals/:approvalId | 保留中の承認を判断(1 回のみ許可/常に許可、拒否) |
DELETE | /tasks/:id/approval-rules/:ruleId | 「常に許可」ルールを削除 |
GET | /computer/setup | Work Computer のセットアップ状態(管理者) |
POST | /computer/setup | GUI イメージをビルドしてポリシーを作成(管理者) |
POST | /tasks/:id/computer/start | タスクの Work Computer セッションを開始 |
GET | /tasks/:id/computer/control | 画面を操作中のユーザーと、エージェントの引き継ぎ要求 |
POST | /tasks/:id/computer/control | 画面を引き継ぐ(または操作権を更新) |
DELETE | /tasks/:id/computer/control | 画面をエージェントへ返す |
POST | /tasks/:id/computer/teach | 記録したデモを教示済みスキルとして保存 |
POST | /tasks/:id/computer/anchor | 記録されたクリック下の要素を解決 |
POST | /computer/skills/:slug/trace | 教示済みスキルへ成功/失敗の行を追加 |
GET | /tasks/:id/files | ワークスペースディレクトリを一覧表示 |
GET | /tasks/:id/file | ワークスペースのテキストファイルを読み取り |
PUT | /tasks/:id/file | ワークスペースのテキストファイルを保存 |
GET | /tasks/:id/git | 保護されたローカル Git status と履歴を読み取り |
GET | /tasks/:id/git/diff | 上限付きのローカル差分を読み取り |
POST | /tasks/:id/git/init | ローカル Git を初期化 |
POST | /tasks/:id/git/stage | 明示的なワークスペースパスをステージ |
POST | /tasks/:id/git/commit | ステージ済み変更をコミット |
POST | /tasks/:id/git/branches | ローカルブランチを作成 |
POST | /tasks/:id/git/switch | クリーンな既存ローカルブランチへ切り替え |
POST | /tasks/:id/preview/start | 管理対象プレビューを開始 |
POST | /tasks/:id/preview/stop | 管理対象プレビューを停止 |
タスク ID は常に認証済み所有者と照合されます。現在のアカウント状態、ロール、Work アクセスポリシーをリクエストごとにデータベースから読み取るため、古い JWT に期限切れのロールクレームが残っていても、権限の取り消しは反映されます。
タスク更新スキーマには、内部互換性のためバックエンドの networkEnabled フィールドが残っています。独立した Work UI 操作としては公開されません。タスク作成時に、目的のネットワークデフォルトを持つ名前付きランタイムポリシーを選びます。生のフィールドを永続設定 API として使用しないでください。
削除、アカウント変更、バックアップ
タスクの削除
タスク削除は意図的に破壊的です。
- バックエンドがタスクを廃止中として記録し、新しい変更操作を開始できないようにします。
- 有効な実行をキャンセルし、タスクサンドボックスを停止します。
- Libre WebUI がランタイムリソースのタスク所有権ラベルを検証します。
- コンテナ/Pod と名前付きボリューム/PVC を削除します。
- データベースのタスクを削除し、実行とメッセージも連鎖削除します。
- API 成功後、そのタスク用のブラウザ下書きを消去します。
ランタイムのクリーンアップに失敗した場合、Libre WebUI はタスクのデータベースレコードを保持してエラーを返します。運用担当者は Docker または Kubernetes バックエンドを修復し、再試行できます。追跡不能なサンドボックスやワークスペースを残したまま、メタデータだけを黙って削除することはありません。
実行またはプレビューの停止は削除とは異なります。実行を停止しても、名前付きボリュームと会話を保持します。
管理者の降格とユーザー削除
管理者を降格すると、Libre WebUI はランタイムのクリーンアップに依存する前に、ロール取り消しを永続化します。以後すべての Work リクエストで、現在のロールとアクセスモードを確認します。新しいロールでアクセスできなくなると、バックエンドはユーザーの Work タスクを停止し、有効な実行の中止とサンドボックス停止を試みます。クリーンアップに失敗しても取り消したアクセス権は取り消されたままで、ロール更新は失敗を報告するため、運用担当者はランタイムを復旧して再試行できます。
別のユーザーを削除する場合、最初にそのユーザーの管理対象 Work リソースをすべて削除します。外部ランタイムのクリーンアップに失敗した場合はユーザーレコードを保持し、安全なクリーンアップに必要な所有権メタデータを失わずに管理者が再試行できるようにします。
タスク全体をバックアップする
完全な Work バックアップには次の両方が必要です。
- タスク所有権、Docker または Kubernetes のリソース名、プロバイダーのルーティング、実行、メッセージ、アクティビティを含む Libre WebUI データベース。
- Work ファイルを含み、
ai.libre-webui.managed=trueラベルが付いた、すべての Docker ボリュームまたは Kubernetes PVC。
使い捨てコンテナとプレビュープロセスはバックアップ不要です。一貫性のあるバックアップには、新しい Work アクティビティを止め、バックエンドを停止してから、データベースとタスクワークスペースを取得します。使用中のバックエンドに応じて、Docker ボリュームまたは Kubernetes ストレージプロバイダーのスナップショット手順に従ってください。
データベースと対応するワークスペースを一緒に復元します。データベースに記録された正確な名前で各ボリュームまたは PVC を再作成し、ai.libre-webui.task=<task UUID> と ai.libre-webui.managed=true を含むタスク所有権メタデータを復元します。ファイルだけをコピーしても Docker または Kubernetes のラベルは保持されません。データベースだけを復元すると、ファイルがないタスクレコードになります。ストレージだけを復元すると、Libre WebUI が検索と検証に使うタスク所有権と生成済みリソース名が失われます。
インストール環境で暗号化済みプロバイダー資格情報も使っている場合は、データディレクトリと暗号化鍵に関する Libre WebUI のメインバックアップガイドに従ってください。
ローカライズとアラビア語 RTL
Work 画面全体は、対応する 25 言語すべてに翻訳されています。英語、アラビア語、ベンガル語、チェコ語、デンマーク語、ドイツ語、スペイン語、フランス語、ヒンディー語、インドネシア語、アイスランド語、イタリア語、日本語、韓国語、マレー語、オランダ語、ポーランド語、ポルトガル語、ロシア語、スウェーデン語、タイ語、トルコ語、ウクライナ語、ベトナム語、中国語です。
アラビア語では、React のレンダリング前に lang="ar" と dir="rtl" を適用します。サイドバーは右へ移動し、デスクトップの分割表示では会話が右、ワークスペースが左に配置されます。方向を示すアイコンは反転し、タブ移動は RTL 順になり、ドラッグ/キーボードによるサイズ変更は見た目どおりの RTL セマンティクスを使います。
方向によって正しさが変わる技術コンテンツは、左から右のままです。
- コードと構文強調。
- ファイルシステムパス。
- モデル ID。
- コマンドとプレビューログ。
- ツール出力とメタデータ。
- コードブロックの内容。
タスク名、自然言語プロンプト、エラー、ファイル名、プレビューコマンドは、適切な場合にテキスト方向を自動判定します。
トラブルシューティング
npx 使用時にランタイムを利用できない
npx libre-webui はホスト上でバックエンドを実行しますが、Docker はインストールしません。Libre WebUI を起動する同じ OS ユーザーで docker info を実行してください。コマンドがない、またはデーモンへ到達できない場合は、Docker をインストール/起動するか、そのユーザーのデーモン権限を修正してから Work を再読み込みします。
また、Ollama が正常であるか、有効な補完/チャットプラグインの少なくとも 1 つに、現在の管理者用のモデルと資格情報が設定されていることを確認します。
Docker または Kubernetes でランタイムを利用できない
リポジトリの Compose デプロイでは通常、この状態になりません。イメージには Docker CLI が含まれ、Compose ファイルはホストのソケットをマウントします。発生した場合、パネルに原因が表示されます。カスタムイメージに CLI がない、ソケットのマウントが削除されたか存在しない、コンテナユーザーがソケットのグループに所属していない、のいずれかです。最後の場合は DOCKER_GID を設定し、コンテナを再作成します。Libre WebUI 自身が Docker 内で動く場合に Work を実行するを参照してください。
Kubernetes では、--set work.enabled=true でネイティブランタイムを有効にします。その後 Libre は kubernetes と報告し、Kubernetes API をプローブして、PVC ワークスペースを持つ Pod としてサンドボックスを実行します。ノードのコンテナランタイムソケットをマウントしないでください。Kubernetes ガイドを参照してください。
Work 互換モデルがない
Ollama では、tools を公開するモデルを確認または選択します。プラグインでは次を確認してください。
- 種別が補完またはチャット。
- 有効。
- 正確なモデルが設定済みモデルマップに存在。
- 現在の管理者が使用可能な API キーを所持。
- リモートモデルが、そのプロバイダーのツール呼び出しを実装。
Work が別のプロバイダーへフォールバックしてルーティングすることはありません。
パッケージのインストールまたはリモート Git コマンドが失敗する
タスクで選択した名前付きランタイムポリシーがネットワークアクセスを有効にしていることを確認します。独立したタスクごとのネットワークスイッチはありません。その後、DNS、プロキシ、ファイアウォール/NetworkPolicy、レジストリ、証明書、ランタイム、上流サービスの設定を確認します。選択したランタイムイメージに、呼び出すコマンドが含まれることも確認してください。
「Git」タブはローカル専用で、リモート操作を決して行いません。タスクのネットワークおよび資格情報ポリシーでリモート Git を意図的に許可している場合だけ、ターミナルまたはモデルのコマンド画面を使用します。長期間有効なアクセストークンをタスクワークスペースへ貼り付けないでください。
エージェント上限で実行が停止する
設定済みラウンド予算またはそこから導出したツール呼び出しの安全予算を、モデルが使い切った可能性があります。Work は実行終了前にツールなしの最終引き継ぎを要求するため、完了した作業と残りの手順を確認してください。タスクは入力が必要のままになります。これはその実行の最終状態ですが、意図的に完了とは主張しません。同じ永続ワークスペースで続けるには後続の実行を開始します。ホストとリモートプロバイダーのコストポリシーで長い実行を許容できる場合は、すべてのプロバイダーに適用される WORK_MAX_AGENT_ROUNDS を意図的に引き上げます。
Work 開始時に HTTP 429 が返る
インスタンスまたは管理者が、有効ランタイム数または永続タスク数の受付上限に達しています。別の実行またはプレビューが停止するのを待つか、古いタスクを削除するか、十分なリソースを持つホストで対応する WORK_MAX_* 設定を意図的に引き上げます。
プレビューが準備完了にならない
コマンドが実行中のままで、0.0.0.0 にバインドし、15 秒以内に WORK_PREVIEW_PORT で待ち受けることを確認します。コマンドが空の場合、Work は package.json の dev スクリプトまたは単純な index.html を自動検出します。単一のネスト済みアプリも対象です。複数のアプリまたは対応エントリーポイントなしとエラーに表示された場合、任意のコマンド欄へ明示的なコマンドを入力します。カスタムコマンドは /workspace から開始するので、ネスト済みアプリには cd <app-directory> && ... を使います。
サーバーではプレビューが動くがリモートブラウザでは動かない
署名付き Work プレビュープロキシを含むビルドがデプロイされていることを確認し、プレビューを再起動して従来のループバック URL を置き換えます。通常ページは読み込めてもホットリロードが動かない場合、リバースプロキシとトンネルが /api/work/previews/ の WebSocket アップグレードを許可しているか確認します。Docker が公開するポートはバックエンドのループバックに置いたままでよく、ファイアウォールで開く必要はありません。
ファイルは残っているがプレビューが停止した
キャンセル、バックエンド再起動、明示的なプレビュー停止、準備確認の失敗後には正常な動作です。プレビュープロセスは一時的で、名前付きボリュームは永続的です。タスクを再度開き、プレビューを開始してください。
ファイルを開く、または保存できない
統合ファイル API が受け付けるのは、最大 2 MB の UTF-8 テキストファイルです。ファイルを開いた後に変更されたとの保存エラーが出た場合、再編集前に再読み込みしてください。別のモデルまたはブラウザによる変更を上書きせずに済みます。
8,000 文字または 400 行を超えると、構文強調は意図的に平文へ切り替わります。整形には別途、100,000 文字、4,000 行の上限があり、文書化されたファイル形式だけに対応します。
Work がサンドボックスを復旧中と表示する
起動または終了処理で、1 つ以上の既知サンドボックスが停止したことを証明できませんでした。Work は安全側に閉じたまま 10 秒ごとに再試行します。Docker デーモンまたは Kubernetes API へのアクセスを復旧し、バックエンドログを確認してください。ラベル付きランタイムリソースの調整が必要な間は、タスクのデータベース行を削除しないでください。
タスク削除が失敗する
選択したランタイムへ到達できることを確認します。想定される ai.libre-webui.task ラベルがない競合リソースは、削除せず意図的に拒否されます。名前/所有権の競合を慎重に解決してから、削除を再試行してください。
セキュリティのまとめ
インストール環境で Work を有効にする前に、次の点を確認してください。
- Work はデフォルトで管理者専用です。すべてのユーザーへ開放すると、有効な各アカウントがサンドボックス運用者になります。意図を持って判断してください。ホストフォルダーのワークスペースは、どのモードでも管理者専用です。
- バックエンドは、設定済み Docker デーモンまたは Kubernetes サンドボックス名前空間を制御する必要があります。
- コンテナはファイルシステムの露出を減らしますが、仮想マシンではありません。
- 名前付きオフラインポリシーのないタスクは外部ネットワークへアクセスできます。名前付きポリシーがデフォルトを選択し、宛先レベルの制限は運用担当者の責任です。
- Work ボリュームに独立したディスククォータはありません。
- 「Git」タブはローカル専用です。その API がリモート資格情報をマウントまたは受け付けることはありません。
- ホストのファイアウォールポリシー、デーモン分離、外向き通信制限、実効性のあるボリュームクォータは、運用担当者が適用します。
- リモートプロバイダーは要求されたツール結果を受け取り、1 回の実行で複数の呼び出しが発生することがあります。
- プレビューポートはバックエンドのループバックに留まり、署名付きで失効可能なプロキシ URL だけを通じて公開されます。
- 標準 Docker Compose は Docker ランタイムを提供し、Kubernetes/Helm は
work.enabled=trueの場合にネイティブ Pod/PVC ランタイムを提供します。 - 完全なバックアップには、Libre WebUI データベースと Work ボリュームの両方が必要です。