> ## Documentation Index
> Fetch the complete documentation index at: https://cndoc-langchain.site/llms.txt
> Use this file to discover all available pages before exploring further.

# 投入生产

> 通过持久化内存、沙箱、弹性中间件和部署选项，将您的深度智能体投入生产

本指南涵盖了将深度智能体从本地原型投入生产部署时需要考虑的事项。它将逐步介绍内存范围界定、执行环境配置、添加防护措施以及连接前端。

## 概述

智能体使用来自内存和执行环境的信息来完成任务。
在生产环境中，有几个基本要素决定了信息如何共享和访问：

* **线程**：单次对话。消息历史记录和临时文件默认限定在线程范围内，不会跨线程传递。
* **用户**：与您的智能体交互的人。内存和文件可以是用户私有的，也可以在用户之间共享。身份和授权来自您的[认证层](/langsmith/auth)。
* **助手**：一个配置好的智能体实例。内存和文件可以绑定到一个助手，也可以在所有助手之间共享。

本页涵盖：

* **[LangSmith 部署](#langsmith-deployments)**：带有认证、Webhook 和定时任务的托管基础设施
* **[生产环境注意事项](#production-considerations)**：多租户、认证、凭据、异步和持久性
* **[内存](#memory)**：跨对话持久化信息
* **[执行环境](#execution-environment)**：文件存储和代码执行
* **[防护措施](#guardrails)**：速率限制、错误处理和数据隐私
* **[前端](#frontend)**：将您的 UI 连接到已部署的智能体

## LangSmith 部署

<img src="https://mintcdn.com/other-405835d4/8rovbnQI_RWJV77O/oss/images/deepagents/production/deepagents-deploy-config.png?fit=max&auto=format&n=8rovbnQI_RWJV77O&q=85&s=2022c8c7910eda4a3ea6e73cee2b413a" alt="deepagents deploy 打包您的智能体配置——内存、沙箱、技能、MCP 服务器——并将其部署到 LangSmith 部署" width="1100" height="950" data-path="oss/images/deepagents/production/deepagents-deploy-config.png" />

将深度智能体投入生产的最快方式是使用 [`deepagents deploy`](/oss/python/deepagents/deploy)，它打包您的智能体配置，并通过一条命令将其部署为 LangSmith 部署。或者，您可以直接配置 [LangSmith 部署](/langsmith/deployment)。无论哪种方式，都会为您的智能体配置所需的基础设施：[助手](/langsmith/assistants)、[线程](/langsmith/use-threads)、[运行](/langsmith/runs)、存储和检查点，因此您无需自行设置。它还为您提供了开箱即用的[认证](/langsmith/auth)、[Webhook](/langsmith/use-webhooks)、[定时任务](/langsmith/cron-jobs)和[可观测性](/langsmith/observability)，并且可以通过 [MCP](/langsmith/server-mcp) 或 [A2A](/langsmith/server-a2a) 暴露您的智能体。

有关基于 CLI 的方法，请参阅[使用 CLI 部署](/oss/python/deepagents/deploy)。有关手动设置，请参阅 [LangSmith 部署快速入门](/langsmith/deployment-quickstart)。

除非另有说明，本页上的所有代码片段均使用以下 `langgraph.json`：

```json langgraph.json theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
{
  "dependencies": ["."],
  "graphs": {
    "agent": "./agent.py:agent"
  },
  "env": ".env"
}
```

`langgraph.json` 是告诉 LangGraph 平台如何构建和运行您的应用程序的配置文件。它位于项目根目录，对于本地开发（使用 `langgraph dev`）和生产部署都是必需的。关键字段如下：

| 字段             | 描述                                                                                                                       |
| -------------- | ------------------------------------------------------------------------------------------------------------------------ |
| `dependencies` | 要安装的包。`["."]` 将当前目录作为包安装（从 `requirements.txt`、`pyproject.toml` 或 `package.json` 读取）。                                     |
| `graphs`       | 将图 ID 映射到其代码位置。每个条目是 `"<id>": "./<file>:<variable>"`，其中 `<id>` 是您通过 API 调用图时使用的名称，`<variable>` 是从 `<file>` 导出的已编译图或构造函数。 |
| `env`          | 包含环境变量（API 密钥、密钥）的 `.env` 文件路径。这些在构建时设置，在运行时可用。                                                                          |

有关完整的配置选项集（自定义 Docker 步骤、存储索引、认证处理程序等），请参阅[应用结构](/oss/python/langgraph/application-structure)。

## 生产环境注意事项

### 多租户

当您的智能体服务于多个用户时，您需要处理三个问题：验证每个用户的身份、控制他们可以访问的内容，以及管理智能体代表他们操作时使用的凭据。

<img src="https://mintcdn.com/other-405835d4/8rovbnQI_RWJV77O/oss/images/deepagents/production/auth-layers.png?fit=max&auto=format&n=8rovbnQI_RWJV77O&q=85&s=15e48a084ff87dc269bd10535b44f547" alt="三个认证层组合：最终用户认证、智能体代表用户认证和团队 RBAC" width="2000" height="1060" data-path="oss/images/deepagents/production/auth-layers.png" />

#### 用户身份和访问控制

[LangSmith 部署](/langsmith/deployment)支持[自定义认证](/langsmith/custom-auth)以建立用户身份，并支持[授权处理程序](/langsmith/auth)来控制对线程、助手和存储命名空间等资源的访问。授权处理程序在认证成功后运行，可以：

* 为资源添加所有权元数据标签（例如，`owner: user_id`）
* 返回过滤器，以便用户只能看到自己的资源
* 对未授权操作返回 HTTP 403 拒绝访问

有关分步教程，请参阅[使对话私有化](/langsmith/resource-auth)。有关演练，请观看[自定义认证视频](https://www.youtube.com/watch?v=DkNqgCz8cjE)。

您如何[界定内存范围](#scoping)和[执行环境](#execution-environment)决定了用户之间共享哪些数据。详情请参阅以下部分。

#### 团队访问控制 (RBAC)

LangSmith 的[基于角色的访问控制](/langsmith/rbac)管理您团队中谁可以部署、配置和监控智能体。这与上述最终用户授权是分开的。

| 角色     | 访问权限                 |
| ------ | -------------------- |
| 工作区管理员 | 完全权限，包括设置和成员管理       |
| 工作区编辑者 | 创建和修改资源，但不能删除运行或管理成员 |
| 工作区查看者 | 只读访问                 |

企业版计划提供具有细粒度权限的自定义角色。有关完整的权限模型，请参阅 [RBAC 参考](/langsmith/rbac)。

#### 最终用户凭据

当您的智能体需要代表用户调用外部 API（例如，读取他们的 GitHub 仓库、发送 Slack 消息、查询他们的数据仓库）时，您需要一种方式将用户的凭据传递给智能体，而无需硬编码它们。

**通过智能体认证的 OAuth。** [智能体认证](/langsmith/agent-auth)提供了一个托管的 OAuth 2.0 流程。配置一个 OAuth 提供程序，智能体就可以请求限定每个用户范围的令牌。首次使用时，智能体会[中断](/oss/python/langgraph/interrupts)执行并呈现一个 OAuth 同意 URL。用户认证后，智能体使用有效的令牌恢复执行。令牌会自动存储和刷新。

```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
from langchain_auth import Client
from langchain.tools import tool, ToolRuntime

auth_client = Client()

# 在您的智能体工具内部：
@tool
async def github_action(runtime: ToolRuntime):
    """代表用户通过 GitHub 执行操作。"""
    auth_result = await auth_client.authenticate(
        provider="github",
        scopes=["repo", "read:org"],
        user_id=runtime.server_info.user.identity,  # [!code highlight]
    )
    # 使用 auth_result.token 代表用户进行 GitHub API 调用
```

**沙箱的凭据注入。** 如果您的智能体在[沙箱](#sandboxes)内运行调用外部 API 的代码，[沙箱认证代理](/langsmith/sandbox-auth-proxy)可以自动将凭据注入出站请求，因此沙箱代码永远不会收到原始 API 密钥。有关设置详情，请参阅[管理密钥](#managing-secrets)。

**工作区密钥。** 对于所有用户共享的 API 密钥（例如，您组织的 LLM 提供商密钥、搜索 API 密钥），请将它们作为[工作区密钥](/langsmith/set-up-hierarchy#configure-workspace-settings)存储在 LangSmith 中。详情请参阅[管理密钥](#managing-secrets)。

### 异步

基于 LLM 的应用程序是 I/O 密集型的：调用语言模型、数据库和外部服务。异步编程允许这些操作并发运行而不是阻塞，从而提高吞吐量和响应能力。

<Note>
  LangChain 遵循在异步方法名前加 `a`
  前缀的约定（例如，`ainvoke`、`abefore_agent`、`astream`）。同步和异步变体位于同一个类或命名空间中。
</Note>

为生产环境构建时：

* **创建异步工具。** LangChain 在单独的线程中运行同步工具以避免阻塞，但原生异步完全避免了线程开销。
* **使用异步中间件方法。** 自定义[中间件](/oss/python/langchain/middleware/custom)应实现异步钩子（例如，`abefore_agent` 而不是 `before_agent`）。
* **对外部资源生命周期使用异步。** 创建[沙箱](#sandboxes)或连接 [MCP 服务器](/oss/python/langchain/mcp)涉及网络调用，应被等待。这就是为什么配置这些资源的[图工厂](/langsmith/graph-rebuild)是异步的。

### 持久性

深度智能体运行在 LangGraph 上，它提供了开箱即用的[持久执行](/oss/python/langgraph/durable-execution)。[持久化](/oss/python/langgraph/persistence)层在每个步骤检查点状态，因此因故障、超时或[Human in the Loop](/oss/python/langgraph/interrupts)暂停而中断的运行会从其最后记录的状态恢复，而无需重新处理之前的步骤。对于生成许多子智能体的长时间运行的深度智能体，这意味着运行中的故障不会丢失已完成的工作。

<img src="https://mintcdn.com/other-405835d4/8rovbnQI_RWJV77O/oss/images/deepagents/production/durable-execution.png?fit=max&auto=format&n=8rovbnQI_RWJV77O&q=85&s=ca9494f25220b10940d2f8447a25895d" alt="持久执行：当一个工作进程在运行中崩溃时，另一个工作进程从最新的检查点接管运行" width="962" height="545" data-path="oss/images/deepagents/production/durable-execution.png" />

检查点还支持：

* **无限期[中断](/oss/python/langgraph/interrupts)。** Human in the Loop的工作流可以暂停数分钟或数天，并准确地从上次中断的地方恢复。
* **[时间旅行](/oss/python/langgraph/use-time-travel)。** 每个检查点步骤都是一个可以回退的快照，如果出现问题，您可以从较早的状态重放。
* **安全处理敏感操作。** 对于涉及支付或其他不可逆操作的工作流，检查点提供审计跟踪和恢复点，以检查导致操作的确切状态。

<Tip>
  [LangSmith
  部署](/langsmith/deployment)会自动配置持久化检查点。如果您是自托管，请参阅[持久化](/oss/python/langgraph/persistence)了解设置说明。
</Tip>

## 内存

没有内存，每次对话都从头开始。内存让您的智能体能够跨对话保留信息（用户偏好、学习到的指令、过去的经验），从而能够随着时间的推移个性化其行为。有关内存类型的概述，请参阅[内存概念指南](/oss/python/concepts/memory)。

<img src="https://mintcdn.com/other-405835d4/8rovbnQI_RWJV77O/oss/images/deepagents/production/memory.png?fit=max&auto=format&n=8rovbnQI_RWJV77O&q=85&s=f03bb9e05b2d289c6f5430ae68e6fbc3" alt="短期内存通过检查点限定在单个线程范围内；长期内存通过存储跨线程持久化" width="1920" height="1160" data-path="oss/images/deepagents/production/memory.png" />

### 范围界定

内存始终跨对话持久化。主要问题是它如何在用户和助手边界之间界定范围。正确的范围取决于谁应该查看和修改数据：

| 范围            | 命名空间             | 用例           | 示例                |
| ------------- | ---------------- | ------------ | ----------------- |
| **用户**（推荐默认值） | `(user_id)`      | 每个用户的偏好和上下文  | "我喜欢简洁的回复"        |
| **助手**        | `(assistant_id)` | 一个助手的共享指令    | "帖子限制在 280 个字符以内" |
| **全局**        | `(org_id)`       | 所有用户和助手的只读策略 | "永远不要泄露内部定价"      |

<Warning>
  共享内存（助手、用户或组织范围）是提示注入的载体。如果一个用户可以写入另一个用户对话读取的内存，恶意用户可能会将指令注入该共享状态。在适当的地方强制执行只读访问。例如，使组织范围的策略只能通过应用程序代码写入，而不是由智能体本身写入。使用[权限](/oss/python/deepagents/permissions)以声明方式拒绝写入共享路径，或使用[后端策略钩子](/oss/python/deepagents/backends#add-policy-hooks)进行自定义验证逻辑。
</Warning>

### 配置

在深度智能体中，内存作为文件存储在虚拟文件系统中。默认情况下，文件仅持续一次对话。要持久化它们，请将类似 `/memories/` 的路径路由到写入 LangGraph [Store](/langsmith/custom-store) 的 [StoreBackend](https://reference.langchain.com/python/deepagents/backends/store/StoreBackend)。使用 [CompositeBackend](https://reference.langchain.com/python/deepagents/backends/composite/CompositeBackend) 为智能体提供临时暂存空间和持久化的[长期内存](/oss/python/deepagents/memory)。

<Note>
  下面显示的 `rt.server_info` 和 `rt.execution_info` 命名空间模式需要 `deepagents>=0.5.0`。
</Note>

<Tabs>
  <Tab title="用户（推荐）">
    按 `user_id` 划分命名空间。每个用户获得自己的私有内存。这是推荐的默认值，因为大多数应用程序部署单个助手。

    ```python agent.py theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    from deepagents import create_deep_agent
    from deepagents.backends import CompositeBackend, StateBackend, StoreBackend

    agent = create_deep_agent(
        model="google_genai:gemini-3.1-pro-preview",
        backend=CompositeBackend(
            default=StateBackend(),
            routes={
                "/memories/": StoreBackend(
                    namespace=lambda rt: (
                        rt.server_info.assistant_id,  # [!code highlight]
                        rt.server_info.user.identity,  # [!code highlight]
                    ),
                ),
            },
        ),
        system_prompt="""您在 /memories/ 处有持久化内存。

        在每次对话开始时读取 /memories/instructions.txt 以获取
        累积的知识和偏好。当您学到应该持久化的内容时，
        更新该文件。""",
    )
    ```
  </Tab>

  <Tab title="助手">
    按 `assistant_id` 划分命名空间。内存跨同一助手的所有用户共享，因此任何用户都可以读取或更新它。用于适用于使用给定助手的所有人的共享指令或知识（例如，“始终以正式语气回复”）。

    ```python agent.py theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    from deepagents import create_deep_agent
    from deepagents.backends import CompositeBackend, StateBackend, StoreBackend

    agent = create_deep_agent(
        model="google_genai:gemini-3.1-pro-preview",
        backend=CompositeBackend(
            default=StateBackend(),
            routes={
                "/memories/": StoreBackend(
                    namespace=lambda rt: (
                        rt.server_info.assistant_id,  # [!code highlight]
                    ),
                ),
            },
        ),
    )
    ```
  </Tab>

  <Tab title="用户">
    仅按 `user_id` 划分命名空间。内存跨所有助手跟随用户。用于应适用于用户与哪个助手对话的全局用户配置文件（姓名、时区、通信偏好）。

    ```python agent.py theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    from deepagents import create_deep_agent
    from deepagents.backends import CompositeBackend, StateBackend, StoreBackend

    agent = create_deep_agent(
        model="google_genai:gemini-3.1-pro-preview",
        backend=CompositeBackend(
            default=StateBackend(),
            routes={
                "/memories/": StoreBackend(
                    namespace=lambda rt: (rt.server_info.user.identity,),  # [!code highlight]
                ),
            },
        ),
    )
    ```
  </Tab>

  <Tab title="组织">
    按 `org_id` 划分命名空间。内存跨所有用户和所有助手共享。通常用于组织范围的策略（合规规则、品牌指南），这些策略对智能体应为只读。写入访问应限制为应用程序代码，以防止提示注入。

    ```python agent.py theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    from deepagents import create_deep_agent
    from deepagents.backends import CompositeBackend, StateBackend, StoreBackend

    agent = create_deep_agent(
        model="google_genai:gemini-3.1-pro-preview",
        backend=CompositeBackend(
            default=StateBackend(),
            routes={
                "/memories/": StoreBackend(
                    namespace=lambda rt: (rt.context.org_id,),
                ),
            },
        ),
    )
    ```
  </Tab>
</Tabs>

您也可以使用 [Store API](/langsmith/custom-store) 从应用程序代码读取和写入存储。有关示例，请参阅[高级用法](/oss/python/deepagents/memory#advanced-usage)。

有关完整的命名空间工厂 API，请参阅[命名空间工厂](/oss/python/deepagents/backends#namespace-factories)。有关自我改进指令和知识库等内存模式，请参阅[长期内存](/oss/python/deepagents/memory)。

## 执行环境

在本地，智能体可以读写磁盘上的文件并直接运行 shell 命令。在生产环境中，您需要考虑隔离性和持久性。正确的设置取决于您的智能体是否需要执行代码：

* **文件系统后端**：如果您的智能体只读写文件，这就足够了。选择符合您持久性需求的后端：临时暂存空间、持久存储，或两者的混合。
* **沙箱**：添加一个带有 `execute` 工具的隔离容器，用于运行 shell 命令。如果您的智能体需要运行代码、安装包或执行文件 I/O 以外的任何操作，请使用沙箱。

### 文件系统

根据需要持久化的内容选择后端：

* [StateBackend](https://reference.langchain.com/python/deepagents/backends/state/StateBackend)（默认）：临时暂存空间，限定在单个对话范围内。在每个步骤检查点，因此避免写入大文件。
* [StoreBackend](https://reference.langchain.com/python/deepagents/backends/store/StoreBackend)：跨对话持久化的存储。使用[命名空间工厂](/oss/python/deepagents/backends#namespace-factories)界定范围。
* [CompositeBackend](https://reference.langchain.com/python/deepagents/backends/composite/CompositeBackend)：混合两者。默认为临时暂存空间，为特定路径（如 `/memories/`）提供持久化路由。

有关完整的后端列表以及如何构建自定义后端，请参阅[后端](/oss/python/deepagents/backends)。

<Warning>
  `FilesystemBackend` 和 `LocalShellBackend`
  直接访问主机。不要在已部署的智能体中使用它们。
</Warning>

### 沙箱

如果您的智能体需要运行代码（而不仅仅是读写文件），请使用[沙箱](/oss/python/deepagents/sandboxes)。沙箱提供文件系统和用于运行 shell 命令的 `execute` 工具，所有这些都在隔离的容器内。这种隔离也保护了您的主机：如果智能体的代码耗尽内存或崩溃，只有沙箱会受到影响。您的服务器继续运行。

#### 生命周期

关键决策是沙箱存活多久。每次对话都获得一个新的沙箱，还是对话共享一个持久化的环境？

| 范围       | 沙箱 ID 存储在                       | 生命周期             | 示例用例                 |
| -------- | ------------------------------- | ---------------- | -------------------- |
| **线程范围** | [线程](/langsmith/use-threads)元数据 | 每次对话全新，TTL 到期后清理 | 每次对话都从干净状态开始的数据分析机器人 |
| **助手范围** | [助手](/langsmith/assistants)配置   | 跨所有对话共享          | 跨对话维护克隆仓库的编码助手       |

<Note>
  下面的示例使用异步[图工厂](/langsmith/graph-rebuild)而不是静态图，因为沙箱需要
  `thread_id` 或 `assistant_id` 来查找或创建正确的沙箱。图工厂不接收完整的
  `Runtime`（没有 `server_info` 或 `execution_info`）；而是接受 `RunnableConfig`
  并从 `config["configurable"]` 读取 `thread_id` 和
  `assistant_id`。工厂是异步的，因为沙箱创建是一个 I/O
  密集型操作，需要仅在调用时可用的每次运行信息。
</Note>

<Tabs>
  <Tab title="线程范围（最常见）">
    每次对话获得自己的沙箱。[图工厂](/langsmith/graph-rebuild)从运行配置中读取 `thread_id`，因此每个[线程](/langsmith/use-threads)自动获得自己的隔离环境。提供商的基于标签的查找处理跨运行的去重。当沙箱 [TTL](/langsmith/configure-ttl) 到期时清理。

    ```python agent.py theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    from daytona import CreateSandboxFromSnapshotParams, Daytona
    from deepagents import create_deep_agent
    from langchain_core.runnables import RunnableConfig
    from langchain_daytona import DaytonaSandbox

    client = Daytona()


    async def agent(config: RunnableConfig):
        thread_id = config["configurable"]["thread_id"]  # [!code highlight]
        try:
            sandbox = await client.find_one(labels={"thread_id": thread_id})
        except Exception:
            sandbox = await client.create(
                CreateSandboxFromSnapshotParams(
                    labels={"thread_id": thread_id},
                    auto_delete_interval=3600,  # TTL：空闲时清理
                )
            )
        return create_deep_agent(model="google_genai:gemini-3.1-pro-preview", backend=DaytonaSandbox(sandbox=sandbox))
    ```
  </Tab>

  <Tab title="助手范围">
    所有对话共享一个沙箱。[图工厂](/langsmith/graph-rebuild)从 `config["configurable"]` 读取[助手](/langsmith/assistants) ID，因此同一助手上的每个线程都返回到相同的环境。文件、安装的包和克隆的仓库跨对话持久化。

    ```python agent.py theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    from daytona import CreateSandboxFromSnapshotParams, Daytona
    from deepagents import create_deep_agent
    from langchain_core.runnables import RunnableConfig
    from langchain_daytona import DaytonaSandbox

    client = Daytona()


    async def agent(config: RunnableConfig):
        assistant_id = config["configurable"]["assistant_id"]  # [!code highlight]
        try:
            sandbox = await client.find_one(labels={"assistant_id": assistant_id})
        except Exception:
            sandbox = await client.create(
                CreateSandboxFromSnapshotParams(labels={"assistant_id": assistant_id})
            )
        return create_deep_agent(model="google_genai:gemini-3.1-pro-preview", backend=DaytonaSandbox(sandbox=sandbox))
    ```

    <Warning>
      助手范围的沙箱会随着时间的推移积累文件、安装的包和其他沙箱内状态。使用您的沙箱提供商配置 TTL，使用快照定期重置，或实现清理逻辑以防止沙箱的磁盘和内存无限增长。
    </Warning>
  </Tab>
</Tabs>

因为 `agent` 变量是一个异步函数（而不是已编译的图），服务器将其视为[图工厂](/langsmith/graph-rebuild)并在每次运行时调用它，注入配置。工厂通过提供商的基于标签的搜索查找或创建沙箱，并返回一个连接到该沙箱的新智能体图。

使用 `langgraph deploy` 部署后，使用 SDK 从应用程序代码调用智能体。客户端代码无论范围如何都是相同的。范围完全在上面的智能体工厂中处理，但行为有所不同：

<Tabs>
  <Tab title="线程范围">
    每个线程获得自己的沙箱。同一线程内的后续消息重用相同的沙箱，但新线程总是从干净状态开始，没有来自先前对话的遗留文件或安装的包。

    ```python client.py theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    from langgraph_sdk import get_client

    client = get_client(url="<DEPLOYMENT_URL>", api_key="<LANGSMITH_API_KEY>")

    # 对话 1：安装 pandas 并分析数据
    thread_1 = await client.threads.create()
    async for chunk in client.runs.stream(
        thread_1["thread_id"],
        "agent",
        input={"messages": [{"role": "human", "content": "安装 pandas 并分析 sales_data.csv"}]},
        stream_mode="updates",
    ):
        print(chunk.data)

    # 同一对话中的后续消息——pandas 仍然已安装
    async for chunk in client.runs.stream(
        thread_1["thread_id"],
        "agent",
        input={"messages": [{"role": "human", "content": "现在绘制结果"}]},
        stream_mode="updates",
    ):
        print(chunk.data)

    # 对话 2：全新沙箱——pandas 未安装，没有来自对话 1 的文件
    thread_2 = await client.threads.create()
    async for chunk in client.runs.stream(
        thread_2["thread_id"],
        "agent",
        input={"messages": [{"role": "human", "content": "安装了哪些包？"}]},
        stream_mode="updates",
    ):
        print(chunk.data)
    ```
  </Tab>

  <Tab title="助手范围">
    所有线程共享一个沙箱。当沙箱具有重新创建成本高昂的状态（如克隆的仓库、安装的依赖项或构建产物）时，这非常有用。同一助手上的任何对话都可以从上次中断的地方继续，而无需重复设置。

    ```python client.py theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    from langgraph_sdk import get_client

    client = get_client(url="<DEPLOYMENT_URL>", api_key="<LANGSMITH_API_KEY>")

    # 对话 1：克隆并设置项目
    thread_1 = await client.threads.create()
    async for chunk in client.runs.stream(
        thread_1["thread_id"],
        "agent",
        input={"messages": [{"role": "human", "content": "克隆 https://github.com/org/repo 并安装依赖项"}]},
        stream_mode="updates",
    ):
        print(chunk.data)

    # 对话 2：仓库和依赖项仍然存在
    thread_2 = await client.threads.create()
    async for chunk in client.runs.stream(
        thread_2["thread_id"],
        "agent",
        input={"messages": [{"role": "human", "content": "运行测试套件并修复任何失败"}]},
        stream_mode="updates",
    ):
        print(chunk.data)
    ```
  </Tab>
</Tabs>

#### 文件传输

沙箱是隔离的容器，因此您的应用程序代码无法直接访问其中的文件。使用 `upload_files()` 和 `download_files()` 在沙箱边界移动数据：

* **在智能体运行前为沙箱提供种子**：上传用户文件、[技能](/oss/python/deepagents/skills)脚本、配置或[持久化内存](/oss/python/deepagents/memory)，以便智能体从一开始就有它需要的内容
* **智能体完成后检索结果**：下载生成的工件（报告、图表、导出）并将更新的内存同步回来以供将来对话使用

有关特定于提供商的文件传输示例，请参阅[处理文件](/oss/python/deepagents/sandboxes#working-with-files)。有关提供商设置、安全性和生命周期模式，请参阅完整的[沙箱指南](/oss/python/deepagents/sandboxes)。

<Accordion title="示例：使用自定义中间件同步技能和内存">
  智能体需要执行的[技能](/oss/python/deepagents/skills)脚本必须在智能体运行前上传到沙箱中。您可能还想同步[内存](/oss/python/deepagents/memory)，以便智能体可以在容器内读取和更新它们。使用带有 `before_agent` 和 `after_agent` 钩子的[自定义中间件](/oss/python/langchain/middleware/custom)在沙箱边界移动文件：

  ```python agent.py theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
  from deepagents import create_deep_agent
  from langchain.agents.middleware import AgentMiddleware, AgentState
  from langgraph.runtime import Runtime


  def _safe_filename(key: str) -> str:
      """拒绝包含路径遍历或通配符字符的键。"""
      name = key.split("/")[-1]
      if ".." in name or any(c in name for c in ("*", "?")):
          raise ValueError(f"无效的键：{key}")
      return name


  class SandboxSyncMiddleware(AgentMiddleware):
      """在存储和沙箱之间同步技能和内存。"""

      def __init__(self, backend: CompositeBackend):
          super().__init__()
          self.backend = backend

      async def abefore_agent(self, state: AgentState, runtime: Runtime) -> None:
          """将技能脚本和内存上传到沙箱。"""
          user_id = runtime.server_info.user.identity  # [!code highlight]
          store = runtime.store
          files = []
          for item in await store.asearch(("skills", user_id)):
              name = _safe_filename(item.key)
              files.append((f"/skills/{name}", item.value["content"].encode()))
          for item in await store.asearch(("memories", user_id)):
              name = _safe_filename(item.key)
              files.append((f"/memories/{name}", item.value["content"].encode()))
          if files:
              await self.backend.upload_files(files)

      async def aafter_agent(self, state: AgentState, runtime: Runtime) -> None:
          """将更新的内存同步回存储。"""
          user_id = runtime.server_info.user.identity  # [!code highlight]
          store = runtime.store
          items = await store.asearch(("memories", user_id))
          results = await self.backend.download_files(
              [f"/memories/{item.key}" for item in items]
          )
          for result in results:
              if result.content is not None:
                  await store.aput(
                      ("memories", user_id),
                      result.path.split("/")[-1],
                      {"content": result.content.decode()},
                  )


  backend = CompositeBackend(
      default=DaytonaSandbox(sandbox=sandbox),
      routes={
          "/skills/": StoreBackend(
              rt,
              namespace=lambda rt: ("skills", rt.server_info.user.identity),  # [!code highlight]
          ),
          "/memories/": StoreBackend(
              rt,
              namespace=lambda rt: ("memories", rt.server_info.user.identity),  # [!code highlight]
          ),
      },
  )

  agent = create_deep_agent(
      model="google_genai:gemini-3.1-pro-preview",
      backend=backend,
      middleware=[SandboxSyncMiddleware(backend)],
  )
  ```
</Accordion>

#### 管理密钥

沙箱是隔离的容器，因此来自主机的环境变量在其中不可用。有两种方式向沙箱代码提供 API 密钥和其他密钥：

**认证代理（推荐）。** [沙箱认证代理](/langsmith/sandbox-auth-proxy)拦截来自沙箱的出站请求并自动注入认证头。沙箱代码正常调用外部 API，代理根据目标主机添加正确的凭据。这意味着 API 密钥永远不会出现在沙箱代码、环境变量或日志中。

<img src="https://mintcdn.com/other-405835d4/8rovbnQI_RWJV77O/oss/images/deepagents/production/sandbox-auth-proxy.png?fit=max&auto=format&n=8rovbnQI_RWJV77O&q=85&s=52fa07bb40fea3d0288c2149a84955a7" alt="沙箱认证代理将凭据注入出站请求，因此密钥永远不会进入沙箱" width="2110" height="1040" data-path="oss/images/deepagents/production/sandbox-auth-proxy.png" />

```json theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
{
  "proxy_config": {
    "rules": [
      {
        "name": "openai-api",
        "match_hosts": ["api.openai.com"],
        "inject_headers": {
          "Authorization": "Bearer ${OPENAI_API_KEY}"
        }
      },
      {
        "name": "anthropic-api",
        "match_hosts": ["api.anthropic.com"],
        "inject_headers": {
          "x-api-key": "${ANTHROPIC_API_KEY}"
        }
      }
    ]
  }
}
```

`${SECRET_KEY}` 引用根据存储在您 LangSmith [工作区设置](/langsmith/set-up-hierarchy#configure-workspace-settings)中的密钥进行解析。在创建引用它们的模板之前，请在那里配置密钥。

**工作区密钥。** 对于不需要基于代理注入的 API 密钥（例如，智能体服务器本身使用的密钥，而不是沙箱代码），请将它们作为[工作区密钥](/langsmith/set-up-hierarchy#configure-workspace-settings)存储在 LangSmith 中。这些在运行时作为环境变量对工作区中的所有智能体可用。

<Warning>
  避免通过环境变量或文件上传将密钥传递到沙箱中。智能体可以读取沙箱内任何可访问的文件或环境变量，包括凭据。认证代理将密钥完全排除在沙箱之外。
</Warning>

## 防护措施

生产环境中的智能体自主运行，这意味着它们可能无限循环、达到速率限制或处理包含敏感信息的用户数据。深度智能体提供两层保护：

* **[权限](/oss/python/deepagents/permissions)**：声明式的允许/拒绝规则，控制智能体可以读取或写入哪些文件和目录。使用权限将智能体隔离到工作目录、保护敏感文件或强制执行只读内存。
* **[中间件](/oss/python/langchain/middleware/built-in)**：包装模型和工具调用的钩子，用于速率限制、错误处理和数据隐私。

<img src="https://mintcdn.com/other-405835d4/8rovbnQI_RWJV77O/oss/images/deepagents/production/middleware-lifecycle.png?fit=max&auto=format&n=8rovbnQI_RWJV77O&q=85&s=4d730097379f7c31fcaa42ac0178e528" alt="中间件钩子——before_model、wrap_model_call、wrap_tool_call、after_model——包装智能体循环，使策略在每个相关步骤周围确定性地运行" width="2560" height="3040" data-path="oss/images/deepagents/production/middleware-lifecycle.png" />

### 速率限制

这里的速率限制是指在单次运行内限制智能体自身的 LLM 和工具使用，而不是传入请求的 API 网关速率限制。

没有限制，一个混乱的智能体可以通过循环调用同一个工具或进行数百次模型调用，在几分钟内耗尽您的 LLM API 预算。设置每次运行的模型调用和工具执行上限：

```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
from deepagents import create_deep_agent
from langchain.agents.middleware import ModelCallLimitMiddleware, ToolCallLimitMiddleware

agent = create_deep_agent(
    model="google_genai:gemini-3.1-pro-preview",
    middleware=[
        ModelCallLimitMiddleware(run_limit=50),
        ToolCallLimitMiddleware(run_limit=200),
    ],
)
```

使用 `run_limit` 限制单次调用内的调用次数（每次轮次重置）。使用 `thread_limit` 限制整个对话中的调用次数（需要检查点）。有关完整配置，请参阅 [ModelCallLimitMiddleware](https://reference.langchain.com/python/langchain/agents/middleware/model_call_limit/ModelCallLimitMiddleware) 和 [ToolCallLimitMiddleware](https://reference.langchain.com/python/langchain/agents/middleware/tool_call_limit/ToolCallLimitMiddleware)。

### 处理错误

并非所有错误都应以相同方式处理。瞬时故障（网络超时、速率限制）应自动重试。LLM 可以恢复的错误（错误的工具输出、解析失败）应反馈给模型。需要人工输入的错误应暂停智能体。有关完整的分解和代码示例，请参阅[适当处理错误](/oss/python/langgraph/thinking-in-langgraph#handle-errors-appropriately)。

中间件处理瞬时情况。模型调用和工具调用各自有自己的重试中间件，具有指数退避。如果您的主要模型提供商完全宕机，回退中间件会切换到替代方案：

```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
from deepagents import create_deep_agent
from langchain.agents.middleware import (
    ModelFallbackMiddleware,
    ModelRetryMiddleware,
    ToolRetryMiddleware,
)

agent = create_deep_agent(
    model="google_genai:gemini-3.1-pro-preview",
    middleware=[
        # 在速率限制、超时和 5xx 错误时重试模型调用
        ModelRetryMiddleware(max_retries=3, backoff_factor=2.0, initial_delay=1.0),
        # 如果主模型完全宕机，回退到替代方案
        ModelFallbackMiddleware("gpt-5.4"),
        # 重试调用外部 API 的特定工具（不是所有工具）
        ToolRetryMiddleware(
            max_retries=2,
            tools=["search", "fetch_url"],
            retry_on=(TimeoutError, ConnectionError),
        ),
    ],
)
```

将 [ToolRetryMiddleware](https://reference.langchain.com/python/langchain/agents/middleware/tool_retry/ToolRetryMiddleware) 限定到特定工具，而不是重试所有工具。失败的文件系统 `read_file` 不会从重试中受益，但超时的网络搜索可能会。有关完整配置，请参阅 [ModelRetryMiddleware](https://reference.langchain.com/python/langchain/agents/middleware/model_retry/ModelRetryMiddleware) 和 [ModelFallbackMiddleware](https://reference.langchain.com/python/langchain/agents/middleware/model_fallback/ModelFallbackMiddleware)。

### 数据隐私

如果您的智能体处理可能包含电子邮件、信用卡号或其他 PII 的用户输入，您可以在它到达模型或存储在日志中之前检测并处理它：

```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
from deepagents import create_deep_agent
from langchain.agents.middleware import PIIMiddleware

agent = create_deep_agent(
    model="google_genai:gemini-3.1-pro-preview",
    middleware=[
        PIIMiddleware("email", strategy="redact", apply_to_input=True),
        PIIMiddleware("credit_card", strategy="mask", apply_to_input=True),
    ],
)
```

策略包括 `redact`（替换为 `[REDACTED_EMAIL]`）、`mask`（部分掩码，如 `****-****-****-1234`）、`hash`（确定性哈希）和 `block`（引发错误）。您还可以为特定领域的模式编写自定义检测器。
有关完整配置，请参阅 [PIIMiddleware](https://reference.langchain.com/python/langchain/agents/middleware/pii/PIIMiddleware)。

有关可用中间件的完整列表，请参阅[预构建中间件](/oss/python/langchain/middleware/built-in)。

## 前端

深度智能体使用 [`useStream`](/oss/python/langchain/frontend/overview) 将您的 UI 连接到智能体后端。`useStream` 是一个前端钩子（适用于 React、Vue、Svelte 和 Angular），可实时从您的智能体流式传输消息、子智能体进度和自定义状态。

在本地，`useStream` 指向 `http://localhost:2024`。在生产环境中，将其指向您的 [LangSmith 部署](/langsmith/deployment)并配置重连，以便用户在连接中断时不会丢失进度。

```tsx theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
import { useStream } from "@langchain/react";

function App() {
  const stream = useStream<typeof agent>({
    apiUrl: "https://your-deployment.langsmith.dev",
    assistantId: "agent",
    reconnectOnMount: true, // 页面刷新或导航后恢复流
    fetchStateHistory: true, // 挂载时加载完整的线程历史记录
  });
}
```

`reconnectOnMount` 会自动接取正在进行的运行。如果用户在智能体工作时刷新页面，他们会看到它继续而不是空白屏幕。`fetchStateHistory` 加载线程的完整对话历史记录，因此返回的用户会看到之前的消息。

对于生成许多子智能体的深度智能体工作流，在提交时设置较高的 `recursionLimit` 以避免切断长时间运行的执行：

```tsx theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
stream.submit(
  { messages: [{ type: "human", content: text }] },
  {
    streamSubgraphs: true,
    config: { recursionLimit: 10000 },
  },
);
```

有关深度智能体特有的 UI 模式，如子智能体卡片、待办事项列表和自定义状态渲染，请参阅[前端指南](/oss/python/deepagents/frontend/overview)。

***

<div className="source-links">
  <Callout icon="terminal-2">
    [通过 MCP 将这些文档](/use-these-docs)连接到 Claude、VSCode
    等，以获取实时答案。
  </Callout>

  <Callout icon="edit">
    [在 GitHub
    上编辑此页面](https://github.com/langchain-ai/docs/edit/main/src/oss/deepagents/going-to-production.mdx)
    或 [提交问题](https://github.com/langchain-ai/docs/issues/new/choose)。
  </Callout>
</div>
