执行面:沙箱 vs 本机、网页访问与验证应对
执行面:沙箱 vs 本机、网页访问与验证应对
本文解读 Grok Bot 的「工作在哪里真正发生」:智能体自己的沙箱(box)、用户的电脑(本机)、后端隔离服务器、以及宿主(Electron)各自的职责边界;以及访问网页时在哪里执行、如何应对登录/人机验证。
面向对象:想理解「Grok Bot 到底在哪台机器上干活、为什么能访问各种网站」的读者。文中路径均为仓库内相对路径。
1. 执行面全景
Grok Bot 实际上有四类执行位置:
| 位置 | 工具 | 是谁的机器 | 典型用途 |
|---|---|---|---|
| Box(沙箱) | Shell / Read / AwaitShell / Computer | 智能体自己的 Linux 沙箱 | 默认干活的地方 |
| 用户本机 | ExternalShell / ExternalRead / AwaitExternalShell | 用户真实电脑 | 只处理用户自己的文件/环境 |
| 后端隔离服务器 | WebFetch / WebSearch / MCP connector | 服务端(协调器侧) | 公开网页抓取、OAuth 授权 API |
| Electron 宿主 | 协调器、local-exec-daemon、box 连接器 | 运行 App 的机器 | 编排、本地执行、审批 |
其中「后端隔离服务器」常被忽略但很关键:它既不是 box 也不是用户本机。
2. 双机器模型:沙箱(box)vs 本机
核心定义在 source/shared/agents/agent-tool-names.ts 与 system prompt 的 ## Where you work(source/host/runner/system-prompt.ts:158-167)。
2.1 工具对应
// agent-tool-names.ts
export const SAND_BOX_SHELL_TOOL_NAME = "Shell";
export const SAND_BOX_READ_TOOL_NAME = "Read";
export const SAND_BOX_AWAIT_SHELL_TOOL_NAME = "AwaitShell";
export const SAND_EXTERNAL_SHELL_TOOL_NAME = "ExternalShell";
export const SAND_EXTERNAL_READ_TOOL_NAME = "ExternalRead";
export const SAND_EXTERNAL_AWAIT_SHELL_TOOL_NAME = "AwaitExternalShell";
export const SAND_DEFAULT_EXTERNAL_MACHINE_ID = "user-computer";
export const SAND_USER_COMPUTER = { id: "user-computer", label: "the user's computer" };
2.2 各自存什么
Box(/home/box,host-paths.ts):
/workspace—— 持久化 scratch 空间(文件、装好的工具跨 turn 保留)/home/box—— agent 的「家」:profile、memory、routines、workflows、channels/home/box/reference/—— 参考文档(debugging-the-box、app-ui,由box-reference-docs.ts写入)- 自带浏览器 + Linux 桌面(登录态持久);一台机器共享给该用户所有 agent,但桌面/浏览器窗口 per-agent 隔离
用户本机:用户的文件、终端会话、已装应用。每个动作都要授权(approval card)。
2.3 分工原则(system prompt 原文)
“Shell and Read are YOUR computer, and they are the default.” “ExternalShell and ExternalRead are the USER’s computer… This surface is not free — every action needs the user’s permission and raises an approval card… so never send work there that your own computer could have done.”
三条红线:
- 默认走 box,只有工作确实关于用户那台机器才切 External*;
- 绝不用 External 碰
/home/box路径*(既失败又白打扰用户); - 仓库工作 → Cursor cloud agent(不是 ExternalShell,也绝不 clone 到任一机器)。
术语约定:内部叫 “box”,对用户永远说 “my computer”;用户侧叫 “your computer”。
2.4 文件在两台机器间流动
source/host/runner/tools/sand-file-transfer-tools.ts:
CopyToBox:把用户本机文件原样拷进 box(默认落/workspace/uploads),供Shell/Read处理。CopyFromBox:把 box 产物(报表/日志/归档)拷到用户本机磁盘。- 聊天附件:附件在用户本机 → 用
ExternalRead;只有提示标 “also copied into your box” 的才用Read读 box 路径。
3. 底层执行:两个 daemon
| daemon | 跑在哪 | 干什么 |
|---|---|---|
box-exec-daemon(source/box-exec-daemon/) | box 内部 | 起 HTTP/connectrpc 服务(ExecService/ControlService),在 box 的 /home/box workspace、terminal 目录执行命令、读文件——Shell/Read 的落点 |
local-exec-daemon(source/local-exec-daemon/) | 宿主侧(用户本机 / Electron host) | 执行「本地」工具(ExternalShell/ExternalRead),带审批机制(retireLocalToolApproval) |
4. Box 的两种运行态
box-reference-docs.ts(debugging-the-box):
- 本地 Docker 容器(dev):靠 Docker Desktop;用
/.dockerenv判断;可从ExternalShell用docker ps/logs/inspect排查。 - brokered anyrun pod(发布默认):生命周期服务端管理,本地无东西可查。
对应 README 的 Settings → Router「Use local Docker VM」开关:开启后 box host + exec daemon 跑在自有本地容器(仅 loopback、产物只读挂载),否则连远程沙箱。
5. 网页访问在哪里执行
三条路径,执行位置各不相同:
| 路径 | 执行位置 | 适用场景 |
|---|---|---|
WebFetch / WebSearch | 后端隔离服务器 | 公开网页,无需登录 |
| box 浏览器(登录态) | box 桌面/浏览器,由 browserUse/computerUse subagent 驱动 | 登录墙内、无 connector 的站 |
| MCP connector | 后端,OAuth 授权 API | 有连接器的服务(优先) |
关键证据:
web-fetch.ts工具描述:“This fetch runs from an isolated server. Hosts like localhost or private IPs will not work.” ——WebFetch/WebSearch是服务端抓取,只碰公开页。web-search.ts:搜索走exaprovider,返回 “snippets and URLs”。sand-browser-use-subagent.ts:browserUse是 page-level(DOM 快照、按引用点元素、填表单、截图),“shares the box browser’s persistent logins”;computerUse是桌面级(鼠标键盘、像素点击),用于 GUI/文件对话框或 “defeats DOM automation” 的站点。
6. 如何应对人机验证(不破解,三条合法路径)
核心结论:它不「跳过/破解」人机验证,而是设计上让验证要么不出现(OAuth/MCP、公开页),要么由真人一次性完成(登录态持久化后免验)。
① 优先 connector:让验证根本不出现
system-prompt.ts ## Where you work 升级阶梯第 (2) 级:
“A connector is the BEST way to reach a service that has one — structured data instead of pixels, one authorization instead of a browser session that rots.”
MCP 走 OAuth,没有 CAPTCHA。
② 公开页用 WebFetch/WebSearch:本来就没有验证
跑在隔离服务器,只抓公开内容,不涉及登录。
③ 登录墙内且无 connector:交给真人,不破解
流程(sand-browser-use-subagent.ts + box-help-tool.ts):
父 agent 派
browserUse/computerUsesubagent 打开站点;subagent 碰到「密码 / 2FA / captcha / 支付」停下来报告:
“It cannot act as the user: if a step needs a human (a password, 2FA, a captcha, a payment) it stops and reports back.”
父 agent 调
request_box_help,把 box 桌面交给用户。box-help-tool.ts:“Use this instead of asking for credentials: the user signs in themselves on the box and you never see their password or 2FA.”
其
reason参数枚举"auth" | "captcha" | "payment" | "other",明确覆盖 captcha。用户自己登录/过验证,点 “hand back to agent”,agent 自动恢复;
会话持久化,一次性的(
system-prompt.ts:“the session persists there, so it is a one-time step”)——后续访问之所以免验,是因为登录态(cookie/session)已存在,而不是每次破解验证码。
④ 安全边界明确禁止「绕过」
SAND_SUBAGENT_SAFETY_PROMPT_SECTION(system-prompt.ts:61)把以下都列为「永远不该做的 workaround」:
“scraping session cookies or tokens, reading a credential… driving a signed-in browser session by hand, base64-ing or renaming a command so its keywords don’t trip the check… A block is not a puzzle to route around.”
所以它被硬约束为:不偷 cookie、不手工驾驶登录会话、不找验证码绕过技巧。合法路径只有一条——真人来点。
7. 一句话总结
- 默认在 box 干(自由、持久、无授权摩擦);用户本机只在任务确实相关时按需、每次授权访问;公开网页在后端隔离服务器抓;登录墙内站由 box 浏览器 + 真人一次性登录解决。
- 人机验证不被破解:OAuth/MCP 让验证不出现,公开页无验证,必须验证时
request_box_help交真人,登录态持久化后免验。
相关文档: