Skip to content

CH 11 · ツールとサンドボックス

全文字数約 3430 字所要時間約 15 分前提CH 03–05 が動作済み難易度手を動かせる

この章の目標

前章までで Agent が動いているのを見ました:自発的にファイルを読み、コマンドを走らせ、ウェブを検索し、機微な操作についてはダイアログで確認を求めてきます。この章では「ツール」と「サンドボックス」を分解します —— ツールはどう呼ばれるのか、どんなチェックを通るのか;サンドボックスはどう Agent を囲い、境界に当たると何が起きるのか。この 2 つのメカニズムが分かれば、なぜ Agent が「あなたの PC で動ける」のか、そして実際に何に触れないのかが分かります。

ツール:Agent の「手」

dsh では、Agent 自身は何も動かせません;Agent のあらゆる「行動」は ツール を通じて行われます —— ファイル読み、コマンド実行、ウェブ検索、それぞれが 1 つのツールです。CH 08 で「工具庫 + 門番」と述べました;もう少し分解します。

システム内のツールは次のような形をしています:

部分役割
schemaモデルに見せる「取扱説明書」:名前、説明、パラメータ(JSON Schema)
実行関数実際に作業を行うコード
出力宣言完了時に返すべき構造
スケジューリングメタデータ並列実行可能か、タイムアウト、UI での表示方法

鍵は最初の 1 つ:モデルの目にはツールの名前・説明・パラメータだけがあり、実行関数・出力宣言・タイムアウト・並列フラグのいずれもモデルには見えません。 これが第 1 層の安全性です:モデルは「このツールがある、パラメータはこの形で埋める」を知っているだけで、内部の実装は知らず、実行ロジックを迂回することもできません。

1 回のツール呼び出し:拡張可能なパイプライン

モデルがツール呼び出しを指示したあと、直接実行されるわけではなく、拡張可能なパイプラインを通ります。公式チームはこのパイプラインを、各段階がプラグインに介入・拡張可能なように設計しています —— また「すべてはプラグイン」(図では任意の finalizeContent 段階を省略;これはツール自身の end-of-pipe コールバックで、主線に影響しません):

1 回のツール呼び出し:モデルリクエストから権威ある結果まで(模式図)

順を追って:

  1. モデルリクエスト:モデルが tool/call(ツール名 + パラメータ)を発行。先にパラメータが検証され、不正なら直接エラー(INVALID_ARGS)が投げられ、実行されません。
  2. pre-execute:最初のチェックポイント。ここで allow / deny / ask を判定 —— UI で見る承認ダイアログはこの層で発生します。
  3. guard:単調ガードで、緩めることはできても厳しくすることはできず、ある段階で境界が密かに緩むのを防ぎます。
  4. execute:実際に実行。サンドボックスはこのステップにマウントされる —— コマンドが実際に走る前に、ファイルシェルでラップされます(下記参照)。
  5. post-execute:結果を検査し、必要なら置換可能。
  6. result:権威ある結果を生成、モデルへフィードバック、次のラウンドに入ります。

各ステップにはプラグインがフックを掛けられます —— だから後でプラグインを書くときに「あるツール呼び出しに介入する」プラグインが作れるわけです(CH 21 でフックを扱います)。このパイプラインを読めば、承認・サンドボックス・ログといった「安全部品」がどこに取り付けられているかが分かります。

サンドボックス:コマンドを囲む「ファイルシェル」

CH 04 では 3 段階の権限(read-only / workspace-write / danger-full-access)を UI 操作の視点から扱いました。ここではメカニズムを見ます:サンドボックスが管理するのはファイルシステムへの効果のみ、ネットワークとプロセスの可視性は管轄外。

公式チームはサンドボックスを「ポリシー」と「バックエンド」の 2 層に分けて設計しています:

![サンドボックス:ポリシーが境界を宣言、バックエンドが強制(模式図)](/assets/part03/ch11-sandbox.svg

  • ポリシー(SandboxPolicy):呼び出しごとに再解析 —— モード + 作業ディレクトリルート。作業ディレクトリルートは現在のセッションの cwd から派生します。
  • バックエンド(SandboxProvider):そのプラットフォーム向けにコマンドを制限プロセスにラップします。プラットフォームごとに実装があり —— Linux は bwrap / Landlock(カーネルレベルの非特権アクセス制御)、macOS は Seatbelt、Windows は ACL 制限トークンのランナー。

覚えておくべき設計がいくつか:

fail-closed:これがセキュリティの鍵です。現在の環境で利用可能なサンドボックスバックエンドがなければ、システムは直接 SANDBOX_UNAVAILABLE エラーを返します、決して「サンドボックスなしで素のまま走らせる」へ密かにダウングレードしません。実行を拒否するほうが、緩めるリスクを取るよりマシです。

danger-full-access はシェルを被せない:制限モード(read-only / workspace-write)だけがサンドボックスラッパー通ります。全権限モードはファイル隔離なしで直接元のコマンドを spawn します —— これが UI で第 3 段階に切り替えるときに二重確認する理由でもあります。

完全性は full / partial に強制分割:ほとんどの場合バックエンドは約束した全ファイル効果を管理できます(full);しかし古い Linux カーネル ABI や一部の Windows 境界では一部しか管理できず(partial)、絶対的な保証が必要なシナリオではこの点に留意する必要があります。通常の日常利用ではデフォルトの workspace-write で十分に安定しています。

実操作:自分で見てみる

ステップ 1:軌跡でツール呼び出しを見る

Web UI で、何かしらアクションを行うタスク(例:CH 05 のようなリポジトリサマリ)を走らせます。終わったら、軌跡 タブに切り替え、任意の TOOL 行をクリックします。右側パネルに重要な 4 つのタブがあり、ちょうど上記のツール構造に対応します:

  • Schema:ツールの「取扱説明書」(名前、説明、パラメータ)
  • Payload:今回送られた実際のパラメータ
  • Result:返された結果
  • Summary / Timing:要約と経過時間

下の画像は実呼び出しです:左で TOOL 行(web_search)がタイムラインで選択され、右側のパネルで全タブが展開、下にはラウンド全体の統計が見えます —— 真ん中にネットワーク問題で失敗した pwsh コマンドが 2 本あり、Agent は即座に web_search に切り替えています。これはまさに「ツールは失敗時に経路を変える」実例です:

軌跡でのツール呼び出し詳細:左で TOOL 行を選択、右で Schema / Payload / Result タブを展開

ステップ 2:承認を見る

デフォルトの workspace-write 権限で、Agent に作業ディレクトリ外のファイルを書かせます。ここでは、E:\software-workspace\doubaowork\doubao の下にグリーティングファイルを作らせました —— このディレクトリは現在の作業ディレクトリには入っていません:

Agent に作業ディレクトリ外のファイルを書かせる:コマンド入力

実際に起きるのは 2 ステップ である点に注意:

  1. 最初の書き込みは直接壁にぶつかります —— 軌跡には Write · Error: [sandbox: file access denied under workspace-write mode] と表示されます。
  2. Agent はターゲットが作業ディレクトリ外だと認識し、自発的にエスカレーションを要求;pre-execute 層の確認ダイアログはこの時点で初めてポップアップします:サンドボックスを danger-full-access にアップグレード、理由を添えて。下部の 2 つのボタン —— 拒否(Deny)今回だけ許可(Allow once):

エスカレーション承認ダイアログ:拒否 / 今回だけ許可

「今回だけ許可」をクリックすれば、この 1 回の書き込みだけ許可されます;「拒否」をクリックすれば、別の方法を探す必要があります。

ステップ 3:read-only に切り替えて見る

入力欄に /permission と打ち、read-only に切り替えます(入力後、UI に permission · preset read-only と表示されます)、Agent にファイルを書き込ませます。結果は 上記と似ていますが、重要な違いが 1 つ:

read-only モードでの書き込み拒否:エラー + エスカレーション要求

  1. 最初の書き込みも壁にぶつかります —— ただしエラーが違います: Write · Error: [sandbox: file access denied under read-only mode]
  2. Agent もエスカレーションを要求しますが —— 今回はターゲットが escalate sandbox to workspace-write、danger-full-access ではありません(通常の書き込み権限が必要なので、全開にするまでもない)。

3 つの「ブロックされた」ケースを比べると明らかです:どの権限レベルでも、書き込みに失敗したときは、まず Agent が壁にぶつかり、その上でダイアログがポップアップします。 違いはエラーメッセージ(workspace-write モード / read-only モード)と、要求する次のレベル(danger-full-access / workspace-write)。「拒否」ボタンは常にあります —— これがサンドボックス設計の核です:Agent は「要求」できるが、「与えるか否か」は常にあなた次第。

この章で学んだこと

下の項目を自力で達成できれば合格です:

  • [ ] ツールを構成する部分を言え、どれがモデルに見え、どれが見えないかを言える
  • [ ] ツール実行パイプラインを描ける(モデルリクエスト → pre-execute → guard → execute → post-execute → result)、承認とサンドボックスがどこにそれぞれマウントされているかを言える
  • [ ] サンドボックスが「ファイルシステムへの効果のみ」を管理するとは何を意味するか、そしてその理由を説明できる
  • [ ] fail-closed を説明できる:サンドボックスバックエンドが利用できないとき何をするか(SANDBOX_UNAVAILABLE を返し、素のまま走らせない)
  • [ ] 軌跡でツール呼び出しを展開でき、Schema / Payload / Result を理解する
  • [ ] 異なる権限レベルで書き込みが拒否されたときのエラー(workspace-write モード / read-only モード)と、Agent が要求するエスカレーション先(danger-full-access / workspace-write)を言える
  • [ ] 書き込み失敗時は Agent がまず壁にぶつかりダイアログをポップアップするが、「拒否」は常にあなたの手にある、を説明できる

Open Source · MIT · Community Driven