跳至主要內容
蒼時弦也
蒼時弦也
資深軟體工程師
發表於

Kobako:打造 AI 時代的沙盒

這篇文章是 Kobako 系列的一部分。

開始 Kobako 的開發已經有幾個月的時間,接下來也會在 COSCUP 分享這個專案,因為過程非常有趣,我認為很適合做一系列的更新,來介紹我怎麼開始「打造 AI 時代的沙盒」

到這篇文章撰寫為止,已經有 20 個左右版本發布,接下來我會盡可能按照時間順序,分享 Kobako 的演進,以及過程中做的決策。

未來需要什麼?

2026 年 4 月,出發到日本 RubyKaigi 前夕,正好 Harness Engineering(駕馭工程)變得熱門起來,裡面有許多不同的主題,其中一個比較少被關注,但剛好各大公司都默默做了一些解決方案的,就是沙盒(Sandbox)技術。

現有的方案很多,像是虛擬機器(Virtual Machine)、微型虛擬機器(microVM)、容器技術(Container)等都是選項,最大的差別在對環境的要求,越接近虛擬機器隔離性越好,但對小專案或者開發時的限制也越多。相較之下 WebAssembly 輕量很多,也被劃分在選項之一,讓我稍微記住這件事情。

RubyKaigi 在和人聊天時提到相關話題,我才想起來我對未來的判斷中,認為沙盒跟虛擬檔案系統(Virtual File System)大概會是關鍵之一,畢竟都是用於運行不被信任的程式碼,非常有效隔離、更容易確保安全的選項。

Ruby 有沙盒嗎?

在 RubyKaigi 期間我開始思考這個問題,結論是在對 AI 安全的情境下,很可能只有 ruby.wasm 符合條件,至少在 Harness Engineering 看到的候選條件中,幾乎都有相對強的隔離性,因此 WebAssembly 跟主程式記憶體隔離,內部跑獨立的虛擬機器的架構,更符合條件。

剛好該年度的 Code Party(由贊助商提供餐點和場地,跟開放原始碼專案作者協作)有 dRuby 專案的作者,帶大家體驗 drb 這個歷史悠久的標準功能,這個 Gem 巧妙的利用 Ruby 語言特性,在數百行左右的規模就讓 Ruby 能做到 RPC(Remote Procedure Call)。

 1# Client
 2class Proxy
 3  def method_missing(method, *args, **kwargs)
 4     raise if @target.respond_to(method)
 5     
 6     @server.send(method, *args, **kwargs)
 7  end
 8end
 9
10# Server
11server = Server.new
12object = Hash.new
13server.bind(object) # Use `object` to handle remote call

原理上,當我們用 TCP 監聽時,會收到「我要呼叫某某方法」這樣的請求,此時 dRuby 會直接對 Proxy 物件呼叫,因為方法不存在就會由 method_missing 捕捉,最後轉發給真正的物件。

實際運作還有不少細節,這只是展示概念,並不是真實的 dRuby 實作

這樣的機制非常巧妙,我們可以在幾乎不特地定義 Server 和 Client 兩側的介面,只需要借助 Ruby 語言能動態處理未知方法的特性,就讓物件可以在遠端運作。我也因此受到啟發,開始思考如何讓 Ruby 跟 ruby.wasm 輕鬆互動的方式。

想法不同

目前 ruby.wasm 是基於 WASI Preview 1(WebAssembly System Interface)為基礎,但這個版本把所有 I/O 能力鎖定,也因此想直接藉由 CRuby 原生的 dRuby 能力通訊,直接失效,也無法利用像是 WASI 的 stdio 來互動,因此一開始的想法就完全無法實現。唯一符合隔離條件的選項,剛好卡在最需要的通訊能力上,最後也只能走自己開發這條路。

實際上這也是合理的,市面上大部分的解決方案,像是虛擬機器、容器等技術,在設計初期要應付的都不是 AI 生成、不可信任的程式碼,大部分都還是可信任,或者可以控制的前提。

最大的不同是,我想走的路線更接近 Cloudflare 提出的 Code Mode,這本身就是沙盒技術的一種應用,LLM 寫出來的程式碼,就在 V8 的隔離環境執行,內建服務也能很自然的擴充。要讓 WebAssembly 裡的 Ruby 能呼叫外面的 Ruby,才能打造容易擴充和使用的沙盒。

在 RubyKaigi 期間,我同時思考有怎樣的替代方案可以達成目的。在搜集一些資訊後,選擇利用 WebAssembly 的 Host Linker(宿主連結器,讓 Guest 環境能呼叫 Host 註冊的函式)來處理,並且把 Kobako 的目標定調為「輕量」與「容易使用」來開發。

這是從我對使用 Ruby 開發軟體的期待,以及現況所得出最佳的情境,使用 WebAssembly 搭配 mruby 基本上可以非常輕量,使用 Host Linker 也很容易和 mruby 的 C API 一起協作,因為 Host 和 Guest 都使用 Ruby 對原本熟悉 Ruby 的開發者也會變得非常容易使用。

剩下的就是如何保持介面單純,以及輕量(啟動、呼叫都是流暢)要解決,這就開啟這長達數個月 Kobako 開發的旅程。

現在回頭看,這些選項本身都沒有問題,其他公司也都還在用,只是把我想要的條件拿去篩選之後,剩下 WebAssembly 搭配 mruby 最符合。