智能体在您的机器或服务器上运行。当需要执行代码时,它调用沙盒工具(如 execute、read_file 或 write_file),这些工具会调用提供商的 API 在远程沙盒中运行操作。优势:
✅ 无需重建镜像即可立即更新智能体代码。
✅ 智能体状态与执行之间的清晰分离。
API 密钥保留在沙盒外。
沙盒故障不会丢失智能体状态。
可以选择在多个沙盒中并行运行任务。
✅ 仅为执行时间付费。
劣势:
🔴 每次执行调用都有网络延迟。
示例:
Copy
from dotenv import load_dotenvfrom daytona import Daytonafrom langchain_daytona import DaytonaSandboxfrom deepagents import create_deep_agentload_dotenv()# Can also do this with E2B, Runloop, Modalsandbox = Daytona().create()backend = DaytonaSandbox(sandbox=sandbox)agent = create_deep_agent( backend=backend, system_prompt="You are a coding assistant with sandbox access. You can create and run code in the sandbox.",)try: result = agent.invoke( { "messages": [ { "role": "user", "content": "Create a hello world Python script and run it", } ] } ) print(result["messages"][-1].content)except Exception: # Optional: delete the sandbox proactively on an exception sandbox.stop() raise
本文档中的示例使用沙盒作为工具模式。
当提供商的 SDK 处理通信层且您希望生产环境与本地开发一致时,选择智能体在沙盒内模式。
当您需要快速迭代智能体逻辑、将 API 密钥保留在沙盒外,或偏好更清晰的关注点分离时,选择沙盒作为工具模式。
import modalfrom langchain_modal import ModalSandboxapp = modal.App.lookup("your-app")modal_sandbox = modal.Sandbox.create(app=app)backend = ModalSandbox(sandbox=modal_sandbox)results = backend.download_files(["/src/index.py", "/output.txt"])for result in results: if result.content is not None: print(f"{result.path}: {result.content.decode()}") else: print(f"Failed to download {result.path}: {result.error}")
Copy
pip install langchain-runloop
Copy
from runloop_api_client import RunloopSDKfrom langchain_runloop import RunloopSandboxapi_key = "..."client = RunloopSDK(bearer_token=api_key)devbox = client.devbox.create()backend = RunloopSandbox(devbox=devbox)results = backend.download_files(["/src/index.py", "/output.txt"])for result in results: if result.content is not None: print(f"{result.path}: {result.content.decode()}") else: print(f"Failed to download {result.path}: {result.error}")
Copy
pip install langchain-daytona
Copy
from daytona import Daytonafrom langchain_daytona import DaytonaSandboxsandbox = Daytona().create()backend = DaytonaSandbox(sandbox=sandbox)results = backend.download_files(["/src/index.py", "/output.txt"])for result in results: if result.content is not None: print(f"{result.path}: {result.content.decode()}") else: print(f"Failed to download {result.path}: {result.error}")
在聊天应用中,对话通常由 thread_id 表示。
一般而言,每个 thread_id 应使用其专属的沙盒。在您的应用中存储沙盒 ID 与 thread_id 的映射,或者如果沙盒提供商允许为沙盒附加元数据,则将映射存储在沙盒中。以下示例展示了使用 Daytona 的获取或创建模式。
对于其他提供商,请查阅沙盒提供商 API 以了解等效的标签、元数据和 TTL 选项:
Copy
import uuidfrom daytona import CreateSandboxFromSnapshotParams, Daytonafrom langchain_daytona import DaytonaSandboxclient = Daytona()thread_id = str(uuid.uuid4())from deepagents import create_deep_agent# Get or create sandbox by thread_idtry: sandbox = client.find_one(labels={"thread_id": thread_id})except Exception: params = CreateSandboxFromSnapshotParams( labels={"thread_id": thread_id}, # Add TTL so the sandbox is cleaned up when idle auto_delete_interval=3600, ) sandbox = client.create(params)backend = DaytonaSandbox(sandbox=sandbox)agent = create_deep_agent( backend=backend, system_prompt="You are a coding assistant with sandbox access. You can create and run code in the sandbox.",)try: result = agent.invoke( { "messages": [ { "role": "user", "content": "Create a hello world Python script and run it", } ] }, config={ "configurable": { "thread_id": thread_id, } }, ) print(result["messages"][-1].content)except Exception: # Optional: delete the sandbox proactively on an exception client.delete(sandbox) raise