架构
沙箱模式有三层:-
带沙箱后端的深度智能体: 智能体自动从沙箱获取文件系统工具(
read_file、write_file、edit_file、execute) -
自定义 API 服务器: 通过
langgraph.json的http.app字段暴露的 Hono 应用,提供前端可调用的文件浏览端点 - IDE 前端: 三面板布局(文件树、代码/差异查看器、聊天),在智能体进行更改时实时同步文件
沙箱生命周期
在深入代码之前,了解沙箱的作用域是很重要的。作用域策略决定了谁共享沙箱、它存活多久以及如何在运行时解析。线程作用域沙箱(推荐)
每个 LangGraph 线程获得自己的沙箱。沙箱 ID 存储在线程的元数据中,并在运行时通过getConfig() 解析。这是大多数应用程序的推荐方法:
- 对话是隔离的——一个线程中的文件更改不会影响另一个
- 沙箱状态跨页面刷新持久化(同一线程 = 同一沙箱)
- 清理很简单:当线程被删除时,其沙箱也可以删除
智能体作用域沙箱
同一助手下的所有线程共享单个沙箱。适用于您希望更改跨对话保留的持久化项目环境:用户作用域沙箱
每个用户在所有线程中获得自己的沙箱。需要自定义身份验证和用户识别:会话作用域沙箱(客户端)
对于没有 LangGraph 线程的简单应用,前端可以生成会话 ID 并直接传递。这种方法不会跨浏览器会话持久化,最适合演示或原型开发:设置智能体
选择沙箱提供商
深度智能体支持多个沙箱提供商。任何实现了SandboxBackendProtocol 的提供商都可以使用:
read_file、write_file、edit_file、ls、glob、grep)和用于运行 shell 命令的 execute 工具。无需配置工具。
按线程解析沙箱
不要在模块级别创建沙箱(这会在所有线程间共享且可能过期),而是在运行时按线程解析沙箱。沙箱通过getConfig() 从 LangGraph 配置中读取 thread_id:
初始化沙箱
在智能体运行前,使用uploadFiles 将项目文件填充到沙箱中:
对于 LangSmith 沙箱,容器镜像和资源限制来自
沙箱快照。创建沙箱时传入
templateName(参见上面的 getOrCreateSandboxForThread)。uploadFiles 在运行时基于该镜像种子或更新项目文件。添加文件浏览 API
智能体可以读写文件,但前端也需要直接访问来浏览沙箱文件系统。添加一个自定义 Hono API 服务器并通过langgraph.json 的 http.app 字段暴露它。
创建 API 服务器
沙箱 API 端点使用线程 ID 作为 URL 路径参数。这确保前端始终访问当前对话的正确沙箱,使用与智能体后端相同的getOrCreateSandboxForThread 函数:
智能体的后端和 API 服务器都调用相同的
getOrCreateSandboxForThread 函数。这确保它们对给定线程始终解析到相同的沙箱。线程元数据中的沙箱 ID 是唯一的事实来源——不需要内存缓存。配置 langgraph.json
注册智能体图和 API 服务器。http.app 字段告诉 LangGraph 平台在默认路由旁提供您的自定义路由:
langgraph dev 的本地开发,即 http://localhost:2024。
在
http.app 中定义的自定义路由优先于默认的 LangGraph 路由。这意味着您可以在需要时遮蔽内置端点,但要注意不要意外覆盖 /threads 或 /runs 等路由。构建前端
前端有三个面板:文件树侧边栏、代码/差异查看器和聊天面板。它使用useStream 进行智能体对话,并使用自定义 API 端点进行文件浏览。
线程创建
页面加载时创建 LangGraph 线程,并将其 ID 持久化到sessionStorage 中,以便页面刷新时重新连接到相同的沙箱:
文件状态管理
跟踪沙箱文件系统的两个快照:原始状态(智能体运行前)和当前状态(实时更新)。线程 ID 包含在 API URL 中,以便请求始终命中当前对话的正确沙箱:实时文件同步
IDE 体验的关键是在智能体工作时更新文件,而不是完成后。观察流消息中来自文件修改工具的ToolMessage 实例。当 write_file 或 edit_file 工具调用完成时,刷新该特定文件。当 execute 完成时,刷新所有内容(因为 shell 命令可能修改任何文件):
检测变更文件
在每次智能体运行前,快照当前文件内容。文件刷新后,与快照比较以识别哪些文件发生了变更:显示差异
使用适合框架的差异库来渲染统一差异:
使用
@pierre/diffs(React)的示例:
变更文件摘要
显示所有修改文件的摘要,包含行级添加/删除计数。这为用户提供了智能体影响的快速概览——类似于git status:
三面板布局
IDE 布局将三个面板并排排列:@iconify-json/vscode-icons)并在修改过的文件上显示琥珀色圆点。选择修改过的文件会自动切换到差异标签页。
使用场景
沙箱是正确的选择,当:- 编程智能体创建、修改和运行代码时需要超越聊天的可视化界面
- 代码审查工作流中,智能体提出更改建议,用户在接受前审查差异
- 教程或学习应用中,AI 助手帮助用户逐步构建项目,在上下文中展示更改
- 原型工具中,用户用自然语言描述功能并实时观看智能体实现
最佳实践
- 使用线程作用域沙箱用于生产应用。将沙箱 ID 存储在线程元数据中,并在运行时通过
getConfig()解析。这避免了模块级状态,并保持沙箱按对话隔离。 - 在智能体后端和 API 服务器之间共享
getOrCreateSandboxForThread。两者都应该以相同方式解析沙箱——通过线程元数据——这样只有单一的事实来源,无需内存缓存。 - 在
sessionStorage中持久化threadId,以便页面刷新时重新连接到相同的线程和沙箱,而不是创建新的。 - 在每次相关工具调用时同步文件,而不仅仅是运行完成时。这使 IDE 感觉是实时的。监视
write_file、edit_file和execute工具消息并立即刷新。 - 对变更文件默认使用差异视图。当用户点击被智能体修改的文件时,首先显示差异——这是他们关心的。
- 对只读操作显示紧凑的工具结果。不要在聊天中倾倒
read_file的完整输出,而是显示一行如Read router.js L1-42。将完整输出显示留给修改工具。 - 用真实项目初始化沙箱。从空沙箱开始会令人困惑。上传一个可工作的启动项目,以便用户(和智能体)立即有上下文。
- 从文件树中过滤
node_modules。没人想浏览成千上万的依赖文件。获取文件树时将其过滤掉。
通过 MCP 连接这些文档到 Claude、VSCode 等以获取实时解答。

