background-agents 隧道URL机制深度解析:.tunnels.env 启动时序的3层设计
background-agents 隧道URL机制深度解析.tunnels.env 启动时序的3层设计【免费下载链接】background-agentsAn open-source background agents coding system项目地址: https://gitcode.com/GitHub_Trending/ba/background-agentsbackground-agentsOpen-Inspect是一个开源的后台 AI 编程代理系统它把编码会话跑在云端沙箱里让你发完 prompt 就能关电脑。当沙箱里的服务比如前端应用需要被外部访问时系统会把「端口 → 公网URL」的映射写进一个.tunnels.env文件。这篇深度解析带你搞懂这个隧道 URL 机制以及.tunnels.env文件的启动时序设计——它是如何在新沙箱、快照恢复两种场景下又快又稳地把 URL 交到你本地脚本手里的。 先搞懂.tunnels.env 是什么简单说它就是一个标准dotenv文件放在沙箱的/workspace/.tunnels.env每一行对应一个端口的隧道 URL# /workspace/.tunnels.env TUNNEL_SANDBOX_IDsandbox-acme-app-1783614336426 TUNNEL_3000https://abc123-3000.modal.host TUNNEL_5173https://abc123-5173.modal.host这种「纯KEYvalue」格式的好处是任何能读 env 文件的工具都能直接用——node --env-file...、bun --env-file...、docker compose --env-file...统统适用无需额外解析。你只需要在.openinspect/start.sh里启动服务时把本地端口的 URL 指向对应隧道地址即可。 一句话这个文件是「沙箱后端」和「你写的启动脚本」之间的桥梁。⚙️ 核心设计谁在什么时候写入这套机制最妙的地方在于写入方和读取方在时间上是解耦的角色位置做什么写入方控制平面 / provider云端沙箱建好、解析出隧道 URL 后立即把文件写进沙箱读取方supervisor 你的脚本沙箱内启动时清理陈旧文件、等待新 URL 就绪再运行start.sh关键点控制平面的写入可能比沙箱内的 supervisor 启动得还早——因为它只需要容器 agent而不需要 supervisor 跑起来。这就引出了整个时序设计的核心矛盾——怎么让沙箱区分「这是给我这个沙箱写的新文件」和「这是上一个沙箱残留的死文件」答案就是文件里的第一行TUNNEL_SANDBOX_ID。相关契约常量定义在 constants.py而 Vercel provider 侧的写入逻辑在 provider.ts。 启动时序的3个关键步骤沙箱每次非构建模式启动时supervisor 会按固定顺序走这3步实现在 repository_boot.py第1步清理陈旧文件Clear Stale File先读环境变量EXPECTED_TUNNEL_PORTS控制平面在tunnelPorts非空时注入再决定要不要清理。清理逻辑很讲究✅ 如果文件里的TUNNEL_SANDBOX_ID等于当前沙箱 ID→保留说明是后端刚写好的新文件️ 否则 →删除这是从快照继承来的遗留文件URL 已经失效了这正是在「快照恢复」场景下的保命设计快照里可能带着上一个沙箱的.tunnels.env里面是早就过期的 URL必须清掉否则会污染新会话。清理与判定的核心代码在 tunnel_environment.py 的clear_stale_file()。第2步等待新 URL 就绪Wait Until Readysupervisor 进入轮询等待每隔0.2 秒检查一次文件直到所有期望端口的TUNNEL_port都出现。⏱️ 默认最多等30 秒TUNNEL_WAIT_TIMEOUT_SECONDS可覆盖✅ 全部就绪 → 记日志tunnel.env_file_ready进入下一步⚠️ 超时 → 记tunnel.env_file_wait_timeout第3步运行 start.sh等 URL 就绪或超时降级后才执行.openinspect/start.sh。此时你脚本里通过--env-file/workspace/.tunnels.env读到的一定是新鲜的、可用的URL。Sandbox Created ──▶ Git Sync ──▶ Setup ──▶ ① 清理陈旧文件 │ ┌───────────────────────────────────────────┘ ▼ ② 等待新URL就绪≤30s ──▶ ③ start.sh ──▶ 服务可被外部访问️ 超时降级为什么「等不到」也不崩这是很多新手容易忽略的优雅设计即使等待超时start.sh依然会执行只是这次它拿不到本地新鲜 URL。为什么这样设计因为控制平面有另一条独立路径——它会把隧道 URL 直接广播给所有客户端网页、Slack 等这条路不依赖沙箱里的文件。所以哪怕沙箱内文件还没就绪用户照样能在界面上看到可访问的 URL只是沙箱本地脚本暂时读不到而已。这让系统在面对「后端解析隧道 URL 稍慢」这类时序抖动时不会卡死整个启动流程而是优雅降级、留待后续重试。 什么时候「不写」这个文件两个场景下系统会跳过写入避免无谓的等待tunnelPorts为空会话根本没配置隧道端口自然没有 URL 可写。构建模式Build Mode镜像预构建阶段只关心依赖安装不暴露服务因此不写文件、也不触发等待。 想深入源码从这几个文件入手这套机制横跨控制平面和沙箱运行时两侧推荐阅读顺序官方架构文档HOW_IT_WORKS.md 里的「Tunnel URLs Inside the Sandbox」一节有最完整的官方说明。沙箱侧时序核心tunnel_environment.py清理 等待、repository_boot.py编排位置、constants.py契约常量。控制平面写入侧vercel/provider.ts 的writeTunnelEnvFile()展示了 provider 如何用一条命令把文件写进沙箱。✅ 小结.tunnels.env看似只是一个 dotenv 文件背后却是一套精心设计的启动时序协议TUNNEL_SANDBOX_ID打标→ 区分「新文件」与「快照遗留」让快照恢复不再被死 URL 污染三步时序清理 → 等待 → 启动→ 保证start.sh读到的永远是新鲜 URL超时降级 独立广播通道→ 即使文件没就绪整个系统也照样可用。理解了这个设计你就能在 background-agents 的.openinspect/start.sh里自信地引用隧道 URL让沙箱里的服务被世界访问——而不用担心时序竞态把一切都搞乱。【免费下载链接】background-agentsAn open-source background agents coding system项目地址: https://gitcode.com/GitHub_Trending/ba/background-agents创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考