资讯动态

用 OpenAI Agents SDK 的 E2BSandboxClient 对接 CubeSandbox:从最简 Shell Agent 到 SWE-bench 调试实战

发布时间:2026/9/16 16:08:19 来源:尧图企业网站定制
用 OpenAI Agents SDK 的 E2BSandboxClient 对接 CubeSandbox从最简 Shell Agent 到 SWE-bench 调试实战【免费下载链接】CubeSandboxInstant, Concurrent, Secure Lightweight Sandbox for AI Agents.项目地址: https://gitcode.com/GitHub_Trending/cu/CubeSandbox本指南以仓库 examples/openai-agents-example 下的两个可运行示例为线索系统讲解如何将 OpenAI Agents SDK 的官方E2BSandboxClient直接对接 CubeSandbox 的 CubeAPIE2B 兼容协议并落地为可复用的 Agent 沙箱方案。读完本文你将掌握环境配置与模板创建、最简 Shell Agent 的接入方式、Pause/Resume 状态恢复验证以及一个具备 LLM 预检、流式输出与全链路追踪的 SWE-bench 调试 Agent 的完整实现思路。示例概览两个脚本两种场景本目录包含两个示例脚本均通过 OpenAI Agents SDK 的E2BSandboxClient对接 CubeSandbox区别在于复杂度和使用场景脚本场景说明simple_demo.py快速上手最简 Shell Agent Pause/Resume 演示main.pySWE-bench 调试完整流式输出 LLM 预检 全链路追踪两者共享同一套「CubeSandbox 适配层」由于 CubeAPI 实现了与 E2B 兼容的 API无需自己编写 Sandbox Provider只需将E2B_API_URL指向 CubeAPI 服务地址即可复用官方客户端。这一点在 CubeAPI 的源码中也有印证——例如 CubeAPI/src/services/sandboxes.rs 注释明确说明“Convert e2b-style volumeMounts into the CubeMaster wire format”并在 CubeAPI/src/services/sandboxes.rs 附近处理 e2b SDK 的请求体形状保证协议层兼容。前置条件Python 3.10CubeSandbox 平台已部署CubeAPI 可访问已创建沙箱模板见下方「模板创建」TokenHub 或其他 OpenAI 兼容 LLM 服务的 API Key快速开始1. 安装依赖pip install -r requirements.txtrequirements.txt 内容极简只有两个依赖openai-agents[e2b]带 E2B 扩展的 Agents SDK 本体和python-dotenv用于读取.env配置文件。其中[e2b]扩展是关键它提供了下文用到的E2BSandboxClient、E2BSandboxClientOptions、E2BSandboxType等组件。2. 配置环境变量cp .env.example .env.env的模板位于 examples/openai-agents-example/.env.example各变量说明如下变量说明TOKENHUB_API_KEYTokenHub API Key自动映射为OPENAI_API_KEYOPENAI_BASE_URLLLM 地址默认https://tokenhub.tencentmaas.com/v1E2B_API_URLCubeAPI 地址如http://cube-host:3000E2B_API_KEYCubeAPI 鉴权 KeyCUBE_TEMPLATE_ID沙箱模板 IDCUBE_SSL_CERT_FILE可选CubeSandbox CA 证书路径从 simple_demo.py 的load_env()实现可以看到几个细节TOKENHUB_API_KEY只有在OPENAI_API_KEY未设置时才会被映射过去优先级是显式设置优先OPENAI_BASE_URL未设置时默认指向https://tokenhub.tencentmaas.com/v1启动时会强制检查必需变量普通 Agent 模式要求OPENAI_API_KEY、E2B_API_KEY、E2B_API_URL三者齐全Pause/Resume 模式只需要后两者不需要 LLM若设置了CUBE_SSL_CERT_FILE且文件真实存在会将其写入SSL_CERT_FILE环境变量供 CubeSandbox 的 gRPC 通道使用。3. 创建沙箱模板simple_demo.py可用任意 Linux 模板。main.py需要预装 Django 源码的 SWE-bench 镜像cubemastercli tpl create-from-image \ --image cube-sandbox-image.tencentcloudcr.com/demo/django_1776_django-13447:latest \ --writable-layer-size 1G \ --expose-port 49983 \ --cpu 4000 --memory 8192 \ --probe 49983命令输出中的模板 ID 填入.env的CUBE_TEMPLATE_ID。其中--writable-layer-size 1G为沙箱分配可写层容量Agent 在沙箱内的文件写入都落在这层--expose-port 49983暴露 envd 服务端口OpenAI Agents SDK 正是通过该端口下发exec/write/read指令--probe 49983设置健康探针端口用于模板就绪检测。simple_demo.py — 最简示例最小化的 Shell Agent展示 CubeSandbox 集成的核心步骤。整个脚本只有约 320 行是理解「Agents SDK × CubeSandbox」最小闭环的最佳起点。用法# 基础 Agent 问答 python simple_demo.py python simple_demo.py --question What Linux distro is this? # Pause / Resume 演示写入文件 → 暂停 → 恢复 → 验证文件 python simple_demo.py --pause-resume # SSL 调试模式 python simple_demo.py --no-ssl-patch # 禁用所有 SSL 自定义 python simple_demo.py --llm-cube-ssl # LLM 也用 cube 的证书参数参数默认值说明--modelopenai/glm-5.1LLM 模型名--question查看 OS 版本发送给 Agent 的问题--templateCUBE_TEMPLATE_ID沙箱模板 ID--timeout300沙箱超时秒--pause-resume—切换到 Pause/Resume 演示模式--no-ssl-patch—禁用 SSL 自定义处理--llm-cube-ssl—LLM 客户端也使用 cube 证书关于默认值有两个值得注意的实现细节见 simple_demo.py--question的实际默认值比文档描述更完整——是What OS is running? Show uname and the first 3 lines of /etc/os-release.引导 Agent 使用uname和读取/etc/os-release两个命令来回答模板 ID 的解析优先级是--template命令行参数 CUBE_TEMPLATE_ID环境变量两者都缺失时脚本会直接SystemExit报错避免创建出错误的沙箱。核心代码agent SandboxAgent( nameCube Demo Agent, modelmake_model(openai/glm-5.1), instructionsYou are a helpful assistant running inside a cloud sandbox., default_manifestManifest(), capabilities[Shell()], ) run_config RunConfig( sandboxSandboxRunConfig( clientE2BSandboxClient(), optionsE2BSandboxClientOptions( sandbox_typeE2BSandboxType.E2B, templateos.environ[CUBE_TEMPLATE_ID], timeout300, ), ), ) result await Runner.run(agent, What OS is running?, run_configrun_config)对照 simple_demo.py 的完整实现实际代码还多设置了两项instructions末尾追加了Use shell commands to explore the environment and answer questions. Be concise.明确引导 Agent 通过 Shell 探索环境而非凭空猜测model_settingsModelSettings(tool_choiceauto)显式开启工具自动选择允许 Agent 在需要时自主调用 Shell 工具。这里make_model()是关键封装见 simple_demo.py它把模型名中的openai/前缀剥离为裸名如glm-5.1并强制构造OpenAIChatCompletionsModel实例。原因后文「CubeSandbox 适配」会详细展开。Pause/Resume 流程[step 1] 创建沙箱 [step 2] 写入标记文件 pause-resume-test.txt [step 3] 暂停沙箱stop shutdown, pause_on_exitTrue [step 4] 恢复沙箱client.resume [step 5] 读取文件验证内容一致 → PASS / FAIL [cleanup] 销毁沙箱这段流程在 simple_demo.py 的run_pause_resume()中有完整实现几个关键点创建与启动分离client.create(options..., manifestManifest())创建沙箱实例并拿到sandbox_id随后显式调用await session.start()完成启动两阶段各自计时打印暂停语义创建时E2BSandboxClientOptions(pause_on_exitTrue)暂停时先session.stop()再session.shutdown()由于pause_on_exitTrueshutdown 会保留沙箱状态而非销毁恢复语义client.resume(saved_state)使用暂停前保存的session.state恢复出resumed_session再start()启动验证内容恢复后通过read读取标记文件与期望内容cube sandbox pause/resume works!\n逐字符比对一致输出PASS否则输出FAIL清理销毁前先把resumed_session.state.pause_on_exit置为False确保shutdown()是真正销毁而非再次暂停。这个流程直接验证了 CubeSandbox 的「暂停后状态保留」能力——沙箱中的文件系统状态在 stop/resume 周期后依然完整这正是面向人工审核、长时任务续跑等场景的基石。main.py — SWE-bench Django 调试完整的 SWE-bench Agent在沙箱中自主分析 Django Bug 并提出修复方案。包含 LLM 预检、流式输出、全链路追踪是前一个示例在生产级场景下的进阶形态。用法# 分析 Django Bugdjango__django-13447 python main.py # 自定义问题 python main.py --question What Python version is installed? Show the Django version too. # 指定模型 python main.py --model openai/deepseek-v3.2 # 仅测试沙箱连通性不调用 LLM python main.py --sandbox-only python main.py --sandbox-only --timeout 60 # 限制工具调用轮数 python main.py --max-turns 20参数参数默认值说明--modelopenai/glm-5.1LLM 模型名TokenHub 用openai/前缀--question分析 Bug 并修复发送给 Agent 的问题--templateCUBE_TEMPLATE_IDSWE-bench Django 模板 ID--timeout300沙箱超时秒--max-turns50最大工具调用轮数--sandbox-only—仅创建/销毁沙箱验证连通性从 main.py 的参数解析代码看--sandbox-only模式会跳过OPENAI_API_KEY的校验只要求E2B_API_KEY与E2B_API_URL并直接走run_sandbox_only()——创建沙箱 → 执行uname -a cat /etc/os-release | head -3健康检查 → 销毁沙箱。这个模式非常适合在调试阶段快速验证 CubeAPI 连通性与模板可用性完全不依赖 LLM。内置功能LLM 预检正式运行前验证 LLM 连通性。实现位于 main.py 的_preflight_llm()分三个阶段递进纯文本plain非流式调用chat.completions.createmax_tokens5验证最基本的连通性工具调用tool-calling附带一个get_info({cmd: uname})的函数定义验证 Function Calling 链路是否可用——这是 Agent 后续依赖 Shell 工具的前提流式streaming以streamTrue请求并逐 chunk 消费验证流式输出能力。任一阶段失败都会打印耗时并SystemExit(1)退出避免带着坏配置进入漫长的 Agent 运行。流式输出实时打印 Agent 的每一步操作[preflight] 1/3 plain ok — glm-5.1 https://tokenhub.tencentmaas.com/v1/ 856 ms [preflight] 2/3 tool-call ok — 1204 ms: get_info({cmd:uname}) [preflight] 3/3 streaming ok — 623 ms, 12 chunks [status] creating sandbox starting session ... [agent] SWE-bench Agent running [step 1] tool_call: exec_command({cmd: cat /testbed/django/contrib/admin/...}) → output: ... [step 2] tool_call: exec_command({cmd: grep -n items_for_result ...}) → output: ... [answer] The bug is in the items_for_result function ... [done] 8 tool calls, 42350 ms total这套输出的实现值得借鉴见 main.py脚本用Runner.run_streamed()拿到事件流然后按事件类型分流处理——agent_updated_stream_event打印 Agent 状态、run_item_stream_event中的tool_called/tool_output打印工具调用与输出超过 200/300 字符的调用参数与输出会被截断显示、raw_response_event中的ResponseTextDeltaEvent以流式方式打印最终答案。同时通过_watch_task()协程监视后台 run loop 的异常避免静默崩溃。全链路追踪自动记录 E2B 生命周期create/start/exec/shutdown和 LLM 调用HTTP 请求/响应、首个 token 延迟的耗时。实现方式是模块级的 monkey-patch见 main.py包装E2BSandboxClient.create在创建沙箱后进一步包装 session 的start、exec、stop、shutdown、running、run_pre_stop_hooks六个生命周期方法每个方法打印「调用 → 耗时 → 完成/失败」包装OpenAIChatCompletionsModel.stream_response——注意这是一个异步生成器yield 事件patch 时需用async for逐事件转发并记录首个事件到达耗时即 first token latency底层 LLM HTTP 客户端见_llm_http_client()main.py通过 httpx 的event_hooks打印每个请求的方法、URL、字节数以及响应状态码和耗时。防挂超时LLM 回答后 30 秒无新事件自动退出。这是对 OpenAI Agents SDK 已知行为Runner 内部 finalization 阶段可能无限挂起的工程规避事件消费循环使用asyncio.wait_for设置超时——在收到答案前超时阈值是--timeout默认 300 秒收到答案后收紧为 30 秒的 idle timeout一旦超时便跳出循环正常结束同时打印[done]汇总工具调用轮数与总耗时。SWE-bench 场景说明默认任务是django__django-13447当ModelAdmin设置list_display_links None时Django admin 仍然为第一个字段生成链接应该显示为纯文本。Agent 会在/testbed/django/contrib/admin/templatetags/admin_list.py中定位items_for_result函数分析 Bug 根因提出修复方案沙箱模板镜像中/testbed包含完整的 Django 源码。对照 main.py 的实现Bug 描述被定义为DJANGO_BUG_DESCRIPTION常量并注入到 Agent 的instructions中同时还附加了明确的任务步骤定位函数 → 分析根因 → 提出修复和约束“Use shell commands to explore the codebase, read files, and run tests. Be concise and cite the exact file paths and line numbers you inspected.”。另一个细节是build_agent()中设置了default_manifestManifest(root/testbed)将工作区根目录指向/testbed使 Agent 可以以相对路径直接访问 Django 源码。CubeSandbox 适配两个脚本都包含以下运行时补丁补丁原因default_username root Filesystem 方法包装CubeSandbox envd 只服务root用户Commands.run移除stdin参数兼容老版本 envdLLM 客户端使用系统 CA bundle避免SSL_CERT_FILEcube gRPC污染 TokenHub HTTPS强制使用OpenAIChatCompletionsModelTokenHub 不支持 Responses API这些补丁在 simple_demo.py 与 main.py 中完全一致具体实现机理如下root 用户适配先通过_e2b_rpc.default_username root修改 RPC 层默认用户随后用inspect.signature动态检查Filesystem各方法的user参数位置用装饰器把userNone强制替换为root。被包装的方法覆盖read、write、write_files、list、exists、get_info、remove、rename、make_dir、watch_dir十个常用文件系统操作stdin 参数兼容包装Commands.run通过self._envd_version与ENVD_COMMANDS_STDIN常量比较当 envd 版本低于支持stdin的版本时直接丢弃该 kwargs——这是为老版本 envd 的兼容处理SSL 隔离CubeSandbox 的 gRPC 需要自定义 CACUBE_SSL_CERT_FILE→SSL_CERT_FILE但全局的SSL_CERT_FILE会破坏 TokenHub 的公网 HTTPS 请求。解法是给 LLM 客户端显式构造ssl.create_default_context()系统 CA 库并通过httpx.AsyncClient(verifyssl_ctx)注入使其不受SSL_CERT_FILE影响--llm-cube-ssl反向测试 cube 证书是否也能被 TokenHub 信任--no-ssl-patch则完全关闭所有自定义Chat Completions 强制适配当直接向SandboxAgent传模型字符串时Agents SDK 默认走 Responses APIPOST /v1/responses而 TokenHub 这类 OpenAI 兼容服务只支持 Chat Completions APIPOST /v1/chat/completions会导致挂起或 404。因此两个脚本都手动构造OpenAIChatCompletionsModel(model裸模型名, openai_clientclient)确保走兼容协议。详细说明见 集成指南其中还覆盖了 Code InterpreterJupyter kernel形态的对接方式与模板要求。相关文档OpenAI Agents SDK × CubeSandbox 集成指南从架构图、集成总览到 Code Interpreter 两种形态的完整对接文档OpenAI Sandbox Agents 概念解析Manifest、Capabilities、状态管理与 Provider 体系的背景知识simple_demo.py最简 Shell Agent 与 Pause/Resume 验证的完整源码main.pySWE-bench 调试 Agent 的完整源码预检、追踪、防挂超时.env.example环境变量模板【免费下载链接】CubeSandboxInstant, Concurrent, Secure Lightweight Sandbox for AI Agents.项目地址: https://gitcode.com/GitHub_Trending/cu/CubeSandbox创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价