# 影片筆記:在 MacOS 上给 OpenAI Agents API 接一个沙箱:apple-sandbox 开源实测 ## ⚠️ 可先使用,仍有待修正項目 本筆記已完成可閱讀的逐字稿與時間跳轉;下列為待處理問題,建議播放原片確認。 - 待修正:逐字稿全文快速校讀未完成(已保留自動字幕/原始逐字稿並繼續生成筆記。;未完成的全文速讀項目可在精進模式回聽確認。) ## 一句話總結 影片介紹並實測了開源專案 `apple-sandbox`,該專案利用 Apple 開源的 `container` 工具與 `Virtualization.framework`,在本地 Mac 電腦上為 OpenAI Agents API 的 `self_hosted` 模式啟動獨立的輕量級 Linux 虛擬機,實現了無需雲端帳號、公网地址或 Docker 的本地隔離執行環境。 ## 核心重點 1. **本地隔離架構**:`apple-sandbox` 基於 Apple Silicon Mac 的 `Virtualization.framework`,為每個 Session 啟動獨立的輕量級 Linux 虛擬機,而非像 Docker 那樣共享內核。 2. **Application-managed 模式**:採用此啟動方式,應用端主動創建 Session 並啟動算力,執行器(`exec-server`)主動通過 WebSocket 出站連接 OpenAI,無需 OpenAI 推送 Webhook 通知。 3. **無縫文件存取**:透過目錄掛載機制,本機 `sandboxes` 目錄下的文件直接映射為虛擬機內的 `/workspace`,實現本機寫入即虛擬機讀取,無需額外的上傳下載接口。 4. **資源清理機制**:不依賴輪詢 OpenAI 狀態,而是依賴 `exec-server` 在連接關閉後自動退出的特性,透過 `prune` 命令清理已停止的容器。 5. **安全與限制**:目前僅支援 Apple Silicon Mac,出站網路未做白名單限制,且目前僅提供 CLI 工具,無官方 SDK。 ## 詳細大綱 ### 一、 專案介紹與核心架構 * **專案目標**:讓 OpenAI 的 Agents API 支援 `self_hosted`(自託管)執行環境。 * **技術基礎**: * 使用 Apple 官方開源的 `container` 工具。 * 基於 macOS 的 `Virtualization.framework`。 * 與 Docker 的區別:Docker 共享 Linux 內核,Apple container 為每個容器啟動獨立的輕量級 Linux 虛擬機。 * **架構分層**: 1. **硬體層**:Apple Silicon Mac。 2. **系統層**:Apple container 服務(透過 `container system start` 啟動)。 3. **執行器層**:基於 Node 22 的精簡版鏡像,安裝 CA 證書與 `codex` npm 包,執行 `codex exec-server`。 4. **CLI 層**:`apple-sandbox` 命令行工具(Go 語言編寫,無常駐進程/守護程序)。 * **目錄掛載機制**: * 本機 `sandboxes` 目錄下的 Session 子目錄直接掛載為虛擬機內的 `/workspace`。 * 文件進出無需上傳/下載接口,本機寫入即為虛擬機讀取,虛擬機寫入即為本機可讀。 ### 二、 與 OpenAI Agents API 的協作機制 * **啟動模式對比**: * **Webhook-managed**:典型雲端部署(如 Cloudflare),OpenAI 透過帶簽名的 Webhook 推送事件通知啟動算力,執行器再建立 WebSocket 連接。 * **Application-managed**:`apple-sandbox` 採用此模式。應用創建 Session 時直接獲取 `environment.id` 和 `remote_url`,同步啟動算力,無需等待 OpenAI 通知。 * **連接流程**: 1. 應用使用普通 API Key 創建 `self_hosted` 類型 Session,獲取 `session ID`、`environment.id` 和 `remote_url`。 2. 在 OpenAI 平台創建受限的 API Key,用於註冊執行器。 3. 執行 `apple-sandbox run`,將受限 API Key 注入環境變數 `OPENAI_EXECUTOR_API_KEY`。 4. 虛擬機內的入口腳本將受限 Key 轉換為 `CODEX_API_KEY` 並啟動 `exec-server`。 5. `exec-server` 使用 API Key 主動向 `remote_url` 發起 WebSocket 連接完成註冊。 6. OpenAI 標記 Session 為活躍,後續任務由 OpenAI 下發命令,虛擬機在 `/workspace` 執行並回傳結果。 * **關鍵特性**: * `apple-sandbox` CLI 本身不與 OpenAI 通信,僅負責啟動虛擬機。 * 數據通道始終為執行器主動出站(Outbound),OpenAI 不需反向連接用戶機器。 * 缺少公网地址僅影響「提前收到 Webhook 通知」,不影響數據傳輸。 ### 三、 狀態管理與資源清理 * **Session 狀態週期**: * `Created`:容器創建。 * `Registering`:啟動 `exec-server` 並註冊。若失敗則進入 `Rejected` 並停止。 * `Connected`:註冊成功,等待命令。 * `Executing`:執行 OpenAI 下發的命令。 * `Reconnecting`:WebSocket 掉線,`exec-server` 自動重連。 * `Stopped`:OpenAI 徹底關閉 Session,`exec-server` 退出,容器停止。 * `Removed`:透過 `rm` 或 `prune` 刪除。 * **清理機制**: * 不輪詢 OpenAI,而是依賴 `exec-server` 在連接徹底關閉後退出的特性。 * 使用 `prune` 命令檢查已停止的容器,清理超過指定時間(如 `--older-than 1h`)的 Session。 * 確保不會誤刪正在運行的容器。 ### 四、 端到端實作演示 * **前置準備**: * 平台:僅支援 Apple Silicon Mac (`darwin_arm64`)。 * 安裝:`brew install --cask container` 及下載 `apple-sandbox` 二進制至 `~/.local/bin`。 * 檢查:執行 `apple-sandbox doctor` 確認環境(Apple Silicon、Hypervisor、container 服務狀態等)。 * **構建與啟動**: * 執行 `apple-sandbox build` 構建執行器鏡像(拉取 Node 鏡像、安裝證書與 codex)。 * 透過 API 創建 Session:POST 至 `/v1/agents/sessions`,設定 `environment` 為 `self_hosted`,工作目錄為 `/workspace`。 * 獲取響應中的 `ID`、`environment.id` 和 `remote_url`。 * **任務執行**: * 執行 `apple-sandbox run` 並傳入上述三個參數。 * 驗證:透過 `container exec` 進入虛擬機確認為 Linux 內核。 * 文件處理:在本機 `sandboxes` 目錄放置 CSV 文件,虛擬機直接讀取(註:`self_hosted` 類型不支援 `environment.files` 字段,需依賴掛載)。 * 提交任務:POST 至 Session 的 events 接口,觸發 Agent 執行 Python 腳本處理數據並寫入 `/workspace/outputs/summary.json`。 * 結果驗證:本機直接讀取生成的 JSON 文件,確認結果正確。 * **清理**: * 執行 `apple-sandbox stop` 和 `rm` 刪除容器。 * 使用 DELETE 請求刪除 OpenAI 端的 Session。 * 或使用 `prune --dry-run` 預覽並批量清理舊 Session。 ### 五、 注意事項與限制 * **網路安全**:目前出站網路未做白名單限制(僅內網或全開放),建議暫勿運行不受信任的任務。 * **SDK 支援**:目前僅提供 CLI,無 TypeScript 或 Python SDK,需自行封裝子進程調用。 * **狀態推斷風險**:`prune` 依賴「容器停止即代表 Session 結束」的推斷,目前雖無反例,但連接中到停止的轉換過程尚未被單獨觀測過。 ## 工具 / 模型 / 名詞整理 * **OpenAI 相關**: * Agents API * OpenAI 官方托管沙箱環境 * codex exec-server (執行器) * codex (npm 包) * API Key (普通 API Key, 受限 API Key) * `api.openai.com` * `/v1/agents/sessions` * `environment.files` * Artifacts 接口 * **Apple 相關**: * Apple Silicon Mac * container (Apple 官方開源工具) * Virtualization.framework * Hypervisor * **第三方/開源專案**: * `apple-sandbox` (專案名稱) * Go 語言 * Docker * Cloudflare (提及作為 Webhook 方案的參考實現) * Vercel * Modal * GitHub (sugarforever/apple-sandbox) * brew (Homebrew) * **技術與協議**: * OCI 容器 * WebSocket * Webhook * Linux 內核 * Node 22 * CA 證書 * Python * CSV * JSON ## 操作流程整理 1. **環境準備**: * 確認硬體為 Apple Silicon Mac。 * 安裝 Apple `container` 工具:`brew install --cask container`。 * 下載並安裝 `apple-sandbox` CLI 至 `~/.local/bin`。 * 執行 `apple-sandbox doctor` 檢查環境完整性。 2. **構建執行器鏡像**: * 執行 `apple-sandbox build`。 * 系統會拉取 Node 鏡像,安裝 CA 證書與 `codex` npm 包。 3. **創建 Session**: * 使用普通 API Key,POST 請求至 `/v1/agents/sessions`。 * 設定 `environment` 為 `self_hosted`,工作目錄為 `/workspace`。 * 從響應中獲取 `session ID`、`environment.id` 和 `remote_url`。 4. **啟動沙箱**: * 在 OpenAI 平台創建受限 API Key。 * 執行 `apple-sandbox run`,傳入 `session ID`、`environment.id`、`remote_url` 及受限 API Key。 * CLI 啟動虛擬機,內部腳本啟動 `exec-server` 並主動連接 OpenAI。 5. **執行任務**: * 將數據文件(如 CSV)放入本機對應的 `sandboxes` 目錄。 * 透過 API 向 Session 提交事件(Events),觸發 Agent 執行腳本。 * Agent 在虛擬機 `/workspace` 執行並寫入結果(如 JSON)。 6. **獲取結果與清理**: * 在本機 `sandboxes` 目錄直接讀取生成的結果文件。 * 執行 `apple-sandbox stop` 或 `rm` 刪除容器。 * 使用 `prune` 命令批量清理過期 Session。 ## 值得注意的限制或風險 1. **硬體限制**:僅支援 Apple Silicon Mac (`darwin_arm64`)。 2. **網路安全**:目前出站網路未做白名單限制,建議暫勿運行不受信任的任務。 3. **開發者體驗**:目前僅提供 CLI 工具,無 TypeScript 或 Python SDK,開發者需自行封裝子進程調用。 4. **狀態推斷風險**:`prune` 命令依賴「容器停止即代表 Session 結束」的推斷,若連接中到停止的轉換過程出現異常,可能導致清理邏輯誤判。 5. **API 兼容性**:`self_hosted` 類型不支援 `environment.files` 字段,若使用該字段會返回 400 錯誤,需依賴目錄掛載機制存取文件。 ## 逐字稿辨識疑點 * **gpt-6-astra**:逐字稿中演示時選擇的模型為 `gpt-6-astra`。目前 OpenAI 公開模型列表中無此標準名稱,可能為內部測試模型、口誤或聽寫錯誤。 * **codex exec-server**:逐字稿多次提及此名稱。OpenAI 官方文件通常稱之為 "Executor" 或 "Code Interpreter" 相關組件,具體組件名稱需查證是否為 `codex` 專案內的特定服務名稱。 * **Apple container 工具**:逐字稿稱 Apple 去年開源了 `container` 工具。需查證 Apple 官方是否確實以該名稱開源此工具,或是否為其他專案(如 `containerd` 或 Apple 內部的某個專案)的誤稱。 * **environment.files 返回 400**:逐字稿稱在 `self_hosted` 類型中,使用 `environment.files` 字段會返回 400 未知參數。需查證 OpenAI Agents API 文件是否確實如此規定,或是否為特定版本的行為。 * **prune 命令的參數格式**:逐字稿中提及 `prune --older-than 1h` 以及 `prune --older`。需確認該 CLI 工具的實際參數格式是否一致。 ## 可延伸追問 1. `apple-sandbox` 專案的開源地址與貢獻指南為何? 2. 若需支援非 Apple Silicon 架構(如 Intel Mac 或 Linux),架構上需要如何調整? 3. 如何為 `apple-sandbox` 開發官方 SDK 以簡化集成流程? 4. 針對出站網路未做白名單的限制,未來版本是否有計畫加入網路過濾機制? 5. `gpt-6-astra` 是否為 OpenAI 內部測試模型,或為影片講者的口誤?