文章來源|字節跳動 Web Infra x veFaas 團隊
項目地址|github.com/agent-infra/sandbox
引言:
AI Agent 在執行復雜任務時,常需在瀏覽器、代碼執行、文件系統之間切換。傳統多沙箱方案面臨環境割裂、數據搬運、鑑權複雜等問題。AIO Sandbox 通過一個 Docker 鏡像整合所有能力,提供統一文件系統與鑑權,並支持鏡像定製,提升了 Agent 任務執行與交付效率。
01 背景
隨着 LLM 的持續演進,AI 的應用形態經歷了三代躍遷:
- Chatbot:對話式交互,回答問題
- Copilot:輔助協作,提升效率
- Agent:自主執行,完成任務
Agent 能夠自主感知環境、規劃步驟、調用工具,能夠像人類一樣操作計算機:自動瀏覽網頁收集信息、生成並運行代碼分析數據、執行系統命令管理文件,甚至通過可視化界面完成複雜的多步驟操作。這種能力使 Agent 的交付成果接近甚至超越人類專業水準。
痛點
- 🧩 環境割裂:多個單功能沙盒(如 E2B 支持代碼執行,Browserbase 支持瀏覽器)迫使 Agent 通過 NAS/OSS 跨沙箱傳輸數據,增加延遲與複雜度。如:深度研究 Agent 完成『將一篇論文 Paper 做成 PPT』需在多沙箱間交換數十個中間文件(JSON 配置、圖表圖片、預覽截圖等),增加整個 Agent 系統複雜度和開銷。
不同功能沙箱共享協作
- 🎁 定製困難:不同類型的 Agent 需要預裝不同的技術棧,傳統沙箱提供統一的預裝環境,既無法滿足所有 Agent 的個性化需求。
不同 Agent 在沙盒環境的預裝包不同
- 🔒 安全隔離難:既要讓 Agent 拿到真實系統能力(網絡、文件、瀏覽器、GPU),又要強隔離避免越權與數據外泄。
- 🖥️ 可視化交互困難:複雜 Agent 任務需要人工接管,功能沙箱需要集成 VNC、Terminal、VSCode 保持一致體驗。分辨率切換、截圖與 GUI 視覺操作。
- 🌐 瀏覽器環境複雜度高:反自動化與指紋風控,CDP 不穩定性、帶用户名密碼的代理支持不完善、GUI 操作缺失。
一台配置完善的電腦能顯著提升人類的辦公效率;同樣,一個功能強大的沙箱環境也能提升 Agent 的任務質量與執行速度。
02 介紹
一句話介紹:AIO Sandbox 在一個沙盒內集成瀏覽器、代碼執行、終端、可視化接管、正反向代理、MCP、鑑權等基礎功能,可根據需求進行沙盒環境定製,讓不同的 Agent“在一個環境容器內中更高效地完成任務”。
- 官網:sandbox.agent-infra.com
- Github:github.com/agent-infra/sandbox
- API:sandbox.agent-infra.com/api
- 論文:arxiv.org/pdf/2509.02544#S2.SS2
AIO(All-in-One)沙箱
特性
- 📦 開箱即用:通過/mcp 協議直連沙箱能力,同時提供 API / SDK 定製沙箱工具集。
- 🚀 秒啓動:沙盒全服務啓動在秒級完成,預緩存/冷啓動後達到毫秒級拉起。
- 🌈 定製化:各垂直場景的 Agent 需配套領域工具與依賴;AIO 以統一鏡像基座,用約定式路由和服務配置支持按需擴展。
- 🌐 瀏覽器:集成 Web Infra 的 RS 輕量內核,提供 CDP、截圖、純視覺 GUI 操作、Proxy 代理配置。
- 🔄 人工接管:提供 瀏覽器 VNC、Code Server、Terminal,支持任務中途人工接管與調試。
- 📡 代理與轉發:支持帶賬密的正向代理;將 {port}-{domain} 泛域名或 /proxy|/absproxy/{port} 路徑映射到沙箱內服務(便於預覽/演示)。
- 🔒安全鑑權:JWT Bearer 訪問控制;對無法攜帶 Header 的鏈接提供短時票據(Short-Lived Ticket)。
AIO Sandbox
03 示例
| 指令 | 回放 | 使用的AIO功能 |
|---|---|---|
| Help me design an interesting website to introduce elementary school children to sauropod dinosaurs of the Jurassic and Cretaceous periods. I hope the site is in a cartoon style.
幫我設計一個有趣的網站,為在上小學的孩子介紹侏羅紀和白堊紀時期的蜥腳類恐龍。希望網站是卡通風格的。 |
Replay
|
- 瀏覽器操作
- DOM 操作( /v1/browser/info)
- 截圖( /v1/browser/screenshot)
- 視覺操作( /v1/browser/actions)
- 執行命令( /v1/shell/exec)
- 文本編輯器工具( /v1/file/str_replace_editor)
- 端口轉發(反向代理) |
| Search Bytedance Seed1.6 News And Deploy Web
搜索關於字節跳動Seed1.6模型的新聞,然後以現代風格編寫一個網頁並部署 |
Replay
|
同上 |
| Based on this picture, please find the latest information on the Internet and design a modern website for it.
根據這張OSWorld圖片,請在互聯網上查找最新信息併為其設計一個現代化的網站。 |
Replay
|
同上 |
| Goto: https://poki.com/zh/g/2048, start play
玩Poki 2048遊戲 |
Replay
|
同上 |
更多見:https://seed-tars.com/showcase/ui-tars-2
04 快速上手
雲端
一鍵部署 All-in-One Sandbox 應用--函數服務-火山引擎:
https://www.volcengine.com/docs/6662/1851199
雲函數部署 AIO Sandbox
本地
前置需要安裝 Docker(見文末參考1),一鍵本地啓動:
docker run --rm -it -p 8080:8080 enterprise-public-cn-beijing.cr.volces.com/vefaas-public/all-in-one-sandbox:latest
本地 Docker 啓動
05 系統架構
整體
AIO Sandbox 面向 Agent 提供 Browser、File、Shell、Code 等基礎能力,提供可擴展性支持開發者根據 Agent 需求組合與定製專屬沙箱(如 AIO Sandbox for 移動端/醫療/法務/金融/科研)。
沙箱定製程度依次遞增:
- Standard(開箱即用):通過
/mcp接入點對 Agent 即插即用,適用於快速 PoC Agent 驗證。 - Custom Toolset(工具 / Skills 擴展):不改鏡像,基於 SDK / API 增加或編排工具(如增加
web_search搜索);同時擴展出 Skills 實現特定沙盒任務的自動化處理。 - Custom Image(定製鏡像):基於
FROM aio.sandbox基礎鏡像,安裝特定的基礎依賴(如多媒體/圖像處理等),掛載自定義服務(例如/custom_tools/ocr圖像識別)。
Sandbox 可擴展架構
基礎組件
AIO Sandbox 組件圖
瀏覽器
面向 Agent 的瀏覽器環境,核心在於提供出 CDP 和 VNC,主流 Browser Use 框架都可以直接使用;
AIO 提供了基於 x11 的瀏覽器 GUI 視覺操作接口,可以與 CDP 方式組合出更高效、更低風控率的 Browser Use 方案。
AIO Sandbox Browser 架構
CDP
CDP (Chrome Devtools Protocol)是一種用於與 Chrome 或 Chromium 瀏覽器通信的協議,通過 WebSocket 提供瀏覽器控制 API,可以執行導航與加載、DOM 操作、JS 執行/調試、網絡攔截與模擬、截圖與渲染、安全與權限等。
為更直觀瞭解,以下示例是用 CDP 發起一個 navigate 頁面導航指令:
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome' \
--disable-gpu \
--user-data-dir=./test \
--remote-debugging-port=9222 \
https://www.chromestatus.com
訪問http://localhost:9222/json/version,其中webSocketDebuggerUrl就是 CDP 地址:
$ curl http://localhost:9222/json/version
{
"Browser": "Chrome/141.0.7390.66",
"Protocol-Version": "1.3",
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36",
"V8-Version": "14.1.146.11",
"WebKit-Version": "537.36 (@95681a3c3d516c397b75ff45b8980c1088666775)",
"webSocketDebuggerUrl": "ws://localhost:9222/devtools/browser/a6c5f19f-5d24-4bed-ba08-9c15cf5aeedb"
}
與 CDP 建立 WebSocket 連接後,就可以執行瀏覽器指令:
Navigate www.toutiao.com
注:AIO Sandbox 不直接暴露 CDP 接口 _/json/version_,而是通過 uvicorn 服務中轉 CDP 並增加了心跳檢測,避免出現 ws 斷連問題。
GUI 視覺操作
不同於基於 CDP 的截圖,視覺的截圖 /v1/browser/screenshot 是帶 Tabs(即整個瀏覽器窗口),操作也是面向整個瀏覽器窗口。
GUI 瀏覽器截圖(Tabs)
基於 CDP 的頁面截圖(Page)
不同於 CDP 的瀏覽器操作,視覺操作/v1/browser/actions 上模擬人類行為進行點擊、輸入、滑動等操作,可以減少目標網站的風控策略。
統一動作空間
將 GUI 操作抽象為可組合的最小原子動作,如移動鼠標、點擊、拖動、滾動、按鍵、輸入文本,以及額外的工具函數如等待,儘可能對齊 VLM 視覺模型在執行實際動作的一致性。
| action_type | 描述 | 必需參數 | 可選參數 |
|---|---|---|---|
| MOVE_TO | 移動鼠標到指定位置 | x, y | - |
| MOVE_REL | 移動當前鼠標的相對位置 | x_offset, y_offset | - |
| CLICK | 點擊操作 | - | x, y, button, num_clicks |
| MOUSE_DOWN | 按下鼠標按鈕 | - | button |
| MOUSE_UP | 釋放鼠標按鈕 | - | button |
| RIGHT_CLICK | 右鍵點擊 | - | x, y |
| DOUBLE_CLICK | 雙擊 | - | x, y |
| DRAG_TO | 拖拽到指定位置 | x, y | - |
| DRAG_REL | 當前鼠標拖拽的相對位置 | x_offset, y_offset | - |
| SCROLL | 滾動操作 | - | dx, dy |
| TYPING | 輸入文本 | text | - |
| PRESS | 按鍵 | key | - |
| KEY_DOWN | 按下鍵盤按鍵 | key | - |
| KEY_UP | 釋放鍵盤按鍵 | key | - |
| HOTKEY | 組合鍵 | keys (數組) 例如:["ctrl", "c"] | - |
| WAIT | 等待 | duration 時間(秒 s) | - |
接管
當 Browser Use 遇到要登錄的情況,一般需要人工接管,需要提供可交互的瀏覽器界面,目前有兩種做法:
1.VNC 接管:AIO Sandbox 提供 /vnc/index.html 頁面,用户可直接交互。
2.前端通過 CDP 連接,在 Canvas 上實時重繪完整瀏覽器界面;我們把前端部分封裝了一個組件 @agent-infra/browser-ui。
兩種接管方式的差異大致如下:
| 對比維度 | VNC | Canvas + CDP(Chrome DevTools Protocol) |
|---|---|---|
| 技術原理 | 遠程桌面協議,傳輸整個屏幕像素 | 通過 CDP 控制瀏覽器,Canvas 渲染內容 |
| 傳輸協議 | RFB (Remote Framebuffer) | WebSocket + CDP |
| 傳輸內容 | 完整瀏覽器畫面(有 Tabs) | 僅瀏覽器當前 page 內容(默認沒有 Tabs,可以單獨實現) |
| 帶寬佔用 | 高(10-50 Mbps) | 低(1-5 Mbps) |
| 延遲 | 較高(50-200ms) | 較低(10-50ms) |
| 穩定性 | 不易斷連 | 易斷連,需要手動增加與 CDP 心跳,避免斷連 |
| CPU佔用 | 高(桌面編碼) | 低(僅瀏覽器渲染) |
| 內存佔用 | 高(需要完整桌面環境) | 低(僅瀏覽器進程) |
| 控制範圍 | 整個瀏覽器 | 僅瀏覽器內部頁面 |
| 自動化能力 | 基礎(鼠標鍵盤模擬) | 強大(DOM操作、網絡攔截、JS注入等) |
| 多窗口支持 | ✅ 支持 | ❌ 僅單個瀏覽器窗口 |
| 文件操作 | ✅ 可以操作本地文件 | ❌ 受瀏覽器沙箱限制 |
命令行解釋器
對於 Coding Agent,大部分任務都可以通過命令行執行完成。設計 Shell 模塊時,以 OpenHands 的 CmdRunAction(見文末參考2)為執行引擎,配合 tmux,實現多會話(multi-session)執行能力。
文件操作
文件/代碼編輯只需要兩個工具就足夠:
- 文件增改查:封裝文件讀取/寫入/列目錄/新建/上傳/下載等基礎 I/O,配合路徑校驗與權限控制,覆蓋通用文件操作場景。
- 文本編輯器:實現面向模型的細粒度編輯工具 str_replace_editor(見文末參考3),支持:
- view(查看文件或目錄,含行範圍)
- str_replace(精確字符串替換)
- insert(按行插入,舊版支持)
- undo_edit(撤銷)
代碼執行
綜合權衡語言覆蓋與鏡像體積,使用 Sandbox Fusion(見文末參考4) 裏的 Python 3.10/3.11/3.12 與 Node.js 22 運行時,併為代碼執行提供一體化的安全隔離環境。
MCP Servers 聚合器
通過統一入口 /mcp 聚合多個 MCP Server(例如 chrome-devtools-mcp),支持參數級過濾,並可為工具名添加前綴(namespacing)。
/mcp 支持 MCP Servers 過濾
按 search 過濾 MCP Servers,後續將擴展標籤(tags)與類別(category)等多維過濾,減少冗餘調用並降低模型 token 開銷。
代理
在 Agent 沙箱裏,一般涉及兩類場景,分別對應正反向代理:
- 正向代理:Browser Use Agent 可訪問私有/全球網絡
- 反向代理:Coding Agent 在沙箱內開發的服務對外開放,供用户側預覽
正向代理
使用 TinyProxy 代理服務器,繞過地理限制、訪問受限內容或在企業內網中提供安全訪問。
AIO Sandbox 正向代理原理
為什麼 Chrome 有 --proxy-server 指定代理,為什麼要引入 TinyProxy 代理服務器?
在 Chromium 官方文檔(見文末參考5)寫明不會使用任何嵌入在代理設置裏的用户名/密碼(例如http://user:pass\@host:port這種),認證要走單獨的質詢彈窗,影響整個 Browser Use 使用(如下圖):
帶用户名密碼代理會出現彈窗
反向代理
AIO Sandbox 反向代理原理
提供兩種訪問 Sandbox 內部服務端口的方法:
- subdomain 泛域名轉發(推薦):只要滿足 _${port}-${domain}_ 的域名格式,都會被轉發到沙盒內的端口上。
- subpath 子路徑轉發:會遇到非常多問題:對於路由敏感服務(如前端項目)會因為額外的 /proxy|absproxy/${端口} 路徑造成資源匹配 404。
鑑權
Agent 在沙箱裏會產生用户數據,為了在不侵入、不修改任何既有業務路由配置、同時不增加未來擴展的路由配置的心智負擔的前提下,實現 AIO Sandbox 全局統一鑑權,在內部 Nginx 網關層設計了“非對稱加密+JWT”反向代理架構來實現鑑權:
如何開啓(一次配置)
- 生成密鑰對
openssl genrsa -out private_key.pem 2048
openssl rsa -in private_key.pem -pubout -out public_key.pem
echo "密鑰對生成完畢!"
- 啓動服務(帶公鑰開啓鑑權),使用環境變量 JWT_PUBLIC_KEY
export JWT_PUBLIC_KEY=$(cat public_key.pem | base64)
JWT_PUBLIC_KEY="${JWT_PUBLIC_KEY}"
簽發 JWT
業務服務用私鑰生成一個有效期為 1 小時的 JWT,以下是簡化的腳本來生成 JWT,實際中業務後端應使用成熟的 JWT 庫:
# 這是一個簡化的腳本來生成JWT,實際中業務後端應使用成熟的 JWT 庫 base64url_encode() { openssl base64 -e -A | tr '+/''-_' | tr -d '='; }
header='{"alg":"RS256","typ":"JWT"}'
exp_time=$(($(date +%s) + 3600))
payload="{"exp":${exp_time}}"
to_be_signed="$(echo -n "$header" | base64url_encode).$(echo -n "$payload" | base64url_encode)"
signature=$(echo -n "$to_be_signed" | openssl dgst -sha256 -sign private_key.pem | base64url_encode)
jwt="${to_be_signed}.${signature}"echo "JWT已生成: ${jwt}"
使用
- Header 鑑權
curl --silent -X GET "http://localhost:8080/v1/sandbox" \
-H "Authorization: Bearer ${jwt}"
- 短時票據鑑權示例(以 VNC 頁面訪問為例):直接訪問無法通過加 Header 方式完成鑑權,只能通過 ?ticket=_ 票據以 query 參數方式發起訪問。
- 使用 JWT 從通用端點獲取票據(默認有效期是 30s,要增加通過 TICKET_TTL_SECONDS 環境變量配置)
echo"使用JWT換取通用的一次性票據..."
ticket_response=$(curl --silent -X POST "http://localhost:8080/tickets" \
-H "Authorization: Bearer ${jwt}")
ticket=$(echo"$ticket_response" | jq -r .ticket)
expires=$(echo"$ticket_response" | jq -r .expires_in)
echo"獲取成功!票據: ${ticket}, 有效期: ${expires}秒"
- 客户端構建並使用 VNC URL:現在,就可以使用獲取到的 ${ticket} 變量來構建 VNC URL 併發起訪問了。
# Bash腳本模擬客户端拼接URL
vnc_url="http://localhost:8080/vnc/index.html?ticket=${ticket}&path=websockify%3Fticket%3D${ticket}"
echo"客户端構建的最終URL: ${vnc_url}"
# 模擬訪問 (實際應在瀏覽器中進行)
# curl -I "${vnc_url}"
06 擴展與生態
定製鏡像
在 AIO 裏,會按約定目錄方式,自動掛載服務進程(supervisord)和服務路由(Nginx)
- 服務進程目錄:/opt/gem/supervisord/.conf
- 路由目錄:/opt/gem/nginx/*.conf
如果在 AIO 鏡像基礎上定製服務和路由,可參考以下鏡像代碼:
FROM enterprise-public-cn-beijing.cr.volces.com/vefaas-public/all-in-one-sandbox:latest
# ----------------------
# 安裝額外系統依賴(若有)
# installed path: /usr/bin/*
# ----------------------
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends \
${your_system_dep} \
--no-install-recommends; \
# clean up
apt-get clean && \
rm -rf /var/lib/apt/lists/*;
# ----------------------
# npm 安裝(若有)
#
# ----------------------
RUN npm i -g ${your_npm_package}
# ----------------------
# python pip 安裝(若有)
# installed path: /usr/local/bin/*
# ----------------------
RUN pip install ${your_python_package}
# 添加自定義 Server 服務
COPY ./supervisord.agent_server.conf /opt/tiger/run/supervisord/agent_server.conf
# 綁定 Nginx 路由
COPY ./nginx.agent_server.conf /opt/gem/nginx/nginx.agent_server.conf
# # 若不需要 AIO 裏的服務,可進行刪除,例如 Code Server
# ## 刪除 Code Server 進程和路由
# RUN rm -rf /opt/gem/supervisord/supervisord.code_server.conf
# ## 刪除 Code Server 路由
# RUN rm -rf /opt/gem/nginx/code_server.conf
SDK 集成
藉助 fern(見文末參考6)將 AIO Sandbox 裏的接口文檔直接轉成 Python / Go / Node.js SDK,以 Python 為例,幾行代碼串聯起 AIO Sandbox 裏的核心功能:
from agent_sandbox import Sandbox
client = Sandbox(base_url="http://localhost:8080")
# Execute Shell
shell_res = client.shell.exec_command(command="ls -la")
print(shell_res.data.output) # /home/gem
# Browser Screenshot
screenshot = client.browser.screenshot()
print(screenshot)
# Get Browser CDP
browser_info = client.browser.get_browser_info()
cdp_url = browser_info.data.cdp_url # ws://
# Read File
file_res = client.file.read_file(file="/home/gem/.bashrc")
print(file_res.data.content)
更多使用示例參考:agent-infra/sandbox#exampleshttps://github.com/agent-infra/sandbox/tree/62e910bae02239f69f749b16a1a78d8deb30c533/examples
browser-use
只需增加 4 行代碼接入社區的 browser-use(https://github.com/browser-use/browser-use):
browser-use + AIO Sandbox
完整代碼見:文末參考7
LangGraph-DeepAgents
LangGraph-DeepAgents + AIO Sandbox
完整代碼見:langgraph-deepagents#main.py
自定義工具集
可使用 API / SDK 來組合 Agent 所需要的高階工具集,例如 link_reader 給 url 地址返回頁面內容:
from openai import OpenAI
from agent_sandbox import Sandbox
import json
client = OpenAI(
api_key="your_api_key",
)
sandbox = Sandbox(base_url="http://localhost:8080")
tools = [{
"type": "function",
"function": {
"name": "link_reader",
"description": "渲染並讀取網頁,返回標題、正文與最終URL(基於CDP)。",
"parameters": {
"type": "object",
"properties": {
"url": {"type": "string", "format": "uri"},
"timeout_ms": {"type": "integer", "default": 30000}
},
"required": ["url"]
}
}
}]
asyncdeflink_reader(url: str, timeout_ms: int = 30_000) -> dict:
cdp_url = sandbox.browser.get_browser_info().cdp_url
asyncwith async_playwright() as p:
browser = await p.chromium.connect_over_cdp(cdp_url)
try:
page = await browser.new_page()
await page.goto(url, wait_until="networkidle", timeout=timeout_ms)
title = await page.title()
text = await page.evaluate("document.body.innerText || ''")
return {"final_url": page.url, "title": title, "text": text[:8000]}
finally:
await browser.close()
部署
目前最佳的公有云部署形態是函數計算,並基於 Sandbox 指定實例訪問能力:
一鍵部署 All-in-One Sandbox 應用--函數服務-火山引擎:
https://www.volcengine.com/docs/6662/1851199
火山引擎- 函數服務 - 一鍵部署 AIO
07 總結與展望
AIO Sandbox 提供一體化、可定製的基座環境(Agent Env),使 Agent 能在同一環境內完成瀏覽、執行代碼、運行命令與文件操作等多樣化任務,並支持根據不同 Agent 定製專屬的領域沙盒。這一沙盒體系也將伴隨 Agent 智能上限的提升與開發者創造力的激發,持續進化與擴展。
後續,我們將圍繞穩定性、可觀測性與生態集成持續打磨,不斷完善評測體系與最佳實踐,推動 AIO Sandbox 在更多大規模、高要求的 Agent 應用場景中實現穩健落地與高效運行。
附錄
名詞解釋
參考
- Docker:https://www.docker.com/get-started/
- CmdRunAction:https://github.com/All-Hands-AI/OpenHands/blob/2bbe15a329e35f5156cdafcbe63c3fd54978ff98/openhands/runtime/utils/bash.py#L494-L681
- str_replace_editor:https://docs.claude.com/zh-CN/docs/agents-and-tools/tool-use/text-editor-tool
- Sandbox Fusion:https://bytedance.github.io/SandboxFusion/
- Chromium 官方文檔:https://chromium.googlesource.com/chromium/src/%2B/HEAD/net/docs/proxy.md#proxy-credentials-in-manual-proxy-settings
- fern:https://buildwithfern.com/learn/sdks/overview/introduction
- 完整代碼:[https://github.com/agent-infra/sandbox/blob/b950470e6d70eabf9941b9a98a0affd15dd2e86c/sdk/python/examples/browser-use-integration/main.py
](https://github.com/agent-infra/sandbox/blob/b950470e6d70eabf9941b9a98a0affd15dd2e86c/sdk/python/examples/browser-use-integration/main.py) - UI-TARS-2 Technical Report: Advancing GUI Agent with Multi-Turn Reinforcement Learning:https://arxiv.org/pdf/2509.02544
- AIO Sandbox: All-in-One Sandbox for AI Agents & Developers:https://medium.com/coding-nexus/aio-sandbox-all-in-one-sandbox-for-ai-agents-developers-b0a5ca4cf2a8
- Agentic AI基礎設施實踐經驗系列(二):專用沙盒環境的必要性與實踐方案:
https://aws.amazon.com/cn/blogs/china/agentic-ai-sandbox-practice/ - Writing effective tools for AI agents—using AI agents:https://www.anthropic.com/engineering/writing-tools-for-agents
- Unifying the Computer Use Action Space:https://scrapybara.com/blog/unified-action-space