Skip to main content
加入与重新加入功能允许您从正在运行的代理流中断开连接,而不停止代理,之后再重新连接。当客户端离开时,代理继续在服务器端执行,您可以从断开的确切位置继续处理流。
此功能需要 LangGraph Agent Server。请在本地使用 langgraph dev 运行您的代理,或将其部署到 LangSmith 以使用此模式。

为什么需要加入与重新加入?

传统的流式 API 将客户端和服务器紧密耦合:如果客户端断开连接,流就会丢失。加入与重新加入打破了这种耦合,支持几种重要的模式:
  • 网络中断:在移动基站或 Wi-Fi 网络之间切换的移动用户可以无缝恢复
  • 页面导航:用户离开聊天页面后稍后返回,不会丢失进度
  • 移动应用后台运行:被操作系统挂起的应用在回到前台时可以重新加入流
  • 长时间运行的任务:代理执行需要数分钟的操作(研究、代码生成、数据分析),用户无需保持页面打开
  • 多设备切换:在手机上开始对话,在桌面设备上重新加入

核心概念

加入/重新加入模式涉及三个关键机制:
stream.stop() 与取消运行有根本区别。停止仅断开客户端连接。代理继续在服务器端处理。要实际取消代理的执行,您需要使用中断或取消机制。

设置 useStream

关键设置步骤是从 onCreated 回调中捕获 run_id,以便稍后重新加入。 定义一个与代理状态模式匹配的 TypeScript 接口,并将其作为类型参数传递给 useStream,以实现对状态值的类型安全访问。在下面的示例中,将 typeof myAgent 替换为您的接口名称:

使用可恢复选项提交

当您提交消息时,传递 onDisconnect: "continue"streamResumable: true 以启用加入/重新加入流程:
始终同时使用这两个选项。设置 onDisconnect: "continue" 而不设置 streamResumable: true 意味着代理继续运行,但您无法重新加入流以查看其输出。

从流中断开连接

调用 stream.stop() 断开客户端连接。代理继续在服务器端处理。
调用 stop() 后:
  • stream.isLoading 变为 false
  • 消息列表保留直到断开点接收的所有消息
  • 代理继续在服务器上运行
  • 在重新加入之前不会收到新消息

重新加入流

使用保存的运行 ID 调用 stream.joinStream(runId) 重新连接:
重新加入后:
  • stream.isLoading 再次变为 true
  • 断开连接期间生成的任何消息都会被传递
  • 新的流式消息实时恢复
  • 如果代理已经完成,您将立即收到最终状态

构建连接状态指示器

视觉指示器可帮助用户了解他们是否正在接收来自代理的实时更新。
使用绿色/红色点为指示器设置样式:

断开连接和重新加入控件

提供明确的断开连接和重新加入按钮,以便用户完全控制:

持久化运行 ID

对于跨会话重新加入(例如,用户关闭浏览器后稍后返回),将运行 ID 持久化到存储中:
持久化的运行 ID 应在运行完成时清理。监听流完成并移除存储的 ID,以避免尝试重新加入已完成的运行。

错误处理

如果运行已过期、被删除或服务器已重启,重新加入可能会失败。优雅地处理这些情况:

完整示例

最佳实践

  • 始终保存运行 ID:没有它,重新加入是不可能的。同时使用组件状态和持久化存储以提高弹性。
  • 显示清晰的连接状态:用户应始终知道他们是正在接收实时更新还是查看快照。
  • 在可见性变化时自动重新加入:使用页面可见性 API 在用户返回标签页时自动重新加入。
  • 设置合理的超时时间:如果重新加入尝试耗时过长,则回退到获取线程历史记录。
  • 清理已完成的运行:在代理完成时移除持久化的运行 ID,以避免过期的重新加入尝试。