编码代理不仅仅需要一个聊天窗口。它们需要文件浏览器、代码查看器、差异对比面板,即一种 IDE 体验。此模式将深度代理连接到沙盒,使其能在隔离环境中读取、写入和执行代码,然后通过自定义 API 服务器暴露沙盒文件系统,以便前端能在代理工作时实时显示文件。 本页涵盖三面板 UI(文件树、代码查看器和聊天)以及将沙盒文件系统暴露给它的自定义 API 路由。关于沙盒提供者、生命周期作用域、文件种子、密钥、部署和生产环境 useStream 配置,请参见投入生产。

架构

此设置包含三个部分:
  1. 带有沙盒后端的深度代理:代理自动从沙盒获取文件系统工具(read_file、write_file、edit_file、execute)。
  2. 自定义 API 服务器:一个通过 langgraph.json 的 http.app 字段暴露的 Hono 应用,提供前端可以调用的文件浏览端点。
  3. 三面板前端:一个文件树、代码/差异查看器和聊天面板,当代理进行更改时实时同步文件。

沙盒生命周期

在连接前端之前,选择沙盒的持续时间和共享方式。关于线程作用域与助手作用域沙盒、异步图工厂设置、TTL 行为和 SDK 调用示例,请参见沙盒生命周期。 本指南默认使用线程作用域沙盒。前端和自定义 API 服务器都从 LangGraph 线程 ID 解析沙盒。这保持对话隔离,并在您持久化线程 ID 时允许页面重新加载重新连接到相同环境。 对于多租户应用,请在您的后端工厂中按用户或助手设定沙盒作用域。对于没有 LangGraph 线程的演示,请在 API URL 中传递客户端生成的会话 ID。该会话 ID 不会在浏览器会话间持久化。

连接代理和 API 服务器

按照执行环境中所述,使用沙盒后端配置深度代理。代理会自动获取文件系统工具和一个 execute 工具;无需额外的工具配置。 构建此 UI 在生产环境设置之上增加了一个要求:一个自定义 API 服务器,它在代理图之外运行,因此代理后端和您的文件浏览路由都必须为每个线程解析相同的沙盒。将沙盒 ID 存储在线程元数据中,并在两者之间共享单个查找函数。

从线程元数据解析沙盒

在共享模块中定义 getOrCreateSandboxForThread。代理图工厂和自定义 API 路由都导入它:
将代理连接为异步图工厂,该工厂从运行配置中读取 thread_id 并将解析后的后端传递给 createDeepAgent:
类似于投入生产中的示例,代理是在每次运行时调用的异步图工厂。将沙盒 ID 存储在线程元数据中,以便自定义 http.app 路由可以调用相同的 getOrCreateSandboxForThread 辅助函数。当 LangGraph SDK 是唯一入口点时,投入生产改用提供者标签查找。

种子项目文件

在代理运行之前,使用 uploadFiles / upload_files 上传启动文件。关于种子模式、提供者示例以及将记忆或技能同步到沙盒中,请参见文件传输。对于 LangSmith 沙盒,在创建容器时从沙盒快照传递 templateName。
上传 package.json 后运行 sandbox.execute("cd /app && npm install"),以便在第一次代理轮次之前准备好依赖项。

添加文件浏览 API

代理可以读取和写入文件,但前端还需要直接访问以浏览沙盒文件系统。添加一个自定义的 Hono API 服务器,并通过 langgraph.json 中的 http.app 字段暴露它。

创建 API 服务器

沙盒 API 端点使用线程 ID 作为 URL 路径参数。这确保前端始终访问当前对话的正确沙盒,使用与代理后端相同的 getOrCreateSandboxForThread 函数:
代理的后端和 API 服务器都调用相同的getOrCreateSandboxForThread 函数。这确保它们总是解析到给定线程的相同沙盒。线程元数据中的沙盒 ID 是唯一的真相来源——无需内存缓存。

配置 langgraph.json

