← 一覧へ
連載 Agentic OS:技術スタックを下から読む の一部です ―― 目次を見る →

Agentic OS 技術スタックを下から読む 第11回:手を動かさせる前に ―― サンドボックスという「縛られた実行環境」

この記事の読み方
ここまでの回では、主にモデルそのものを見てきた。

モデルから運行时へ

ここまでの回では、主にモデルそのものを見てきた。

モデルは、入力を読み、次に来るものを予測し、文章を組み立てる。効率を上げる工夫もあれば、能力を広げる工夫もある。だが、その中心にあるのは、あくまで「考える」ことだった。

もちろん、考えるだけでも十分に強力である。要約する。分類する。説明する。計画を立てる。文章を書く。これだけでも、多くの仕事は変わる。

しかし、それだけではまだエージェントではない。

エージェントは、手を動かす。検索する。ファイルを読む。ファイルを書き換える。コードを実行する。外部の道具を呼ぶ。何かを予約する。何かを送信する。つまり、世界の状態を変える。

ここで層が変わる。

前回まで見てきたのは、モデルの中で何が起きるかだった。今回から入るのは、そのモデルを実際に走らせ、行動させ、状態を抱えさせる運行时の層である。

その最初の関門は、安全である。

エージェントに手を動かさせるなら、その手はどこまで届いてよいのか。何を触ってよいのか。どれだけ計算してよいのか。失敗したとき、どこで止まるのか。

この問いを避けたまま、エージェントを外の世界につなぐことはできない。

考えるだけなら安全、動かすと危ない

文章を返すだけのモデルは、間違えることがある。

間違った説明をする。古い情報を言う。もっともらしいが存在しない話を作る。これは危険ではあるが、危険の形はまだ限られている。出てくるものは、基本的には文章である。

ところが、エージェントが自分でコードを書き、それを実行し始めると、話は変わる。

コードは文章ではない。動く。

動けば、ファイルを読むかもしれない。ファイルを書き換えるかもしれない。ネットワークにつながるかもしれない。大量のメモリを使うかもしれない。終わらない処理に入るかもしれない。

そこに悪意があるとは限らない。

むしろ、多くの場合はただの失敗である。生成されたコードにバグがある。入力の形を勘違いしている。終了条件を書き忘れている。大きすぎるデータを一度に読もうとする。保存先を間違える。

人間が書くコードにも、こうした失敗はある。エージェントがその場で書いたコードなら、なおさら起きる。

問題は、その失敗がどこまで広がるかである。

もし生成されたコードを、利用者の環境で、そのまま全権限で動かしたらどうなるか。作業中のファイルを読める。設定ファイルを読める。秘密情報に触れるかもしれない。重要なファイルを上書きするかもしれない。外部に通信できるなら、読んだものを送ることもできる。

これは、見知らぬ相手に家の鍵を渡すのに近い。

相手が悪人かどうか以前に、鍵を渡す設計そのものが危うい。間違えて台所を水浸しにするかもしれないし、玄関を開けっぱなしにするかもしれない。だから、最初から家全体には入れないほうがよい。

エージェントにコードを実行させるときも同じである。

考えさせるだけなら、出力を読んで判断できる。だが、動かさせるなら、失敗の影響範囲を先に決めておかなければならない。

手を縛った実行環境を用意する

そこで必要になるのが、サンドボックスである。

サンドボックスとは、動くことはできるが、手は縛られている実行環境である。中では処理を実行できる。計算もできる。必要なら一時的なファイルも作れる。だが、その影響は外へ勝手には漏れない。

砂場を思い浮かべるとわかりやすい。

子どもは砂場の中で自由に遊べる。穴を掘ってもよい。山を作ってもよい。崩してもよい。だが、その遊びは砂場の中に閉じている。家の床を掘るわけではない。道路に砂をまき散らすわけでもない。

サンドボックスの核心も同じである。

信用していないコードを、信用しなくてよい場所で動かす。

ここで大事なのは、コードを信用しようとしないことだ。

「このコードはモデルが書いたから大丈夫だろう」と考えない。「このタスクは簡単だから問題ないだろう」とも考えない。そうではなく、間違う前提で囲う。暴走する前提で止める。余計なものに触る前提で、触れないようにする。

これは、エージェントを疑うというより、実行という行為を正しく扱うということに近い。

どれほど賢いモデルでも、実行されたコードの副作用は現実に残る。だから、現実に残ってよい範囲を、先に区切る。

何を縛るのか

では、具体的に何を縛るのか。

大きく四つある。ファイル、ネットワーク、メモリ、計算量である。

まず、ファイルである。

実行中のコードに、利用者の環境全体を見せてはいけない。原則として、何も触らせない。必要がある場合だけ、読んでよい場所、書いてよい場所を明示する。

たとえば、変換したい表があるなら、その表だけを渡す。出力先が必要なら、一時的な保存場所だけを与える。作業に関係のない文書、設定、鍵、履歴には届かないようにする。

次に、ネットワークである。

ネットワークは便利だが、危険も大きい。外部の情報を取りに行けるということは、外部へ情報を送れるということでもある。どこへつながったのかを後から追うのも、簡単ではない。

だから、勝手に外へ出られる状態にしない。通信が必要なら、管理された窓口だけを通す。どの宛先に、どの方法で、何を送ってよいのかを、実行環境の外側で決める。

三つ目は、メモリである。

コードは、メモリを使いすぎることがある。大きなファイルを一度に読み込む。配列を無限に増やす。不要なものを捨てない。こうした処理がそのまま走ると、実行している箱だけでなく、周囲のアプリケーションや本体まで巻き込んで不安定にする。