注册代理图和 API 服务器。http.app 字段告诉 LangGraph 平台在默认路由旁边提供您的自定义路由。完整的 langgraph.json 选项集请参见应用程序结构和 LangSmith 部署。
您的自定义路由在与 LangGraph API 相同的主机上可用。对于使用 langgraph dev 的本地开发,地址为 http://localhost:2024。
http.app 中定义的自定义路由优先于默认的 LangGraph 路由。这意味着您可以根据需要覆盖内置端点,但要小心不要意外覆盖 /threads 或 /runs 等路由。

构建前端

前端有三个面板:文件树侧边栏、代码/差异查看器和聊天面板。它使用 useStream 进行代理对话,并使用自定义 API 端点进行文件浏览。 对于生产部署,将 apiUrl 指向您的 LangSmith 部署,并在每次运行时传递稳定的 thread_id。关于这些设置以及使用 thread_id 和运行时 context 调用代理的信息,请参见投入生产中的前端部分。

线程创建

在页面加载时创建 LangGraph 线程,并将其 ID 持久化在 sessionStorage 中,以便页面重新加载重新连接到同一沙盒:
“新建线程”按钮清除存储的 ID,因此下一次挂载会创建一个全新的线程(和沙盒):

文件状态管理

跟踪沙盒文件系统的两个快照:原始状态(代理运行前)和当前状态(实时更新)。线程 ID 包含在 API URL 中,因此请求总是命中正确的沙盒:

实时文件同步

IDE 体验的关键是在代理工作时更新文件,而不是在它完成之后。监视流中的消息,查找来自文件变更工具的 ToolMessage 实例。当 write_file 或 edit_file 工具调用完成时,刷新该特定文件。当 execute 完成时,刷新所有内容(因为 shell 命令可能修改任何文件):

检测更改的文件

在每次代理运行之前,快照当前文件内容。文件刷新后,与快照进行比较以识别哪些文件已更改:
当用户选择一个已更改的文件时,默认显示差异视图,以便他们立即查看代理修改了什么。

显示差异

使用适合框架的差异库来渲染统一的差异: 使用 @pierre/diffs (React) 的示例:

已更改文件摘要

显示所有修改过的文件摘要,包含行级别的新增/删除计数。这为用户提供了代理影响的快速概览——类似于 git status:

用例

当满足以下条件时,沙盒是合适的选择:
  • 编码代理:需要超越聊天的可视化界面来创建、修改和运行代码。
  • 代码审查工作流:代理建议更改,用户在接受前审查差异。
  • 教程或学习应用:AI 助手帮助用户逐步构建项目,并在上下文中显示更改。
  • 原型设计工具:用户用自然语言描述功能,并实时观看代理实现它们。

最佳实践

前端特定:
  • 在 sessionStorage 中持久化 threadId,以便页面重新加载重新连接到同一线程和沙盒,而不是创建新的。
  • 在每个相关的工具调用时同步文件,而不仅仅在运行完成时。监视 write_file、edit_file 和 execute 工具消息,并立即刷新。
  • 默认对更改的文件显示差异视图。当用户点击被代理修改的文件时,首先显示差异——那是他们关心的。
  • 为只读操作显示紧凑的工具结果。不要在聊天中转储 read_file 的完整输出,而是显示像 Read router.js L1-42 这样的单行摘要。将完整输出显示保留给变更工具。
  • 从文件树中过滤 node_modules。没有人想浏览数千个依赖文件。在获取树时将它们过滤掉。
对于后端和沙盒:
  • 对生产应用使用线程作用域沙盒。参见沙盒生命周期。
  • 通过线程元数据在代理后端和 API 服务器之间共享沙盒解析,这样两者都使用相同的查找函数解析到相同的环境,无需内存缓存。
  • 用真实项目作为沙盒的种子。参见文件传输。
  • 将密钥排除在沙盒之外。使用沙盒认证代理来处理 API 密钥,而不是使用环境变量或文件上传。
  • 在启动前添加防护栏。为自主编码代理配置速率限制、错误处理和数据隐私中间件。

相关

投入生产

使用持久沙盒、认证、防护栏和生产环境 useStream 设置部署代理。

沙盒

沙盒提供者、安全模型和文件传输 API。

前端概述

其他深度代理 UI 模式:子代理流式传输、待办事项列表和自定义状态。

应用程序结构

完整的 langgraph.json 参考,包括自定义 http.app 路由。