そこで、使えるメモリに上限を置く。上限を超えたら止める。失敗はサンドボックスの中で終わらせる。

四つ目は、計算量である。

終わらない処理は珍しくない。条件が少し間違っているだけで、ループは止まらなくなる。組み合わせをすべて試す処理は、入力が少し大きくなっただけで急に重くなる。

だから、実行時間や処理量に上限を置く。一定の時間を超えたら打ち切る。外から止められるようにしておく。

この四つを縛ることで、目指す状態が見えてくる。

中で失敗しても、外は無事である。

これが、サンドボックスの基本である。

禁止するだけでは仕事にならない

ただし、すべてを閉じればよいわけではない。

何も読めない。何も書けない。どこにもつながらない。すぐ止まる。これでは安全かもしれないが、仕事にならない。

エージェントには、何かをさせたい。表を整形させたい。文章から情報を抜き出させたい。決まった場所からデータを取ってこさせたい。コードを試しに走らせ、結果を見て修正させたい。

そのためには、能力を渡す必要がある。

ただし、渡し方が重要である。

基本は、まず禁止することだ。何でもできる状態から少しずつ制限するのではない。何もできない状態から、必要なものだけを一つずつ開ける。

このファイルは読んでよい。この一時ディレクトリには書いてよい。この外部サービスには、この決められた窓口を通してだけ問い合わせてよい。実行時間はここまで。メモリはここまで。

こうして、許可を積み上げる。

これは、普通のオペレーティングシステムが長く扱ってきた問題と似ている。

プログラムにいきなり機械全体を渡すのではない。メモリの境界を作る。ファイルへの権限を分ける。外界に触るときは、決められた入口を通らせる。あるプログラムの失敗が、他のプログラムや本体に広がらないようにする。

エージェントの運行时でも、同じ発想が必要になる。

違うのは、動かすものが、人間が事前に十分確認したプログラムだけではないことだ。エージェントは、その場でコードを書き、その場で試す。何を実行するかが、実行直前まで確定しない。

だからこそ、最小限の権限から始める設計が重要になる。

エージェントに自由を与えるには、まず境界を作らなければならない。境界があるから、その中で動かせる。

隔離は程度の問題である

ここまで書くと、サンドボックスを置けば安全になるように見えるかもしれない。

だが、そこまで単純ではない。

隔離は難しい。

どこまで縛れば十分なのかは、仕事の内容によって変わる。短い計算だけなら厳しくできる。外部の情報を取りに行く仕事なら、何らかの通信が要る。大量のデータを扱うなら、メモリや時間の上限も広げざるを得ない。

締めすぎれば、エージェントは役に立たない。緩めすぎれば、危険が残る。

しかも、上限の値はいつも明快に決められるわけではない。メモリをどれだけ許すか。何秒で打ち切るか。どの通信を許すか。どのファイルを渡すか。これらは、実際の仕事を見ながら調整する部分が多い。

だから、隔離は「あるかないか」ではなく、「どれだけ縛れているか」として見るほうがよい。

低い危険の作業なら、簡単な囲いで足りるかもしれない。重要な情報を扱う作業なら、より強い囲いが必要になる。外部への副作用がある作業なら、実行環境だけでなく、承認や記録や取り消しの仕組みも考えなければならない。

また、一つの壁だけを信じきるのも危うい。

ファイルを縛る。ネットワークを縛る。資源の上限を置く。実行後に環境を捨てる。外部に出る操作は別の窓口で検査する。こうした複数の壁を重ねることで、一つが破れても全体がすぐには崩れないようにする。

完璧な隔離を前提にしない。

失敗するかもしれないものとして設計する。

この態度が、エージェントの実行環境では重要になる。

Agentic OS への含意

Agentic OS という見方で考えると、サンドボックスは単なる安全機能ではない。

それは、エージェントに行動を許すための基礎である。

モデルは考える。だが、エージェントは動く。動くなら、実行の場所が要る。実行の場所には、境界が要る。境界がなければ、行動の失敗がそのまま利用者の環境へ広がる。

オペレーティングシステムは、長いあいだ、似た問題に向き合ってきた。複数のプログラムを同じ機械の上で動かすために、メモリを分け、権限を分け、入口を決め、暴走を止める仕組みを作ってきた。

エージェントの運行时でも、同じ種類の問題が立ち上がる。

自分でコードを書いて実行する。道具を呼ぶ。外部のサービスに触れる。長く走る。こうしたエージェントほど、手を縛った実行環境が必要になる。

ここでの目的は、エージェントを小さく閉じ込めることではない。

むしろ逆である。安全に動ける範囲を作ることで、エージェントに実際の仕事を任せられるようにする。どこまでなら失敗してよいかを決めることで、試行錯誤を許せるようにする。

実行を隔離する。触れてよい範囲を決める。資源の上限を置く。暴走を止める。必要な能力だけを、管理された窓口から渡す。

これが、運行时における最初の関門である。

安全というテーマは、この先でも何度も出てくる。エージェントが外の世界に強く触れるほど、安全は一つの部品ではなく、全体を横断する層になる。

ただ、その入口にあるのは、とても素朴な考え方だ。

信用していないコードを、信用しなくてよい場所で動かす。

次回は、運行时のもう一つの柱に進む。エージェントは手を動かすだけではない。途中の状態を持ち、過去の結果を参照し、次の行動につなげる。

つまり、記憶の話に入る。

← 一覧へ