diff --git a/.agents/README.md b/.agents/README.md index 3301e112..7adf2618 100644 --- a/.agents/README.md +++ b/.agents/README.md @@ -168,4 +168,5 @@ Builtin transport: [direct HTTP](notes/implemented/architecture/2026-10-18-nativ - [Command execution deadline](notes/proposed/feature/2026-10-25-command-execution-deadline.md) · [verification](evidence/verify/2026-10-25-command-execution-deadline.md) +- [Current public SDK documentation](notes/proposed/process/2026-10-25-public-sdk-documentation.md) · [verification](evidence/verify/2026-10-25-public-sdk-documentation.md) - [Bounded public PyPI readback](notes/proposed/process/2026-10-25-pypi-public-readback.md) · [verification](evidence/verify/2026-10-25-pypi-public-readback.md) diff --git a/.agents/evidence/verify/2026-10-25-public-sdk-documentation-benchmark.json b/.agents/evidence/verify/2026-10-25-public-sdk-documentation-benchmark.json new file mode 100644 index 00000000..84a6b826 --- /dev/null +++ b/.agents/evidence/verify/2026-10-25-public-sdk-documentation-benchmark.json @@ -0,0 +1,11 @@ +{ + "source": "client-sdk/benchmarks/bench_create.py", + "source_sha256": "2927f443f4ac89c57e5f2961f267a96d7cf66b94c326c44953faa0248c6e5637", + "public_client_server": "0.4.0a2", + "source_path_injection": false, + "actual_source_public_kwargs_sentinel_binding": true, + "owned_created": 3, + "independent_get_info_typed404": 3, + "result": "PASS", + "seconds": 4.47 +} diff --git a/.agents/evidence/verify/2026-10-25-public-sdk-documentation-cloud.json b/.agents/evidence/verify/2026-10-25-public-sdk-documentation-cloud.json new file mode 100644 index 00000000..b7366061 --- /dev/null +++ b/.agents/evidence/verify/2026-10-25-public-sdk-documentation-cloud.json @@ -0,0 +1,35 @@ +{ + "public_packages": "0.4.0a2", + "cases": [ + { + "guide": "docs/en/guide/getting-started.md", + "sha256": "3b4dee410a0d373cb1841111e3693b77045ef8718172356706aed1c1f5405ab2", + "status": "PASS", + "operations": [ + "create", + "command", + "file write/read", + "download", + "upload", + "kill on context exit", + "independent typed absence" + ], + "owned_cleanup": "PASS" + }, + { + "guide": "docs/zh/guide/getting-started.md", + "sha256": "ce3b8b9dd36b6131f29f4186c1076b2cdc6d68caa6f28e97d1fbd98e8a8b2c6d", + "status": "PASS", + "operations": [ + "create", + "command", + "file write/read", + "download", + "upload", + "kill on context exit", + "independent typed absence" + ], + "owned_cleanup": "PASS" + } + ] +} diff --git a/.agents/evidence/verify/2026-10-25-public-sdk-documentation-index.json b/.agents/evidence/verify/2026-10-25-public-sdk-documentation-index.json new file mode 100644 index 00000000..b35f0ce9 --- /dev/null +++ b/.agents/evidence/verify/2026-10-25-public-sdk-documentation-index.json @@ -0,0 +1,7 @@ +{ + "package": "agent-sandbox-server==0.4.0a2", + "configured_index": "https://example.invalid/simple", + "explicit_index": "https://pypi.org/simple", + "download": "PASS", + "original_public_wheel_sha256_equal": true +} diff --git a/.agents/evidence/verify/2026-10-25-public-sdk-documentation-migration.json b/.agents/evidence/verify/2026-10-25-public-sdk-documentation-migration.json new file mode 100644 index 00000000..de7ef7ff --- /dev/null +++ b/.agents/evidence/verify/2026-10-25-public-sdk-documentation-migration.json @@ -0,0 +1,36 @@ +{ + "source": "examples/compat-demos/e2b_import_migration.py", + "source_sha256": "73850fb33989c4b412ce5399f2303df1ca642ad5d15fe6cbd8088e7ef0819415", + "source_commit": "c8f5d48dc015b6bdcb65455285c651edf8c1eafd", + "installed_packages": { + "agent-sandbox-client": "0.4.0a2", + "agent-sandbox-server": "0.4.0a2" + }, + "credential_names": [ + "ABX_SANDBOX_API_KEY", + "ABX_SANDBOX_BASE_URL", + "ABX_SANDBOX_DOMAIN" + ], + "E2B_environment_set": false, + "result": "PASS", + "seconds": 4.27, + "checks": [ + "standard sync create", + "file write/read", + "shell exit/output", + "persistent interpreter 41 to 42", + "owned context kill", + "independent get_info typed404" + ], + "audit": { + "created": 1, + "cleanup": [ + { + "absent_before_cleanup": true, + "absent_after_cleanup": true + } + ], + "example_exit": 0 + }, + "owned_cleanup": "PASS" +} diff --git a/.agents/evidence/verify/2026-10-25-public-sdk-documentation.md b/.agents/evidence/verify/2026-10-25-public-sdk-documentation.md new file mode 100644 index 00000000..9aa7215c --- /dev/null +++ b/.agents/evidence/verify/2026-10-25-public-sdk-documentation.md @@ -0,0 +1,138 @@ +# Verification: current public SDK documentation + +- Date: 2026-10-25 +- Tested base: dab0e3194e3f790fab28307d9fd126b8239bcbd7 plus scoped documentation changes. +- Package under test: official PyPI agent-sandbox-client/server 0.4.0a2. +- Environment: Linux, fresh Python 3.13.13 venv, Express account configured via + canonical environment variables; values and resource IDs are not recorded. +- Result: PASS for documentation-specific execution below; broader example suite + remains PARTIAL because the browser cold installation failed. + +## From-page real execution + +- Install: fresh venv, official-index exact `agent-sandbox-client==0.4.0a2`, pip + check, public sync/async/provider/server imports all PASS. Both distribution + versions are exactly 0.4.0a2. Source import injection was not used. +- Extract the first Python fence from each actual `getting-started.md` page, + save it as a script outside the checkout and run with the fresh environment. + Both complete scripts PASS: create base, command output/exit status, file + write/read, download, upload, content equality and context-manager kill. +- Independently call `ProviderSandbox.get_info_by_id` for each created ID: + typed `SandboxNotFoundError` PASS. No owned sandboxes remain. +- [Machine-readable source hashes and results](2026-10-25-public-sdk-documentation-cloud.json). + +## Public signature and local HTTP execution + +- Inspect published `sandbox` and `create_mcp_app` signatures: sandbox_api_key, + sandbox_base_url and sandbox_domain present; api_key/api_url/domain absent. +- Confirm native `ProviderSandbox.create_sync` remains callable; retain it. +- Install exact `agent-sandbox-client[mcp]==0.4.0a2` from official PyPI, as the + HTTP guide requires. Construct its documented create_mcp_app with the corrected + sandbox_api_key argument: real ASGI `/health` 200 and unauthenticated `/mcp` 401 PASS. +- Construct a decorator with all three canonical configuration arguments: PASS. + This only validates configuration, not another remote function execution. + +## Independent broader public example rerun + +The maintainer's new public-a2 rerun executed all fourteen cloud examples: thirteen +PASS; browser example FAIL while installing Chromium and dependencies on base +under its 300-second command deadline (406.73 seconds total including preceding pip). +Every owned sandbox was independently confirmed absent with typed 404. The real +Qwen-generated sorting example passed. Local protocol fixtures are not real agent +executions. These observations do not certify a new template image or the entire +template matrix. The failure is retained, and browser setup/default-template policy +is pending user choice. This documentation change does not close +[Issue 111](https://github.com/Alibaba-Agent-Sandbox/python-sdk/issues/111). + +## Published deadline verification + +The independent public-a2 check observed typed CommandTimeout for silent output +(1.353 seconds) and continuous output (1.159 seconds). Each exact observed owned +PID was absent from process.list afterwards, a subsequent command worked, and +the owned sandbox was independently absent with typed 404. This closes the runtime +deadline acceptance scope of [Issue 113](https://github.com/Alibaba-Agent-Sandbox/python-sdk/issues/113), +separately from the unfinished browser scope in Issue 111. + +## Unverified comparison claims removed + +Replace the comparison page's unsupported startup-time, GPU, lifetime, competitor +infrastructure/pricing and stale tool-count assertions with actual project entry +contracts and prerequisites. Keep standard interpreter, base command/file and +launched application examples distinct. No competitor capability claim or new +benchmark is introduced. Main README and contributor entry points recommend +unified launch; image build/deploy remain advanced preparation steps. + +## Example README correction + +The EN/ZH core API overview previously put interpreter and hello named-command +calls inside a base ProviderSandbox context. Split this confirmed misleading +example into base shell execution, the actual standard interpreter entry, and +a separately launched python-hello application bound with application_client(token). +No runtime helper or fallback is added. Correct the example table, decorator +template ID, writable file path and canonical configuration wording together. + +## Repository skills + +The current SDK/provider SKILL.md files now use published a2 instead of claiming +a1 is awaiting publication. Their installation/Dockerfile pins and shared ABX +configuration agree with the user guides. Original public client/server wheels +and sdists contain neither skill file, so this Git documentation fix does not +replace or require rebuilding the immutable published a2 artifacts. + +## Static checks and limits + +- PASS: repository health 106 PASS / 1 warning / 0 failures; hygiene PASS. +- PASS: scan maintained docs/READMEs for retired Git-archive install pins and old + decorator/MCP keywords. Historical explicitly retired provider-engine design and + merged evidence remain history; actual third-party api_key/domain options remain. +- Follow-up review: canonical ABX configuration is supported by all project + entries, including standard sync/async/interpreter; it is not ProviderSandbox-only. + Corrected this wording in the installation, beginner, migration and example guides. + Standard public api_key parameters and real third-party E2B configuration remain valid. + The import-migration example changes only its configuration docstring, not code. +- Documentation-only change: no product runtime or test implementation changed. + Full package CI remains enforced by the PR; unrelated cloud matrix is not rerun + merely for prose. CLI source preparation and new application images are being + separately verified by their owning repositories; no new success claim is made here. + +## Final official-index and benchmark follow-up + +A real template build found the Alibaba base-image pip mirror still listing only +a1. All maintained first-party public install instructions now explicitly select +`https://pypi.org/simple`, including skill Dockerfiles and package READMEs. No +source fallback or retry is added. A real pip download with an intentionally +different configured index succeeded through the explicit official index and +matched the original public a2 server wheel digest. + +The maintained release guide now states actual published a2 facts and requires a +new reviewed lockstep tag for a future release, rather than calling a1 unreleased. + +The creation benchmark used obsolete TransportConfig api_key/api_url/domain +arguments. Actual public a2 construction silently ignored all three sentinel +values. The benchmark now uses the explicit public ProviderSandbox entry and +canonical parameters with the normally installed package. It creates three fixed +samples, deletes and closes each owned sandbox before the next iteration, +propagates cleanup failures, prints no IDs, and reports only this run's samples. +No product runtime configuration behavior is changed. + +- PASS: 3 benchmark regressions cover a failing second create, a failing kill + with close still executed, and exactly three successful owned lifecycles. +- PASS: execute the actual benchmark with public a2: three creates, three + independent get_info_by_id typed NotFound results, no leaked resources. +- PASS: rerun the updated import-migration script from its documented path using + only ABX configuration, no E2B environment or source injection: files, shell, + persistent interpreter 41-to-42, owned kill and independent typed absence. +- PASS: full client suite 2264 passed / 27 skipped; lint, typecheck, format checks. +- PARTIAL: full local server suite 873 passed / 1 skipped / 2 raw-loopback + failures: missing-key WebSocket expected400/actual501 and chunked framing + expected400/actual502. The earlier original-tag official CI passed; this PR's + latest-head official matrix remains required, not inferred from that earlier run. +- PASS: repository health106 / warning1 / failure0, hygiene and diff checks. + +New receipts preserve the separate executed sources: +[benchmark](2026-10-25-public-sdk-documentation-benchmark.json), +[migration](2026-10-25-public-sdk-documentation-migration.json), +[official index](2026-10-25-public-sdk-documentation-index.json). +The broader old example results remain unchanged; the browser case in Issue111 +still has its own unresolved acceptance scope. Docker fixture repair/build +acceptance is tracked separately and is not claimed by this PR. diff --git a/.agents/notes/proposed/process/2026-10-25-public-sdk-documentation.md b/.agents/notes/proposed/process/2026-10-25-public-sdk-documentation.md new file mode 100644 index 00000000..558af43d --- /dev/null +++ b/.agents/notes/proposed/process/2026-10-25-public-sdk-documentation.md @@ -0,0 +1,62 @@ +# Decision: Use current public SDK contracts in maintained guides +Status: proposed + +## Problem + +Maintained guides still installed a retired Git archive or older alpha packages, +published decorator/MCP keyword names absent from current signatures, mixed MCP +credentials with the standard E2B entry, and described the removed local Python +gRPC engine. The Express quickstart bypassed the current template launcher. The maintained +creation benchmark silently ignored old configuration names and could skip +cleanup after a later failure. + +## Decision + +Use public paired 0.4.0a2 installations, canonical sandbox_* configuration and +explicit root ProviderSandbox imports for provider-extension examples. Preserve +valid native synchronous wrappers and genuine third-party provider options. +Use the official PyPI index explicitly for public installs. The maintained +benchmark uses the installed public ProviderSandbox API, exactly three samples +and explicit per-sandbox cleanup; it adds no product runtime or compatibility API. +Use the single template launcher for application startup, with application tokens +separate from platform credentials. Keep standard-client migration documentation +separate and preserve historical design/evidence files that are labeled retired. + +## API Design + +No new API, alias, compatibility path or version is introduced. Correct the +maintained guides to match the actual published decorator and MCP signatures. +The beginner tutorial uses base command/file operations; it does not claim an +unimplemented Express ProviderSandbox interpreter operation. + +## Alternatives considered + +Keeping old examples with fallback aliases conflicts with the requested cleanup. +Replacing every api_key or domain occurrence would corrupt valid external SDK and +provider-option contracts. Rewriting historical engineering receipts would destroy +the distinction between previously tested and current behavior. + +## Dependencies + +Official PyPI paired packages and the separately maintained CLI template launcher. + +## Test Strategy + +Execute complete English and Chinese beginner scripts extracted from the actual +pages using fresh public packages, assert command/file transfer behavior and +independently verify owned sandbox absence. Inspect actual public signatures and +run the documented MCP HTTP app health/auth locally. Run document, link, health +and hygiene checks. Record the broader public example rerun separately and honestly. + +## Acceptance criteria + +- Maintained installations and first-party examples use current public contracts. +- Both beginner scripts pass with real Express resources and no leaked sandboxes. +- MCP/decorator parameters match public a2; HTTP app health/auth work locally. +- The independent browser cold-install failure remains recorded, not hidden or + treated as a passing example; Issue 111 remains open until its full criteria pass. + +## Evidence + +- [Verification](../../../evidence/verify/2026-10-25-public-sdk-documentation.md) +- [Example cleanup Issue 111](https://github.com/Alibaba-Agent-Sandbox/python-sdk/issues/111) diff --git a/AGENTS.md b/AGENTS.md index 6cb163e1..187c0840 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -5,7 +5,7 @@ ## Project Overview -**Agent Sandbox** (distribution name `agent-sandbox-client`, import `agent_sandbox`) provides standard synchronous/asynchronous Express clients and the explicit asynchronous `ProviderSandbox` for provider/server extensions. Standard entries follow the pinned Alibaba-supported E2B contract; conditional capabilities still depend on the actual account/function. Templates are built and deployed with `abx template build|deploy`; read `docs/en/guide/migrate-from-e2b.md` before changing either surface. +**Agent Sandbox** (distribution name `agent-sandbox-client`, import `agent_sandbox`) provides standard synchronous/asynchronous Express clients and the explicit asynchronous `ProviderSandbox` for provider/server extensions. Standard entries follow the pinned Alibaba-supported E2B contract; conditional capabilities still depend on the actual account/function. Launch templates with `abx template launch `; advanced image preparation uses `abx template build|deploy`. Read `docs/en/guide/migrate-from-e2b.md` before changing either surface. This repository (`python-sdk`) holds the **Python SDK only**, split into two distributions that share the `agent_sandbox` namespace and are **versioned in lockstep** (same version number): diff --git a/CHANGELOG.md b/CHANGELOG.md index fe65919e..721c6aba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/). ### Fixed +- Use the installed public provider API in the creation benchmark, clean each owned sandbox before continuing, propagate cleanup failures, and remove unsupported performance targets. / 创建基准改用已安装公开 Provider API,逐轮清理自有沙箱,透传清理错误并删除无依据性能目标。 + +- Align maintained bilingual SDK guides with public 0.4.0a2, canonical decorator/MCP arguments, current ProviderSandbox imports and unified template launch. Remove stale source-install recipes and retired Python-engine instructions. / 将维护中的双语 SDK 指南统一为公开 0.4.0a2、规范装饰器/MCP 参数、ProviderSandbox 公开导入及统一模板启动;删除旧源码安装方案和已退役 Python 引擎说明。 - Bound public PyPI metadata and fresh-install propagation retries while keeping artifact digest mismatches and dependency/import failures fatal. / 为公开 PyPI 元数据及全新安装增加有限传播重试,保持产物哈希、依赖与导入检查失败即中止。 ### Fixed diff --git a/README.md b/README.md index 911b207d..4aadb892 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,8 @@ **Agent Sandbox** is a Python SDK for sandboxes. The default provider is Alibaba Cloud Express (`alicloud-express`, Function Compute). OpenSandbox, the container edition, CubeSandbox, and E2B are catalog `node` plugins in `awesome-providers` (`provider.mjs`). Install one with `abx provider install alibaba-agent-sandbox/awesome-providers// --allow-unpinned --yes` (or `python -m agent_sandbox.providers install registry: --yes`). After that, both `abx --provider ` and `ProviderSandbox.create(provider="")` use it. The Python SDK reaches a `node` provider through the local engine (`abx provider engine serve`; `abx` on `PATH` or `ABX_BIN`). The CLI loads Express plus installed `node`, `exec` and `rest` plugins. It is the standard sync/async runtime and Template client. Project provider/server template launches use -`abx template build|deploy` from the CLI. The SDK uses E2B-shaped method names so that E2B code +`abx template launch ` from the CLI; advanced image preparation uses +`abx template build|deploy`. The SDK uses E2B-shaped method names so that E2B code ports with few changes; the standard API follows Alibaba-supported E2B behavior (see [Migrate from E2B](docs/en/guide/migrate-from-e2b.md)). This repository (`python-sdk`) contains the **Python SDK**, packaged as two lock-step distributions. The `abx` command-line tool is a separate Node.js project that lives in the @@ -58,14 +59,14 @@ Provider management operations are available through `agent_sandbox.providers.co - **In-image HTTP service** — `commands.py` imports `agent_sandbox.server` and calls `start(9000)`. - **Registered commands** — `@command` functions become routes the Client SDK calls with `sandbox.run`. - **Agents API** — Codex and Qwen Code HTTP sessions inside the sandbox. Install a CLI when you call it. Guide: [Agents API](docs/en/guide/agents-api.md). -- **Templates** — the image and `template.yaml` are built and deployed with `abx template build|deploy`. +- **Templates** — start the complete template with `abx template launch `; use `template build` / `template deploy` for advanced image preparation. ## Installation Use Python 3.10 or newer in a virtual environment. The client installs its matching server dependency automatically. See the [installation guide](docs/en/guide/install-python.md) for a pinned version, optional extras and development setup. ```bash -python -m pip install --upgrade --pre agent-sandbox-client +python -m pip install --index-url https://pypi.org/simple --upgrade --pre agent-sandbox-client python -m pip check ``` diff --git a/README.zh-CN.md b/README.zh-CN.md index 637344b3..bc9c6d85 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -12,7 +12,7 @@ > 为 AI Agent 打造的云沙箱 —— 秒级创建、执行、管理隔离环境。 -**Agent Sandbox** 是沙箱的 Python SDK。默认提供方是阿里云极速版(`alicloud-express`,函数计算)。OpenSandbox、容器版、CubeSandbox 和 E2B 都是 `awesome-providers` 里的目录 `node` 插件(`provider.mjs`)。用 `abx provider install alibaba-agent-sandbox/awesome-providers// --allow-unpinned --yes`(或 `python -m agent_sandbox.providers install registry: --yes`)安装。装好之后,`abx --provider ` 和 `ProviderSandbox.create(provider="")` 都能用。Python SDK 通过本机引擎(`abx provider engine serve`;`abx` 在 `PATH` 里或由 `ABX_BIN` 指定)使用 `node` 提供方。CLI 加载极速版,以及已安装的 `node`、`exec` 和 `rest` 插件。标准接口包含同步/异步运行时和 Template 客户端;项目 Provider/Server 模板流程通过 CLI 的 `abx template build|deploy` 完成。SDK 的方法名参考了 E2B, +**Agent Sandbox** 是沙箱的 Python SDK。默认提供方是阿里云极速版(`alicloud-express`,函数计算)。OpenSandbox、容器版、CubeSandbox 和 E2B 都是 `awesome-providers` 里的目录 `node` 插件(`provider.mjs`)。用 `abx provider install alibaba-agent-sandbox/awesome-providers// --allow-unpinned --yes`(或 `python -m agent_sandbox.providers install registry: --yes`)安装。装好之后,`abx --provider ` 和 `ProviderSandbox.create(provider="")` 都能用。Python SDK 通过本机引擎(`abx provider engine serve`;`abx` 在 `PATH` 里或由 `ABX_BIN` 指定)使用 `node` 提供方。CLI 加载极速版,以及已安装的 `node`、`exec` 和 `rest` 插件。标准接口包含同步/异步运行时和 Template 客户端;项目 Provider/Server 模板通过 CLI 的 `abx template launch ` 统一启动,高级镜像准备使用 `abx template build|deploy`。SDK 的方法名参考了 E2B, 方便 E2B 代码迁移,标准接口遵循阿里云支持版本的行为契约(见[从 E2B 迁移](docs/zh/guide/migrate-from-e2b.md))。 本仓库(`python-sdk`)包含 **Python SDK**,以两个版本同步的分发包提供。命令行工具 `abx` 是独立的 @@ -56,14 +56,14 @@ Node.js 项目,位于 [`agent-sandbox`](https://github.com/alibaba-agent-sandb - **镜像内 HTTP 服务** —— `commands.py` 导入 `agent_sandbox.server` 并调用 `start(9000)`。 - **注册命令** —— `@command` 函数变成路由,Client SDK 用 `sandbox.run` 调用。 - **Agents API** —— 沙箱里的 Codex 与 Qwen Code HTTP 会话。CLI 按需安装。说明见 [Agents API](docs/zh/guide/agents-api.md)。 -- **模板** —— 镜像和 `template.yaml` 用 `abx template build|deploy` 构建和部署。 +- **模板** —— 使用 `abx template launch ` 启动完整模板;高级镜像准备使用 `template build` / `template deploy`。 ## 安装 使用 Python 3.10 或更高版本及虚拟环境。客户端会自动安装同版本的服务端依赖。固定版本、可选依赖及开发安装见[安装指南](docs/zh/guide/install-python.md)。 ```bash -python -m pip install --upgrade --pre agent-sandbox-client +python -m pip install --index-url https://pypi.org/simple --upgrade --pre agent-sandbox-client python -m pip check ``` diff --git a/agent-sandbox-provider/SKILL.md b/agent-sandbox-provider/SKILL.md index da0f9879..2c509eb4 100644 --- a/agent-sandbox-provider/SKILL.md +++ b/agent-sandbox-provider/SKILL.md @@ -5,20 +5,20 @@ description: Write an Agent Sandbox provider plugin so ProviderSandbox.create(pr # Write an Agent Sandbox provider -Specification 5 and 0.4.0a1 are release candidates until publication; use the matching checkout for validation. +Specification 5 is implemented in the published 0.4.0a2 client/server alpha pair. This file is instructions for a coding agent. It is not executed by the SDK. Calling `Sandbox.create` against a backend that already exists is `agent-sandbox-sdk`. This skill only covers the provider you add. The client distribution is `agent-sandbox-client` (import `agent_sandbox`). -For the specification 5 candidate, install the matching alpha pair after publication; the client installs its matching server dependency: +Install the published alpha client; it installs its matching server dependency: ```bash -python -m pip install 'agent-sandbox-client==0.4.0a1' +python -m pip install --index-url https://pypi.org/simple 'agent-sandbox-client==0.4.0a2' python -m pip check ``` -The image needs only `agent-sandbox-server==0.4.0a1`. Installing that package on the host does not update an existing image. Development source installations must use a matching client/server revision. +The image needs only `agent-sandbox-server==0.4.0a2`. Installing that package on the host does not update an existing image. Development source installations must use a matching client/server revision. Do not install `agent-sandbox`; that PyPI project is unrelated. Only `alicloud-express` is built in. Do not reinstall it and do not reuse @@ -60,7 +60,7 @@ CLI if it reports that initialization cannot be verified. Doctor never creates a and a successful initialization does not prove cloud credentials or backend availability. The Node.js SDK currently provides the in-sandbox HTTP `ServerClient`, not provider lifecycle. -Do not start from the Express engine. Do not copy the Express `ABX_SANDBOX_API_KEY` or its standard-entry `E2B_API_KEY` setting into the new provider. Credentials belong to their selected backend. +Do not start from the Express engine. Do not copy the Express `ABX_SANDBOX_API_KEY` into the new provider. Credentials belong to their selected backend. ## Credentials diff --git a/agent-sandbox-sdk/SKILL.md b/agent-sandbox-sdk/SKILL.md index 9aaa1425..5e6a9b14 100644 --- a/agent-sandbox-sdk/SKILL.md +++ b/agent-sandbox-sdk/SKILL.md @@ -5,7 +5,7 @@ description: Write a Python client or a sandbox template for Agent Sandbox. Use # Write an Agent Sandbox client or template -Specification 5 and 0.4.0a1 are release candidates until publication; use the matching checkout for validation. +Specification 5 is implemented in the published 0.4.0a2 client/server alpha pair. This file is instructions for a coding agent. It is not executed by the SDK. Operating a sandbox with `abx` or MCP is the `agent-sandbox` skill. This skill @@ -18,19 +18,19 @@ Two packages share one version: | `agent-sandbox-client` | `agent_sandbox` | The caller's machine | | `agent-sandbox-server` | `agent_sandbox.server` | Inside the image, port 9000 | -For the specification 5 candidate, install the matching alpha pair after publication; the client installs its matching server dependency: +Install the published alpha client; it installs its matching server dependency: ```bash -python -m pip install 'agent-sandbox-client==0.4.0a1' +python -m pip install --index-url https://pypi.org/simple 'agent-sandbox-client==0.4.0a2' python -m pip check ``` -The image needs only `agent-sandbox-server==0.4.0a1`. Installing that package on the host does not update an existing image. Development source installations must use a matching client/server revision. +The image needs only `agent-sandbox-server==0.4.0a2`. Installing that package on the host does not update an existing image. Development source installations must use a matching client/server revision. Do not run `pip install agent-sandbox`. That PyPI name is an unrelated project. ## Credentials -ProviderSandbox reads `ABX_SANDBOX_API_KEY`, `ABX_SANDBOX_BASE_URL` and `ABX_SANDBOX_DOMAIN`. Standard clients also map the E2B environment names according to the [migration contract](https://github.com/Alibaba-Agent-Sandbox/python-sdk/blob/main/docs/en/guide/migrate-from-e2b.md). Preserve the selected entry's configuration; never forward a control-plane key as an application token. +Use `ABX_SANDBOX_API_KEY`, `ABX_SANDBOX_BASE_URL` and `ABX_SANDBOX_DOMAIN` for project configuration. Standard Sandbox / AsyncSandbox, code_interpreter and ProviderSandbox all support these settings. Public parameters retain each entry's [documented contract](https://github.com/Alibaba-Agent-Sandbox/python-sdk/blob/main/docs/en/guide/migrate-from-e2b.md); never forward a control-plane key as an application token. AK/SK, when a call needs them, are `ALICLOUD_ACCESS_KEY_ID` and `ALICLOUD_ACCESS_KEY_SECRET`. Never print a key, never commit one, and never @@ -195,7 +195,7 @@ Do not listen on 49983, 5000, or 49999. `` defaults to `cn-hangzhou`. ```dockerfile FROM fc-e2b-registry..cr.aliyuncs.com/runtime/base: -RUN pip install --no-cache-dir 'agent-sandbox-server==0.4.0a1' +RUN pip install --index-url https://pypi.org/simple --no-cache-dir 'agent-sandbox-server==0.4.0a2' WORKDIR /home/user/app COPY commands.py /home/user/app/commands.py EXPOSE 9000 @@ -207,7 +207,7 @@ The CLI can prepare the supported official native base recipe for both Express a ```dockerfile FROM python:3.12-slim -RUN pip install --no-cache-dir 'agent-sandbox-server==0.4.0a1' +RUN pip install --index-url https://pypi.org/simple --no-cache-dir 'agent-sandbox-server==0.4.0a2' WORKDIR /home/user/app COPY commands.py /home/user/app/commands.py EXPOSE 9000 diff --git a/client-sdk/README.md b/client-sdk/README.md index 62773a06..6fc5e89d 100644 --- a/client-sdk/README.md +++ b/client-sdk/README.md @@ -19,9 +19,9 @@ The command-line tool (`abx`) is a separate Node.js project that lives in the [` ## Install ```bash -python -m pip install --upgrade --pre agent-sandbox-client +python -m pip install --index-url https://pypi.org/simple --upgrade --pre agent-sandbox-client # Optional extras: -python -m pip install --upgrade --pre 'agent-sandbox-client[all]' +python -m pip install --index-url https://pypi.org/simple --upgrade --pre 'agent-sandbox-client[all]' python -m pip check ``` diff --git a/client-sdk/benchmarks/bench_create.py b/client-sdk/benchmarks/bench_create.py index ea7f57e3..37c6f7d3 100644 --- a/client-sdk/benchmarks/bench_create.py +++ b/client-sdk/benchmarks/bench_create.py @@ -1,62 +1,44 @@ -"""沙箱创建性能基准。目标:P95 < 3s""" +"""Measure three sandbox creation samples using an installed SDK.""" import asyncio -import contextlib import os import sys import time -from pathlib import Path -CLIENT_ROOT = Path(__file__).resolve().parent.parent -sys.path.insert(0, str(CLIENT_ROOT.parent / "server-sdk" / "src")) -sys.path.insert(0, str(CLIENT_ROOT / "src")) - -async def bench_create(): - """测试沙箱创建时间。""" - from agent_sandbox.models.sandbox import SandboxConfig - from agent_sandbox.providers.shared.e2b.sandbox import SandboxProtocol - from agent_sandbox.providers.alicloud_express.auth import ApiKeyAuth - from agent_sandbox.transport.config import TransportConfig - from agent_sandbox.transport.http import HttpClient +async def bench_create() -> None: + """Report this run's samples; delete each owned sandbox before the next one.""" + from agent_sandbox import ProviderSandbox api_key = os.environ.get("ABX_SANDBOX_API_KEY", "") if not api_key: print("ERROR: ABX_SANDBOX_API_KEY environment variable is required.") - print(" export ABX_SANDBOX_API_KEY=your_api_key_here") sys.exit(1) api_url = os.environ.get("ABX_SANDBOX_BASE_URL", "https://api.cn-hangzhou.e2b.fc.aliyuncs.com") domain = os.environ.get("ABX_SANDBOX_DOMAIN", "cn-hangzhou.e2b.fc.aliyuncs.com") - - config = TransportConfig(api_key=api_key, api_url=api_url, domain=domain) - auth = ApiKeyAuth(api_key=api_key) - http = HttpClient(config=config, auth=auth) - proto = SandboxProtocol(http_client=http) - - sandbox_config = SandboxConfig(template="base", timeout=60, env_vars={}, metadata={}) - times = [] - sandbox_ids = [] for i in range(3): start = time.perf_counter() - result = await proto.create(config=sandbox_config) - elapsed = time.perf_counter() - start - times.append(elapsed) - sid = result.sandbox_id - sandbox_ids.append(sid) - print(f" Create #{i + 1}: {elapsed:.3f}s (id={sid[:20]}...)") - - # Cleanup - for sid in sandbox_ids: - with contextlib.suppress(Exception): - await proto.kill(sid) - - await http.close() - - avg = sum(times) / len(times) - p95 = sorted(times)[int(len(times) * 0.95)] - print(f"\nCreate sandbox: avg={avg:.3f}s, p95={p95:.3f}s (target: <3.0s)") + sandbox = await ProviderSandbox.create( + template="base", + provider="alicloud-express", + timeout=60, + sandbox_api_key=api_key, + sandbox_base_url=api_url, + sandbox_domain=domain, + ) + try: + elapsed = time.perf_counter() - start + times.append(elapsed) + print(f" Create #{i + 1}: {elapsed:.3f}s") + finally: + try: + await sandbox.kill() + finally: + await sandbox.close() + + print(f"\nCreate sandbox: sample mean={sum(times) / len(times):.3f}s (3 samples)") if __name__ == "__main__": diff --git a/client-sdk/tests/test_benchmark_create.py b/client-sdk/tests/test_benchmark_create.py new file mode 100644 index 00000000..56aaaa5b --- /dev/null +++ b/client-sdk/tests/test_benchmark_create.py @@ -0,0 +1,67 @@ +"""The creation benchmark uses installed public APIs and closes owned resources.""" + +import importlib.util +from pathlib import Path + +import pytest + +from agent_sandbox import ProviderSandbox + +spec = importlib.util.spec_from_file_location( + "bench_create", Path(__file__).resolve().parents[1] / "benchmarks/bench_create.py" +) +assert spec and spec.loader +benchmark = importlib.util.module_from_spec(spec) +spec.loader.exec_module(benchmark) + + +@pytest.mark.parametrize("failure", [None, "second-create", "kill"]) +async def test_benchmark_has_bounded_public_calls_and_preserves_cleanup_errors( + monkeypatch, capsys, failure +): + events = [] + count = 0 + monkeypatch.setenv("ABX_SANDBOX_API_KEY", "placeholder") + monkeypatch.setenv("ABX_SANDBOX_BASE_URL", "https://example.invalid") + monkeypatch.setenv("ABX_SANDBOX_DOMAIN", "example.invalid") + + class OwnedSandbox: + async def kill(self): + events.append("kill") + if failure == "kill": + raise RuntimeError("owned cleanup failed") + + async def close(self): + events.append("close") + + async def create(**kwargs): + nonlocal count + count += 1 + events.append("create") + assert kwargs == { + "template": "base", + "provider": "alicloud-express", + "timeout": 60, + "sandbox_api_key": "placeholder", + "sandbox_base_url": "https://example.invalid", + "sandbox_domain": "example.invalid", + } + if failure == "second-create" and count == 2: + raise RuntimeError("creation failed") + return OwnedSandbox() + + monkeypatch.setattr(ProviderSandbox, "create", create) + if failure: + with pytest.raises(RuntimeError, match="creation failed|owned cleanup failed"): + await benchmark.bench_create() + else: + await benchmark.bench_create() + expected = { + None: ["create", "kill", "close"] * 3, + "second-create": ["create", "kill", "close", "create"], + "kill": ["create", "kill", "close"], + } + assert events == expected[failure] + output = capsys.readouterr().out + assert "id=" not in output + assert "p95" not in output.lower() diff --git a/docs/en/DESIGN.md b/docs/en/DESIGN.md index 886fc024..4c89d970 100644 --- a/docs/en/DESIGN.md +++ b/docs/en/DESIGN.md @@ -21,7 +21,7 @@ This repository holds the Python SDK as two lock-step PyPI distributions — `ag ### Quick Start ```bash -pip install agent-sandbox-client +python -m pip install --index-url https://pypi.org/simple agent-sandbox-client==0.4.0a2 export ABX_SANDBOX_API_KEY=your-api-key ``` @@ -29,8 +29,8 @@ export ABX_SANDBOX_API_KEY=your-api-key from agent_sandbox import ProviderSandbox as Sandbox async with await Sandbox.create(template="base") as sb: - result = await sb.run_code("print('Hello, Agent Sandbox!')") - print(result.text) + result = await sb.commands.run("printf 'Hello, Agent Sandbox!'") + print(result.stdout) ``` --- diff --git a/docs/en/design/agents-api.md b/docs/en/design/agents-api.md index 56cc4b62..33f744b1 100644 --- a/docs/en/design/agents-api.md +++ b/docs/en/design/agents-api.md @@ -617,7 +617,7 @@ Already have a URL? `AgentHost.connect(url, token=…)` skips the bootstrap ### Bootstrap (`AgentHost` via `sandbox.agents.host(agent)`) 1. `commands.run("python3 -c 'import agent_sandbox.server'")`; if missing and - `install=True` (default) → `pip install agent-sandbox-server==` + `install=True` (default) → `pip install --index-url https://pypi.org/simple agent-sandbox-server==` (lockstep releases; configurable `server_package=`/`index_url`). 2. Ensure the runtime CLI: `GET /agents/runtimes` after the server is up; if not installed and `install=True` → `POST …/install`. diff --git a/docs/en/design/mcp-server.md b/docs/en/design/mcp-server.md index 6184c78c..27eb699c 100644 --- a/docs/en/design/mcp-server.md +++ b/docs/en/design/mcp-server.md @@ -292,7 +292,7 @@ graph LR - **Sessions**: in-process `SessionStore`; idle TTL 3600 s (default), max 100 concurrent sessions (default); capacity exhaustion returns 503 with JSON-RPC error `-32000` - **Version negotiation**: `initialize` echoes the client-requested `protocolVersion` when supported; this transport supports `2025-06-18` only, matching `GET /health`. Missing or unsupported requested versions negotiate to `2025-06-18` — per the MCP spec the server responds with a version it supports, and clients that cannot accept it may disconnect. The STDIO transport independently keeps `2024-11-05` - **Use case**: remote service, team sharing, multiple clients; deploy to Alibaba Cloud FC via the artifact generated by the CLI's `abx mcp deploy`, or run locally with uvicorn -- **Optional dependency**: Starlette + uvicorn (`pip install 'agent-sandbox-client[mcp]'`) +- **Optional dependency**: Starlette + uvicorn (`pip install --index-url https://pypi.org/simple 'agent-sandbox-client[mcp]==0.4.0a2'`) ### Authentication diff --git a/docs/en/design/provider-e2b.md b/docs/en/design/provider-e2b.md index 2e27e6e6..da234884 100644 --- a/docs/en/design/provider-e2b.md +++ b/docs/en/design/provider-e2b.md @@ -18,9 +18,9 @@ Chinese page: [provider-e2b.md](../../zh/design/provider-e2b.md). | `domain` | string | `ABX_E2B_DOMAIN` | `e2b.app` | | `api_key` | secret | `ABX_E2B_API_KEY` | unset | -Pass the same three names in `provider_options`. `Sandbox.create(api_url=...)` does not select this origin. The resolver reads `provider_options["base_url"]`. +Pass the same three names in `provider_options`. Select the origin with `provider_options["base_url"]`, not a top-level API URL override. -When the key is set, the client sends header `X-API-Key`. A missing `ABX_E2B_API_KEY` raises `InvalidAPIKeyError` and the message names `ABX_E2B_API_KEY`. This provider does not read `ABX_SANDBOX_API_KEY` (the Alibaba Cloud Express key) or retired `ABX_SANDBOX_API_KEY`. +When the key is set, the client sends header `X-API-Key`. A missing `ABX_E2B_API_KEY` raises `InvalidAPIKeyError` and the message names `ABX_E2B_API_KEY`. This provider does not read `ABX_SANDBOX_API_KEY` (the Alibaba Cloud Express key). `domain` is the suffix in `https://{port}-{sandboxID}.{domain}`. The envd port is 49983. A create response that omits `region` stays unknown (empty), not `cn-hangzhou`. diff --git a/docs/en/design/repository-layout.md b/docs/en/design/repository-layout.md index 1db25139..8d1c6777 100644 --- a/docs/en/design/repository-layout.md +++ b/docs/en/design/repository-layout.md @@ -154,7 +154,7 @@ links with an absolute URL; byte-identical copies are forbidden (checked by the | Page (en + zh) | Owner | Other repo | |----------------|-------|------------| | `reference/template-yaml-spec`, `reference/error-codes` (E1xxx-E6xxx taxonomy), `reference/server-http-api`, `design/server-api`, `design/template-system` (schema half) | **python-sdk** | CLI links (CLI keeps only CLI-specific codes such as `E2007` and the exit-code map) | -| `guide/getting-started`, `guide/authentication`, `guide/environment-variables`, `guide/troubleshooting`, `reference/configuration`, `guide/mcp-integration` | **each repo owns its own, trimmed version** (SDK: Python API, `api_key=`, `Sandbox`; CLI: `abx config`, flags, exit codes). The shared credential precedence table is authored once in python-sdk `reference/configuration` and linked from the CLI page | no duplicated sections | +| `guide/getting-started`, `guide/authentication`, `guide/environment-variables`, `guide/troubleshooting`, `reference/configuration`, `guide/mcp-integration` | **each repo owns its own, trimmed version** (SDK: Python API, `sandbox_api_key=`, `ProviderSandbox`; CLI: `abx config`, flags, exit codes). The shared credential precedence table is authored once in python-sdk `reference/configuration` and linked from the CLI page | no duplicated sections | | `guide/authoring-templates` | **cli** (workflow: `abx template scaffold/deploy`) with a link to python-sdk `guide/server-sdk` for the `commands.py` API | link | | `design/mcp-server` | **python-sdk** (`agent_sandbox.agent.mcp`) | CLI documents `abx mcp install` and links | | `DESIGN.md`, `README.md` indexes | each repo, listing only its own pages plus a "Related documentation" section | link | diff --git a/docs/en/guide/authentication.md b/docs/en/guide/authentication.md index 77916721..91c2b5b6 100644 --- a/docs/en/guide/authentication.md +++ b/docs/en/guide/authentication.md @@ -2,7 +2,7 @@ This guide describes asynchronous `ProviderSandbox` provider extensions. Root `Sandbox` and `AsyncSandbox` follow the pinned standard migration contract; see [Migrate from E2B](migrate-from-e2b.md). -For current SDK installation, use the [paired source installation guide](install-python.md). +For current SDK installation, use the [installation guide](install-python.md). > **Note:** The `abx` commands shown on this page are provided by the Node.js CLI in the `cli` repository ([CLI binary installation](https://github.com/Alibaba-Agent-Sandbox/agent-sandbox/blob/main/docs/en/guide/binary-installation.md)). CLI-specific documentation (CLI design, tutorial, reference) lives there too; this repository documents the Python SDK (`agent-sandbox-client`) and the container-side runtime (`agent-sandbox-server`). @@ -68,7 +68,7 @@ sandbox_domain = "cn-hangzhou.e2b.fc.aliyuncs.com" #### 5. Code parameter (wins over the environment and over `~/.abx`) ```python -from agent_sandbox.api.sandbox import Sandbox +from agent_sandbox import ProviderSandbox as Sandbox # Pass directly when creating sandbox = await Sandbox.create(sandbox_api_key="your-api-key") @@ -85,7 +85,7 @@ sandbox = await Sandbox.connect("sbx-xxxx", sandbox_api_key="your-api-key") The previous automatic AK/SK-to-sandbox-key exchange has been removed. With only AccessKey credentials, sandbox authentication now raises `InvalidAPIKeyError` (E1001) locally, before any exchange/network request. Configure -`ABX_SANDBOX_API_KEY` or pass `sandbox_api_key=` / `api_key=` explicitly for +`ABX_SANDBOX_API_KEY` or pass `sandbox_api_key=` explicitly for sandbox create/connect/list and data-plane requests. Keep `ALICLOUD_ACCESS_KEY_ID`, `ALICLOUD_ACCESS_KEY_SECRET` and the configured diff --git a/docs/en/guide/authoring-templates.md b/docs/en/guide/authoring-templates.md index 1f02d471..f4b81e21 100644 --- a/docs/en/guide/authoring-templates.md +++ b/docs/en/guide/authoring-templates.md @@ -1,6 +1,6 @@ # Authoring Templates -For current SDK installation, use the [paired source installation guide](install-python.md). +For current SDK installation, use the [installation guide](install-python.md). > **Note:** The `abx` commands shown on this page are provided by the Node.js CLI in the `cli` repository ([CLI binary installation](https://github.com/Alibaba-Agent-Sandbox/agent-sandbox/blob/main/docs/en/guide/binary-installation.md)). CLI-specific documentation (CLI design, tutorial, reference) lives there too; this repository documents the Python SDK (`agent-sandbox-client`) and the container-side runtime (`agent-sandbox-server`). @@ -136,7 +136,7 @@ The server does not select a provider. Port 9000 is the application HTTP listen `commands.py` imports only `agent_sandbox.server` and calls `start(port)` from its main entry; the image explicitly installs the server SDK. For the provider-native -application API in the published 0.3.1a1 alpha, import `ProviderSandbox` from +application API in the published 0.4.0a2 alpha, import `ProviderSandbox` from `agent_sandbox` and connect with `await ProviderSandbox.connect(ID)`. This instance supports `async with await sandbox.application_client(9000, token=application_token)`; the standard `Sandbox`/`AsyncSandbox` classes have a different interface. diff --git a/docs/en/guide/client-sdk.md b/docs/en/guide/client-sdk.md index b004bcba..1422612d 100644 --- a/docs/en/guide/client-sdk.md +++ b/docs/en/guide/client-sdk.md @@ -5,7 +5,7 @@ For current SDK installation, use the [installation guide](install-python.md). The Client SDK runs on **your machine**. It creates a sandbox, connects to one that already exists, and then runs commands, reads and writes files, and calls the code interpreter. The package is `agent-sandbox-client`. Import `agent_sandbox`. ```bash -python -m pip install 'agent-sandbox-client==0.4.0a1' +python -m pip install --index-url https://pypi.org/simple 'agent-sandbox-client==0.4.0a2' python -m pip check ``` diff --git a/docs/en/guide/cloud-examples.md b/docs/en/guide/cloud-examples.md index 09a91291..83d8bc98 100644 --- a/docs/en/guide/cloud-examples.md +++ b/docs/en/guide/cloud-examples.md @@ -3,7 +3,7 @@ Install the public Python pair through the client dependency: ```bash -python -m pip install "agent-sandbox-client[all]==0.4.0a2" +python -m pip install --index-url https://pypi.org/simple "agent-sandbox-client[all]==0.4.0a2" export ABX_SANDBOX_API_KEY="your-express-sandbox-api-key" # Configure ABX_SANDBOX_BASE_URL and ABX_SANDBOX_DOMAIN for your region if needed. ``` @@ -33,7 +33,7 @@ For `codex_agent.py`, set `OPENAI_API_KEY`; optionally set `OPENAI_BASE_URL` and The browser example installs Playwright and real headless Chromium. Its default HTTP page runs inside the owned sandbox, providing deterministic title/link/screenshot checks. Set `BROWSER_URL` for an external site; non-success HTTP responses and absent expected content fail visibly. Installation still needs outbound access to package/browser repositories. -The standard-client import migration example uses `E2B_API_KEY`, `E2B_API_URL`, and `E2B_DOMAIN` configured for your Express account, then runs `python examples/compat-demos/e2b_import_migration.py`. These names belong to the standard E2B-compatible client. Do not reuse credentials from a different provider account. `ProviderSandbox` and decorator examples above use `ABX_SANDBOX_API_KEY`. +The standard-client import migration example uses the same project `ABX_SANDBOX_API_KEY`, `ABX_SANDBOX_BASE_URL` and `ABX_SANDBOX_DOMAIN` configuration as the other examples. Run `python examples/compat-demos/e2b_import_migration.py`. These values must belong to the Express account; do not reuse credentials from a different provider. For local HTTP/session examples run `python examples/run_examples_e2e.py`. That runner uses real local server processes and controlled Codex/Qwen protocol executables, not model calls. Cloud scripts are explicitly listed as `needs-provider` there. See the [example catalog](../../../examples/README.md) and [template HTTP API](template-server-api.md). diff --git a/docs/en/guide/command-map.md b/docs/en/guide/command-map.md index 51511df4..de766f40 100644 --- a/docs/en/guide/command-map.md +++ b/docs/en/guide/command-map.md @@ -10,7 +10,7 @@ Public surfaces used for this map: | Product | CLI | SDK | |---|---|---| -| Agent Sandbox | `abx` (`@agent-sandbox/cli`) | `agent-sandbox-client`, `from agent_sandbox.api.sandbox import Sandbox` | +| Agent Sandbox | `abx` (`@agent-sandbox/cli`) | `agent-sandbox-client`, `from agent_sandbox import ProviderSandbox` | | E2B | `e2b` (`@e2b/cli`, docs for 2.16.1) | `e2b`, `from e2b import Sandbox` | | OpenSandbox | `osb` (`opensandbox-cli`, [CLI](https://open-sandbox.ai/cli/)) | `opensandbox`, `from opensandbox import Sandbox` ([Python SDK](https://open-sandbox.ai/sdks/python)) | @@ -23,7 +23,7 @@ A cell with "—" means that side has no matching public command or method. | Job | abx | Agent Sandbox SDK | e2b | E2B SDK | osb | OpenSandbox SDK | |---|---|---|---|---|---|---| | Install | [CLI binary installation](https://github.com/Alibaba-Agent-Sandbox/agent-sandbox/blob/main/docs/en/guide/binary-installation.md) | [Paired source install](install-python.md) | `npm install -g @e2b/cli` | `pip install e2b` | `pip install opensandbox-cli` | `pip install opensandbox` | -| Store a credential | `abx config set sandbox_api_key` | environment variable `E2B_API_KEY` | `e2b auth login` | environment variable `E2B_API_KEY` | `osb config set connection.api_key` | `ConnectionConfig(api_key=…)` or `OPEN_SANDBOX_API_KEY` | +| Store a credential | `abx config set sandbox_api_key` | environment variable `ABX_SANDBOX_API_KEY` | `e2b auth login` | environment variable `E2B_API_KEY` | `osb config set connection.api_key` | `ConnectionConfig(api_key=…)` or `OPEN_SANDBOX_API_KEY` | | Show the effective config | `abx config list` | — | `e2b auth info` | — | `osb config show` | — | Alibaba Cloud access keys keep the official names `ALICLOUD_ACCESS_KEY_ID` and `ALICLOUD_ACCESS_KEY_SECRET`. The OpenSandbox address is `osb config set connection.domain`, and the environment variable is `OPEN_SANDBOX_DOMAIN`. diff --git a/docs/en/guide/comparison.md b/docs/en/guide/comparison.md index a1cf3386..36892f94 100644 --- a/docs/en/guide/comparison.md +++ b/docs/en/guide/comparison.md @@ -1,234 +1,74 @@ -# Comparison with Other Sandbox Tools +# SDK entry comparison -For current SDK installation, use the [paired source installation guide](install-python.md). +Choose an entry by the API your code uses. The entries below share project +configuration (`ABX_SANDBOX_API_KEY`, `ABX_SANDBOX_BASE_URL`, `ABX_SANDBOX_DOMAIN`), +but retain their own method signatures and result models. -> **Note:** The `abx` commands shown on this page are provided by the Node.js CLI in the `cli` repository ([CLI binary installation](https://github.com/Alibaba-Agent-Sandbox/agent-sandbox/blob/main/docs/en/guide/binary-installation.md)). CLI-specific documentation (CLI design, tutorial, reference) lives there too; this repository documents the Python SDK (`agent-sandbox-client`) and the container-side runtime (`agent-sandbox-server`). +| Entry | Use | Requirements | +|---|---|---| +| `from agent_sandbox import Sandbox` | Standard synchronous lifecycle, command and file APIs | Alibaba-supported pinned standard contract; Express account | +| `from agent_sandbox import AsyncSandbox` | The same standard operations from async code | Await asynchronous methods | +| `from agent_sandbox.code_interpreter import Sandbox, AsyncSandbox` | Standard interpreter results and contexts | An interpreter-enabled template such as `code-interpreter-v1` | +| `from agent_sandbox import ProviderSandbox` | Explicit provider extensions, sessions and application clients | The selected provider must implement the requested operation | +| `from agent_sandbox.declarative import sandbox` | Execute a Python function remotely | A template with the required Python environment and dependencies | +| `from agent_sandbox.server import command, start` | Register and serve application commands inside an image | Install the same-version server runtime inside that image | -This document provides an objective comparison of Agent Sandbox (abx) with other popular sandbox and remote execution platforms: E2B, Modal, and Docker Sandbox. +Install the [published Python packages](install-python.md). The Python packages +do not install the separate [abx CLI](https://github.com/Alibaba-Agent-Sandbox/agent-sandbox). ---- - -## Positioning and Use Cases - -| Platform | Core Positioning | Primary Use Cases | -|----------|-----------------|-------------------| -| **Agent Sandbox (abx)** | Sandbox SDK with pluggable providers. The default provider is Alibaba Cloud Express (FC); others install as plugins | AI agent code execution, cloud or local dev environments, template-driven sandboxes | -| **E2B** | Cloud sandboxes built for AI apps | AI agent tool-use, code interpreters, data analysis in LLM workflows | -| **Modal** | Serverless compute for data/ML pipelines | GPU workloads, batch jobs, model inference, scheduled tasks | -| **Docker Sandbox** | Container-based local/remote isolation | Local development, CI/CD, reproducible environments | - ---- - -## SDK Comparison - -| Dimension | Agent Sandbox | E2B | Modal | -|-----------|-------------|-----|-------| -| **Language** | Python | Python, JS/TS, Kotlin, Go | Python | -| **Install** | [paired source installation guide](install-python.md) | `pip install e2b` | `pip install modal` | -| **Sandbox creation** | `await Sandbox.create()`, or the Modal-style `@sandbox` decorator | `await Sandbox.create()` | `@app.function()` decorator | -| **Sync support** | `Sandbox.create_sync()` | `Sandbox()` (sync class) | N/A (async-native) | -| **Command execution** | `sandbox.commands.run()` | `sandbox.commands.run()` | Remote function call | -| **File operations** | `sandbox.files.read/write/list` | `sandbox.files.read/write/list` | `modal.Volume` mount | -| **Code execution** | `sandbox.run_code()` | `sandbox.run_code()` | Remote function execution | -| **Registered commands** | `sandbox.run(name, **kwargs)` | N/A | N/A | -| **Network access** | `sandbox.network.get_host()` | `sandbox.get_host()` | Built-in URL routing | -| **Terminal (PTY)** | `sandbox.get_terminal()` | `sandbox.terminal.start()` | `modal shell` | -| **E2B migration helper** | `from agent_sandbox import Sandbox` (partial) | Native | N/A | -| **Auth methods** | Depends on the provider. The default uses `E2B_API_KEY`; Alibaba Cloud Express also uses the official AK/SK names | API Key | Token-based | - -### Code Examples - -**Agent Sandbox:** +## Standard interpreter ```python -from agent_sandbox.api.sandbox import Sandbox +from agent_sandbox.code_interpreter import Sandbox -async with await Sandbox.create(template="python-hello") as sb: - result = await sb.run_code("print('hello')") +with Sandbox.create(template="code-interpreter-v1") as sandbox: + result = sandbox.run_code("print(1 + 1)") + assert result.error is None print(result.text) ``` -**E2B:** - -```python -from e2b import Sandbox - -sandbox = Sandbox() -result = sandbox.run_code("print('hello')") -print(result.text) -sandbox.kill() -``` - -**Modal:** - -```python -import modal -app = modal.App("example") - -@app.function() -def hello(): - print("hello") -``` - -### Usage Style Comparison +For an existing E2B application, follow the [pinned migration contract](migrate-from-e2b.md). +Changing imports does not remove backend permissions, account restrictions or +runtime prerequisites. Third-party libraries keep their own native configuration. -Agent Sandbox supports both **imperative** (E2B style) and **declarative** (Modal style) programming paradigms: - -| Dimension | E2B Style (Imperative) | Modal Style (Declarative) | -|-----------|----------------------|-------------------------| -| **Creation** | Manual `Sandbox.create()` | Automatic (`@sandbox` decorator) | -| **Dependency install** | `sb.commands.run("pip install ...")` | Decorator argument `packages=[...]` | -| **Data transfer** | `files.write()` + `files.read()` | Function args and return values auto-serialized | -| **Execution** | `sb.commands.run()` / `sb.run_code()` | Call function directly | -| **Result retrieval** | Parse stdout / read files | Function return value | -| **Lifecycle** | Manual `kill()` or `async with` | Automatically managed | -| **Best for** | Fine-grained control, long-running interactions, multi-step workflows | Simple compute tasks, batch processing, function-as-a-service | - -**E2B Style (Imperative) — fine-grained control:** +## Provider command and file operations ```python -from agent_sandbox.api.sandbox import Sandbox +from agent_sandbox import ProviderSandbox -async with await Sandbox.create() as sb: - await sb.commands.run("pip install pandas") - await sb.files.write("/app/data.csv", csv_content) - result = await sb.commands.run("python3 /app/analyze.py") - report = await sb.files.read("/app/report.txt") +async with await ProviderSandbox.create(template="base") as sandbox: + result = await sandbox.commands.run("printf hello") + assert result.exit_code == 0 + await sandbox.files.write("/home/user/note.txt", result.stdout) + assert await sandbox.files.read("/home/user/note.txt") == "hello" ``` -**Modal Style (Declarative) — call like a local function:** - -```python -from agent_sandbox.declarative import sandbox - -@sandbox(packages=["pandas"]) -def analyze(data: list[dict]) -> dict: - import pandas as pd - df = pd.DataFrame(data) - return {"mean": df["value"].mean(), "count": len(df)} - -# Called just like a local function — automatically runs in a remote sandbox -result = analyze(my_data) -``` - -> See [`examples/compat-demos/comparison.py`](../../../examples/compat-demos/comparison.py) for a complete example. - ---- - -## CLI Comparison - -| Dimension | abx | e2b CLI | modal CLI | -|-----------|-----|---------|-----------| -| **Install** | [CLI binary installation](https://github.com/Alibaba-Agent-Sandbox/agent-sandbox/blob/main/docs/en/guide/binary-installation.md) | `npm i -g @e2b/cli` | `pip install modal` | -| **Runtime** | Node.js (TypeScript) | Node.js | Python (Typer) | -| **Create sandbox** | `abx create` | `e2b sandbox create` | N/A (code-driven) | -| **List sandboxes** | `abx sandbox list` | `e2b sandbox list` | `modal container list` | -| **Connect to sandbox** | `abx connect ` | `e2b sandbox connect` | `modal shell` | -| **Template build** | `abx template build` | `e2b template build` | N/A | -| **Template deploy** | `abx template deploy` | `e2b template build --push` | N/A | -| **Auth setup** | Via environment variables (`.env`) | `e2b auth login` | `modal token set` | -| **MCP integration** | `abx mcp install` | N/A | N/A | -| **Secret management** | Via environment variables (`.env`) | N/A | `modal secret create` | - ---- - -## Infrastructure - -| Dimension | Agent Sandbox | E2B | Modal | Docker Sandbox | -|-----------|-------------|-----|-------|----------------| -| **Isolation** | Depends on the provider. The default is an Alibaba Cloud FC container; `local-process` is not isolated | Firecracker MicroVM | Container (gVisor) | Container (runc/containerd) | -| **Startup time** | Seconds | ~150ms (MicroVM) | Seconds (cold) / ms (warm) | Seconds | -| **Regions** | Default provider: Alibaba Cloud regions (cn-hangzhou, etc.). Other providers choose their own | US, EU | US (aws-us-east-1, etc.) | Self-hosted | -| **Platform** | Default provider is managed Alibaba Cloud. Plugins can be local or another cloud | Managed (E2B Cloud) | Managed (Modal Cloud) | Self-hosted / Docker Desktop | -| **GPU support** | Via template config | N/A | Native (A10G, A100, H100) | Via NVIDIA Container Toolkit | -| **Max lifetime** | Configurable (up to 86400s) | Configurable | Per-invocation | Unlimited | -| **Pricing** | Alibaba Cloud FC billing | Per-sandbox-second | Per-second compute | Infrastructure cost | - ---- - -## Unique Capabilities of Agent Sandbox - -### E2B-shaped API - -Agent Sandbox uses E2B-style method names, so E2B code can often be ported with few edits. The standard API follows the pinned Alibaba-supported behavior contract; see the migration guide for backend limits and imports. - -```python -# Start of a migration: change the import, then follow the guide -from agent_sandbox import Sandbox -``` - -See [Migrating from E2B](migrate-from-e2b.md) for the full guide. - -### Alibaba Cloud Integration - -| Feature | Description | -|---------|-------------| -| **AK/SK Auth** | Native Alibaba Cloud AccessKey authentication | -| **Template build and deploy** | `abx template build` / `abx template deploy` push images to Alibaba Cloud Container Registry and register the template | - -VPC, OSS volumes and custom domains are platform settings (template runtime configuration and account-level resources). The Python SDK has no API for them. - -### Registered Commands - -Functions registered in the sandbox server (`@sandbox.register`, implemented by the Server SDK inside the container) are callable through one API: - -```python -result = await sandbox.run("analyze", data="input.csv") -``` - -This is not available in E2B or Modal. - -### MCP Server Integration - -Agent Sandbox includes a built-in MCP (Model Context Protocol) Server, enabling AI IDEs (Cursor, Claude Desktop, VS Code) to operate sandboxes directly: - -```bash -abx mcp install --target cursor -``` - -Provides 7 tools: `create_sandbox`, `run_code`, `run_command`, `read_file`, `write_file`, `list_files`, `kill_sandbox`. - -### Declarative Sandbox Decorator - -```python -from agent_sandbox import sandbox - -@sandbox(template="python-hello", timeout=60) -async def my_task(): - ... -``` - ---- - -## Other Platforms (Brief) - -| Platform | Notes | -|----------|-------| -| **Daytona** | Cloud development environment platform. Transitioned to closed-source in 2026. Previously offered an open-source self-hosted option. | -| **Google Gemini Sandbox** | Code execution sandbox within Google Cloud's Gemini Enterprise Agent Platform (formerly Vertex AI). Managed service, tightly coupled to Google Cloud ecosystem. | -| **Cloudflare Workers** | Uses V8 Isolates for process-level isolation with sub-millisecond cold starts. Focused on edge computing rather than general-purpose sandboxes. | -| **Fly.io Machines** | Firecracker-based ephemeral VMs. Good for running full Linux environments with fast boot times. API-driven, no sandbox-specific SDK. | - ---- - -## Summary - -| Consideration | Recommended Platform | -|--------------|---------------------| -| Migrating from E2B to Alibaba Cloud | **Agent Sandbox** — E2B-shaped method names, few code changes (not a drop-in) | -| AI agent with code execution needs | **Agent Sandbox** or **E2B** — purpose-built sandbox SDKs | -| GPU-heavy ML/inference workloads | **Modal** — native GPU support and serverless scaling | -| Local development isolation | **Docker** — industry-standard, self-hosted | -| Alibaba Cloud ecosystem integration | **Agent Sandbox** — AK/SK auth, template build and deploy to ACR | -| MCP-based AI IDE integration | **Agent Sandbox** — built-in MCP Server | - ---- - -## Further Reading - -- [Command and SDK map](command-map.md) -- [Migrating from E2B](migrate-from-e2b.md) -- [SDK Usage Guide](sdk-usage.md) -- [CLI Tutorial](https://github.com/alibaba-agent-sandbox/agent-sandbox/blob/main/docs/en/guide/cli-tutorial.md) -- [MCP Integration](mcp-integration.md) -- [Authentication](authentication.md) +This uses command and file operations on Express `base`. It does not exercise an +interpreter API or start an application server. The Express ProviderSandbox +adapter does not implement interpreter operations; use the standard interpreter +entry above for those calls. Other providers' operation declarations are separate +from account availability and live acceptance; see [providers](providers.md). + +## Template applications + +Use `abx template launch ` to prepare and start the complete template. +Advanced `template build` / `template deploy` handle image preparation separately. +After launch, bind an application client with +`await sandbox.application_client(9000, token=application_token)` and call +`client.commands.run("hello", name="Python")`. This requires a running template +that registers hello; plain `base` does not provide it. See +[Express quickstart](express-quickstart.md) and [template launch](template-workflows.md). + +Application tokens and platform credentials have separate audiences. The provider +owns gateway resolution and preserves the required headers and URL prefix. +Close borrowed client connections; delete only sandboxes and build resources +you own. + +## Verification scope + +A compatible signature or provider declaration is not a live-cloud result. +[Cloud examples](cloud-examples.md) describe reproducible scripts and their +prerequisites. Each recorded test covers its actual account, template, provider +and invocation path. This guide makes no cross-platform startup-time, GPU, +maximum-lifetime or pricing comparison; those depend on platform and account +conditions and are not established by an API comparison. diff --git a/docs/en/guide/declarative-usage.md b/docs/en/guide/declarative-usage.md index 16fb1419..537e1d7f 100644 --- a/docs/en/guide/declarative-usage.md +++ b/docs/en/guide/declarative-usage.md @@ -33,9 +33,9 @@ print(result) serializer="json", # Serialization method (default "json") sandbox_id=None, # Reuse an existing sandbox ID (skips creation when not None) keep_alive=False, # When True, the sandbox is not destroyed after execution - api_key=None, # API Key override - api_url=None, # Platform API URL override - domain=None, # Domain override + sandbox_api_key=None, # API Key override + sandbox_base_url=None, # Platform API URL override + sandbox_domain=None, # Domain override cpu=None, # CPU cores memory=None, # Memory in MB ) @@ -54,9 +54,9 @@ def my_func(): | `serializer` | `str` | `"json"` | Serialization mode (only `json` is supported) | | `sandbox_id` | `str` | `None` | Reuse an existing sandbox ID | | `keep_alive` | `bool` | `False` | Do not destroy the sandbox after execution | -| `api_key` | `str` | `None` | API Key override | -| `api_url` | `str` | `None` | Platform URL override | -| `domain` | `str` | `None` | Platform domain | +| `sandbox_api_key` | `str` | `None` | API Key override | +| `sandbox_base_url` | `str` | `None` | Platform URL override | +| `sandbox_domain` | `str` | `None` | Platform domain | | `cpu` | `int` | `None` | CPU cores | | `memory` | `int` | `None` | Memory in MB | diff --git a/docs/en/guide/environment-variables.md b/docs/en/guide/environment-variables.md index 8c77192b..2516a891 100644 --- a/docs/en/guide/environment-variables.md +++ b/docs/en/guide/environment-variables.md @@ -2,7 +2,7 @@ This guide describes asynchronous `ProviderSandbox` provider extensions. Root `Sandbox` and `AsyncSandbox` follow the pinned standard migration contract; see [Migrate from E2B](migrate-from-e2b.md). -For current SDK installation, use the [paired source installation guide](install-python.md). +For current SDK installation, use the [installation guide](install-python.md). > **Note:** The `abx` commands shown on this page are provided by the Node.js CLI in the `cli` repository ([CLI binary installation](https://github.com/Alibaba-Agent-Sandbox/agent-sandbox/blob/main/docs/en/guide/binary-installation.md)). CLI-specific documentation (CLI design, tutorial, reference) lives there too; this repository documents the Python SDK (`agent-sandbox-client`) and the container-side runtime (`agent-sandbox-server`). diff --git a/docs/en/guide/express-quickstart.md b/docs/en/guide/express-quickstart.md index b1cd8499..8f2d4e51 100644 --- a/docs/en/guide/express-quickstart.md +++ b/docs/en/guide/express-quickstart.md @@ -1,62 +1,52 @@ # Express quickstart -Verified 2026-10-15 on Alibaba Cloud Express (`alicloud-express`) with `agent-sandbox-client` 0.3.0. The template is generation 2. Its start command runs `agent-sandbox-server`. +Install the [current Python pair](install-python.md) and the separate +[abx CLI](https://github.com/Alibaba-Agent-Sandbox/agent-sandbox/blob/main/docs/en/guide/binary-installation.md). +Configure the Express provider using the CLI's +[template launch guide](https://github.com/Alibaba-Agent-Sandbox/agent-sandbox/blob/main/docs/en/guide/using-templates.md); +source builds require the documented Docker/registry prerequisites. -## Deploy +## Launch the application ```bash -abx template scaffold --template python --name hello-x -cd hello-x -abx template deploy . -y --generation 2 \ - --start-cmd 'agent-sandbox-server serve --port 9000 --commands /home/user/app/commands.py' \ - --ready-cmd 'agent-sandbox-server healthcheck --port 9000' +export ABX_SERVER_TOKEN='replace_me' +abx --provider alicloud-express template launch 'alibaba-agent-sandbox/awesome-templates//python-hello' ``` -The python scaffold registers `hello(name="World")`, which returns `Hello, {name}!`. Copy the template id from the deploy output. +The launcher prepares the provider reference, creates the sandbox, runs the +template's startup command and checks its declared services. No workflow selector +is needed. Keep the returned sandbox ID and cleanup instructions. -`--start-cmd` and `--ready-cmd` require `--generation 2`. If a generation-1 template already uses the name, delete it first (`abx template delete -y`). If deploy reports `base must be a mapping`, set `template.yaml` to: +## Call from Python -```yaml -base: - image: "fc-e2b-registry.cn-hangzhou.cr.aliyuncs.com/runtime/base:v0.0.49" -``` - -Use your region and the current runtime base tag in place of those two values. - -## Call it +Set `SANDBOX_ID` to the returned identifier; keep the same `ABX_SERVER_TOKEN`. +`ABX_SANDBOX_API_KEY` configures platform access and is separate from that token. ```python import asyncio +import os -from agent_sandbox import ProviderSandbox as Sandbox +from agent_sandbox import ProviderSandbox -TEMPLATE = "" - -async def main() -> None: - sb = await Sandbox.create(template=TEMPLATE, timeout=300) +async def main(): + sandbox = await ProviderSandbox.connect( + os.environ["SANDBOX_ID"], provider="alicloud-express" + ) try: - echoed = await sb.commands.run("echo hi") - assert echoed.stdout == "hi\n" and echoed.exit_code == 0 - assert await sb.run("hello", name="Bob") == "Hello, Bob!" - url = sb.network.get_url(9000) - headers = sb.network.get_access_headers() - # GET {url}/health with headers. /health answers 200. + async with await sandbox.application_client( + 9000, token=os.environ["ABX_SERVER_TOKEN"] + ) as client: + result = await client.commands.run("hello", name="Python") + print(result) finally: - await sb.kill() + await sandbox.close() asyncio.run(main()) ``` -`sandbox.run` does not send the sandbox access token. `get_access_headers()` is `X-Access-Token` for the platform gateway. - -Generation 1 still supports `commands.run` and `files` (verified the same day on the platform template `base`, envd 0.5.2). The image entrypoint is fixed, so a generation-1 template cannot start `agent-sandbox-server` itself. Named commands need the generation-2 start and ready commands above. - -## Clean up - -`sb.kill()` removes the sandbox. Delete the template when you are done: - -```bash -abx template delete -y -``` +This code borrows the CLI-created sandbox and closes its connection. When finished, +use the launch cleanup instructions to delete the sandbox and owned build resources. +See [template launch](template-workflows.md) for the equivalent prepared-reference +Python launcher and lifecycle ownership. diff --git a/docs/en/guide/getting-started.md b/docs/en/guide/getting-started.md index dd965ea6..f7341a6b 100644 --- a/docs/en/guide/getting-started.md +++ b/docs/en/guide/getting-started.md @@ -1,228 +1,104 @@ # Getting Started -For current SDK installation, use the [paired source installation guide](install-python.md). +Install the Client SDK on your machine to create and use sandboxes. The +[Server SDK](server-sdk.md) runs applications inside sandbox images. +This tutorial uses the provider extension `ProviderSandbox`. Standard synchronous +`Sandbox` and asynchronous `AsyncSandbox` entries are documented in +[Migrate from E2B](migrate-from-e2b.md). -This is the **Client SDK**: install it on your machine, create a sandbox, and use it. The service that starts inside the image is the [Server SDK](server-sdk.md). +## 1. Install and configure -This tutorial covers the lifecycle from install through teardown. - ---- - -## Prerequisites - -- Python 3.10 or later -- For the default provider (`alicloud-express`): an API key from the [Agent Sandbox product docs](https://help.aliyun.com/zh/functioncompute/product-overview-of-fc-agent-sandbox). The variable is `E2B_API_KEY`. The standard SDK reads `E2B_API_KEY`, `E2B_API_URL` and `E2B_DOMAIN`. -- Network access to the Alibaba Cloud Hangzhou region (default `cn-hangzhou`) - -## 1. Installation - -```bash -# Install the SDK -python -m pip install \ - "agent-sandbox-server @ https://github.com/Alibaba-Agent-Sandbox/python-sdk/archive/3aa5e5ae6bd9c843f62c6689e549437f460b382d.tar.gz#subdirectory=server-sdk" \ - "agent-sandbox-client @ https://github.com/Alibaba-Agent-Sandbox/python-sdk/archive/3aa5e5ae6bd9c843f62c6689e549437f460b382d.tar.gz#subdirectory=client-sdk" - -# Install with all extras (recommended) -python -m pip install \ - "agent-sandbox-server @ https://github.com/Alibaba-Agent-Sandbox/python-sdk/archive/3aa5e5ae6bd9c843f62c6689e549437f460b382d.tar.gz#subdirectory=server-sdk" \ - "agent-sandbox-client[all] @ https://github.com/Alibaba-Agent-Sandbox/python-sdk/archive/3aa5e5ae6bd9c843f62c6689e549437f460b382d.tar.gz#subdirectory=client-sdk" -``` - -Do not run `pip install agent-sandbox`. That name on PyPI is an unrelated project. - -The `abx` CLI is not part of the Python package (there is no `[cli]` extra); it is a separate Node.js project, see [Related: the abx CLI](#related-the-abx-cli). The container-side runtime -(`agent_sandbox.server`) is the separate `agent-sandbox-server` package ([paired source installation guide](install-python.md)); `agent-sandbox-client` -depends on it, so installing the client provides it too. - -### Working from a source checkout - -From the repository root, with a virtual environment activated, install both -local distributions and the development tools: +Use Python 3.10 or later. Create and activate a virtual environment following the +[installation guide](install-python.md), then install: ```bash -uv pip install -e ./server-sdk -e "./client-sdk[dev]" +python -m pip install --index-url https://pypi.org/simple 'agent-sandbox-client==0.4.0a2' +python -m pip check +export ABX_SANDBOX_API_KEY='your-api-key' ``` -The root uv workspace resolves the client's runtime dependency to `server-sdk/`. -No `--no-sources` workaround is needed. Regular `pip install` accepts the same -editable arguments; published packages retain the matching server version pin. +Obtain the Express sandbox API key using the +[Agent Sandbox product documentation](https://help.aliyun.com/zh/functioncompute/product-overview-of-fc-agent-sandbox). +The default provider is `alicloud-express`, region `cn-hangzhou`. All project entries, including standard `Sandbox` / `AsyncSandbox` and +`ProviderSandbox`, support `ABX_SANDBOX_API_KEY`, `ABX_SANDBOX_BASE_URL` and +`ABX_SANDBOX_DOMAIN`. Use these names for project configuration. See +[authentication](authentication.md) for provider-extension `sandbox_api_key=` overrides; +standard entries retain their documented public `api_key=` parameter. -## 2. Configure the API Key +Installing the client installs the matching server distribution. This does not +update a server already inside an existing image. The distribution named +`agent-sandbox` on PyPI is an unrelated project. Optional dependencies and source +development are covered in the [installation guide](install-python.md). -There are three ways to configure credentials. When a call actually needs the key, this is the order (highest first). The full table is in [Configuration — Credential resolution](../reference/configuration.md#credential-resolution). +## 2. Create, execute and transfer files -### Option 1: Code parameter (this call only) - -```python -from agent_sandbox.api.sandbox import Sandbox - -sandbox = await Sandbox.create(sandbox_api_key="your-api-key-here") -``` - -### Option 2: Environment variable (recommended for CI/CD) - -```bash -export E2B_API_KEY="your-api-key-here" -``` - -### Option 3: Persisted file (`~/.abx/.env`) - -Used when neither the environment nor the project `.env` sets the key. The file is written by the `abx` CLI (`abx config set sandbox_api_key your-api-key`, permissions 600; see [Related: the abx CLI](#related-the-abx-cli)) or edited by hand: `E2B_API_KEY=your-api-key`. - -## 3. Create Your First Sandbox - -### Using the SDK (async) +Save this as `quickstart.py`, then run `python quickstart.py`: ```python import asyncio -from agent_sandbox.api.sandbox import Sandbox -async def main(): - # Create a sandbox (default template: base, timeout: 300 seconds) - sandbox = await Sandbox.create(template="base", timeout=300) - print(f"Sandbox created: {sandbox.id}") - print(f"Status: {sandbox.status.value}") - -asyncio.run(main()) -``` +from agent_sandbox import ProviderSandbox -`base` is the default template (`Sandbox.create()` with no template argument). The repository README uses `python-base` because that image registers the `hello` command shown there. -### Using the SDK (sync) - -```python -from agent_sandbox.api.sandbox import Sandbox - -sandbox = Sandbox.create_sync(template="base") -print(f"Sandbox ID: {sandbox.id}") -``` - -## 4. Execute Code - -### SDK - -```python -result = await sandbox.run_code("print('Hello, Agent Sandbox!')") -print(result.text) # "Hello, Agent Sandbox!" -print(result.stdout) # "Hello, Agent Sandbox!\n" -print(result.exit_code) # 0 -``` - -## 5. Run Shell Commands - -### SDK - -```python -result = await sandbox.commands.run("ls -la /home/user") -print(result.stdout) -print(f"Exit code: {result.exit_code}") -``` - -With `ProviderSandbox` on Express, `commands.run`, `start`, and `stream` accept -`user="root"` or another existing OS account. Starting with 0.3.1a2, the native -envd adapter selects that account for the individual request: - -```python -result = await sandbox.commands.run("id -u", user="root") -assert result.exit_code == 0 and result.stdout.strip() == "0" -``` - -Omitting `user` (or passing `""`) preserves the provider's default account; an -explicit user does not change later or concurrent requests. A missing account -raises an envd error rather than silently using the default. Colons, NUL and line -breaks are rejected as invalid account names. This selects an OS process identity, -not an application-server token or a new provider permission. Earlier native -clients, including 0.3.1a1 and the historical source recipe, silently ignored this -argument; the standard `AsyncSandbox` entry already supports it. - -## 6. File Operations - -### Upload files to the sandbox - -```python -# Write a text file -await sandbox.files.write("/home/user/hello.py", "print('hello world')") - -# Upload a local file -await sandbox.files.upload("./local_script.py", "/home/user/script.py") -``` +async def main(): + async with await ProviderSandbox.create(template="base", timeout=300) as sandbox: + print(f"Sandbox ID: {sandbox.id}") + result = await sandbox.commands.run("printf 'Hello, Agent Sandbox!'") + assert result.exit_code == 0 + print(result.stdout) -### Download files from the sandbox + path = "/home/user/note.txt" + await sandbox.files.write(path, "Hello from Python!") + assert await sandbox.files.read(path) == "Hello from Python!" + await sandbox.files.download(path, "note.txt") + await sandbox.files.upload("note.txt", "/home/user/copied-note.txt") + assert await sandbox.files.read("/home/user/copied-note.txt") == "Hello from Python!" -```python -# Read text -content = await sandbox.files.read("/home/user/hello.py") -print(content) + # The context manager destroys this owned sandbox, including on an exception. -# Download to local -await sandbox.files.download("/home/user/output.csv", "./output.csv") -``` -## 7. List Directory Contents - -```python -files = await sandbox.files.list("/home/user") -for f in files: - print(f"{f.name} ({f.type.value}, {f.size} bytes)") +asyncio.run(main()) ``` -## 8. Destroy a Sandbox +`base` provides command and file operations. It does not imply a code interpreter +or application server. Native process calls accept `user="root"` or another +existing OS account; this selects the account for that request only. -### SDK +For an existing sandbox, `await ProviderSandbox.connect(sandbox_id)` attaches a +client. Call `await sandbox.close()` when finished; delete it with +`await sandbox.kill()` only when you own its lifecycle. -```python -await sandbox.kill() -``` +## 3. Run a Python script -### Using a Context Manager (recommended) +Use command execution when you want to run a Python program on `base`: ```python -async with await Sandbox.create(template="base") as sandbox: - result = await sandbox.run_code("print('auto cleanup')") - print(result.text) -# Automatically destroyed after exiting the with block -``` - -## 9. Complete Example - -```python -import asyncio -from agent_sandbox.api.sandbox import Sandbox - -async def main(): - async with await Sandbox.create(template="base") as sandbox: - # Install dependencies - await sandbox.commands.run("pip install requests") - - # Execute code - result = await sandbox.run_code(""" -import requests -resp = requests.get('https://httpbin.org/get') -print(resp.status_code) -""") - print(f"Status code: {result.text}") - - # Write and read files - await sandbox.files.write("/home/user/note.txt", "Hello!") - content = await sandbox.files.read("/home/user/note.txt") - print(f"File content: {content}") - -asyncio.run(main()) +result = await sandbox.commands.run("python3 -c 'print(1 + 1)'") +assert result.exit_code == 0 and result.stdout.strip() == "2" ``` ---- +Run this inside the context from step 2. This exercises a shell process, not an +interpreter API. For structured interpreter results on Express, use the standard +`agent_sandbox.code_interpreter` entry described in [E2B migration](migrate-from-e2b.md); +the Express `ProviderSandbox` adapter does not implement interpreter operations. -The sandbox server can also host coding-agent CLIs. Codex (`codex`, npm package `@openai/codex`) and Qwen Code (`qwen`, npm package `@qwen-code/qwen-code`) are supported today, on `/v1/agents/sessions`, after `ABX_SERVER_ENABLED_GROUPS` includes `agents`. See [Hosted agents](hosted-agents.md). +## 4. Run a template application -## Next Steps +Use the separately installed [abx CLI](https://github.com/Alibaba-Agent-Sandbox/agent-sandbox) +to launch a catalog template with its declared startup and readiness checks. +Follow [template launch](template-workflows.md) to call its application API and clean +up the owned resources. Creating a plain sandbox with `base` does not start a +template's application. -- [Authentication](authentication.md) — Authentication methods and configuration priority -- [SDK Usage Guide](sdk-usage.md) — Complete API usage -- [Error Codes Reference](../reference/error-codes.md) — Error troubleshooting -- [Troubleshooting](troubleshooting.md) — Common issues and solutions +## Next steps ---- +- [SDK usage](sdk-usage.md): provider extensions and their synchronous wrappers. +- [Declarative functions](declarative-usage.md): execute a Python function remotely. +- [MCP integration](mcp-integration.md): connect an IDE or agent. +- [Troubleshooting](troubleshooting.md): installation and runtime errors. ## Related: the abx CLI -The command-line equivalents of the steps above (installing `abx` with npm or as a standalone binary, `abx config set`, `abx create`, `abx exec`, `abx upload` / `download`, `abx kill`) are in the CLI repository: [Getting Started (CLI)](https://github.com/alibaba-agent-sandbox/agent-sandbox/blob/main/docs/en/guide/getting-started.md), [Binary Installation](https://github.com/alibaba-agent-sandbox/agent-sandbox/blob/main/docs/en/guide/binary-installation.md), [CLI Tutorial](https://github.com/alibaba-agent-sandbox/agent-sandbox/blob/main/docs/en/guide/cli-tutorial.md) and [Using Templates](https://github.com/alibaba-agent-sandbox/agent-sandbox/blob/main/docs/en/guide/using-templates.md). +The CLI is a separate Node.js package, `@agent-sandbox/cli`. Installing Python does +not install `abx`; there is no Python `[cli]` extra. Follow the +[CLI installation guide](https://github.com/Alibaba-Agent-Sandbox/agent-sandbox/blob/main/docs/en/guide/binary-installation.md). diff --git a/docs/en/guide/install-python.md b/docs/en/guide/install-python.md index a73cb4ab..625ea861 100644 --- a/docs/en/guide/install-python.md +++ b/docs/en/guide/install-python.md @@ -1,6 +1,6 @@ # Install the Python packages -> Specification 5 template launch requires the matching `agent-sandbox-client==0.4.0a1` and `agent-sandbox-server==0.4.0a1` alpha packages used in this guide. The previous 0.3.x packages do not implement this entry point. To validate a source revision, install both distributions from the same checkout as described below. +> Specification 5 template launch requires the matching `agent-sandbox-client==0.4.0a2` and `agent-sandbox-server==0.4.0a2` alpha packages used in this guide. The previous 0.3.x packages do not implement this entry point. To validate a source revision, install both distributions from the same checkout as described below. Use Python 3.10 or newer and a virtual environment: @@ -9,7 +9,7 @@ python -m venv .venv # Linux or macOS: source .venv/bin/activate # Windows PowerShell: .venv\Scripts\Activate.ps1 -python -m pip install --index-url https://pypi.org/simple 'agent-sandbox-client==0.4.0a1' +python -m pip install --index-url https://pypi.org/simple 'agent-sandbox-client==0.4.0a2' python -m pip check ``` @@ -23,18 +23,23 @@ python -c "from importlib.metadata import version; print(version('agent-sandbox- Install the [abx CLI](https://github.com/Alibaba-Agent-Sandbox/agent-sandbox) separately. For template launch in this guide, use CLI 0.5.0 or newer and configure the selected provider before creating a sandbox. +Project configuration uses `ABX_SANDBOX_API_KEY`, `ABX_SANDBOX_BASE_URL` and +`ABX_SANDBOX_DOMAIN` for all project entries, including standard Sandbox / +AsyncSandbox and ProviderSandbox. Public keyword parameters still follow each +entry's documented contract; the standard `api_key=` parameter remains valid. + ## Optional dependencies ```bash -python -m pip install 'agent-sandbox-client[all]==0.4.0a1' +python -m pip install --index-url https://pypi.org/simple 'agent-sandbox-client[all]==0.4.0a2' ``` -Replace `[all]` with `[mcp]`, `[session]` or `[fast]` for that subset. Workflow YAML and the declarative decorator belong to the base client; they need no extra. Browser automation requires Playwright installed inside the sandbox image. +Replace `[all]` with `[mcp]`, `[session]` or `[fast]` for that subset. Template YAML and the declarative decorator belong to the base client; they need no extra. Browser automation requires Playwright installed inside the sandbox image. ## Server-only installation inside an image ```bash -python -m pip install 'agent-sandbox-server==0.4.0a1' +python -m pip install --index-url https://pypi.org/simple 'agent-sandbox-server==0.4.0a2' ``` The server runs the application inside an image. Installing it does not create a sandbox. See the [server guide](server-sdk.md) to register commands and start the service. diff --git a/docs/en/guide/mcp-integration.md b/docs/en/guide/mcp-integration.md index 90c58536..1e394dd5 100644 --- a/docs/en/guide/mcp-integration.md +++ b/docs/en/guide/mcp-integration.md @@ -13,8 +13,8 @@ MCP (Model Context Protocol) is an open protocol that allows AI models to intera ### Requirements ```bash -pip install agent-sandbox-client # the SDK's own MCP STDIO server: python -m agent_sandbox.agent.mcp -export E2B_API_KEY=your-api-key +pip install --index-url https://pypi.org/simple "agent-sandbox-client==0.4.0a2" # the SDK's own MCP STDIO server: python -m agent_sandbox.agent.mcp +export ABX_SANDBOX_API_KEY=your-api-key ``` The Node.js `abx` CLI ships a second implementation of the same server (`abx mcp ...`, installed with `npm install -g @agent-sandbox/cli`); see [Related: the abx CLI](#related-the-abx-cli). @@ -29,13 +29,13 @@ Point the IDE's MCP configuration at the Python server. For example, in Cursor's "agent-sandbox": { "command": "python", "args": ["-m", "agent_sandbox.agent.mcp"], - "env": { "E2B_API_KEY": "your-api-key" } + "env": { "ABX_SANDBOX_API_KEY": "your-api-key" } } } } ``` -`python -m agent_sandbox.agent.mcp` reads `E2B_API_KEY`, `E2B_API_URL`, `E2B_DOMAIN`, and the default template from `ABX_DEFAULT_TEMPLATE` (default `base`). Restart the IDE after editing its configuration. The server speaks the same tools over STDIO, so the [Available Tools](#available-tools) below apply unchanged. +`python -m agent_sandbox.agent.mcp` reads `ABX_SANDBOX_API_KEY`, `ABX_SANDBOX_BASE_URL`, `ABX_SANDBOX_DOMAIN`, and the default template from `ABX_DEFAULT_TEMPLATE` (default `base`). Restart the IDE after editing its configuration. The server speaks the same tools over STDIO, so the [Available Tools](#available-tools) below apply unchanged. The `abx mcp install --target cursor|claude|vscode` and `abx mcp status` commands write and inspect these files for you; see [Related: the abx CLI](#related-the-abx-cli). @@ -97,10 +97,10 @@ For team sharing or remote access, run the MCP Server as a Streamable HTTP servi ### Run Locally with uvicorn ```bash -pip install "agent-sandbox-client[mcp]" +pip install --index-url https://pypi.org/simple "agent-sandbox-client[mcp]==0.4.0a2" export ABX_MCP_AUTH_TOKEN=replace_me # Bearer token (omit to disable auth) -export E2B_API_KEY=your-api-key +export ABX_SANDBOX_API_KEY=your-api-key uvicorn agent_sandbox.agent.mcp_http:asgi_app --host 0.0.0.0 --port 9000 ``` @@ -114,7 +114,7 @@ from agent_sandbox.agent.mcp_http import create_mcp_app app = create_mcp_app( auth_token="replace_me", # None disables client auth - api_key="your-api-key", + sandbox_api_key="your-api-key", template="base", ) ``` @@ -125,7 +125,7 @@ The entry points use different credentials: | Entry | Client authentication | How to configure | |-------|----------------------|------------------| -| `python -m agent_sandbox.agent.mcp` (STDIO) | No Bearer token. The IDE starts a local process; it does not listen on the network | Sandbox calls use `E2B_API_KEY` | +| `python -m agent_sandbox.agent.mcp` (STDIO) | No Bearer token. The IDE starts a local process; it does not listen on the network | Sandbox calls use `ABX_SANDBOX_API_KEY` | | `uvicorn agent_sandbox.agent.mcp_http:asgi_app` / `create_mcp_app()` | Bearer token. Loopback may omit it (the process warns) | `ABX_MCP_AUTH_TOKEN` or `auth_token=` | | Remote function on Alibaba Cloud FC | Bearer token is required. The artifact `app.py` refuses to start when the token is empty, so a remote process cannot boot with authentication disabled | The token goes into the function environment as `ABX_MCP_AUTH_TOKEN`. The FC HTTP trigger uses `anonymous` so an MCP client does not need an Alibaba Cloud signature; the application Bearer token is the check. `GET /health` returns status and protocol only, with no token check and no secrets | @@ -167,7 +167,7 @@ The artifact directory contains: | File | Content | |------|---------| | `requirements.txt` | `agent-sandbox-client[mcp]`, `uvicorn>=0.29` | -| `app.py` | ASGI entry point reading FC env vars (`ABX_MCP_AUTH_TOKEN`, `E2B_API_KEY`, `E2B_API_URL`, `E2B_DOMAIN`, `ABX_DEFAULT_TEMPLATE`) | +| `app.py` | ASGI entry point reading FC env vars (`ABX_MCP_AUTH_TOKEN`, `ABX_SANDBOX_API_KEY`, `ABX_SANDBOX_BASE_URL`, `ABX_SANDBOX_DOMAIN`, `ABX_DEFAULT_TEMPLATE`) | | `config.yaml` | YAML manifest with function name, region, runtime `python3.10`, handler `app.app`, memory/timeout, env vars, HTTP trigger (POST/GET/DELETE), session affinity | The deployment steps are: package → create function → create HTTP trigger → enable `Mcp-Session-Id` affinity if supported. @@ -247,8 +247,8 @@ curl -s -X DELETE http://localhost:9000/mcp \ | Symptom | Likely cause | Fix | |---------|--------------|-----| | IDE shows the server as failed / no tools | `python` on the IDE's `PATH` is not the interpreter that has `agent-sandbox` installed | Use an absolute interpreter path in the IDE config's `command` | -| Tools list works but every call errors | API key missing or invalid | Set `E2B_API_KEY` in the server's `env` block | -| `create_sandbox` fails after IDE restart | Backend API URL/region mismatch | Set `E2B_API_URL` in the server's `env` block | +| Tools list works but every call errors | API key missing or invalid | Set `ABX_SANDBOX_API_KEY` in the server's `env` block | +| `create_sandbox` fails after IDE restart | Backend API URL/region mismatch | Set `ABX_SANDBOX_BASE_URL` in the server's `env` block | | HTTP 401 on every request | Empty `ABX_MCP_AUTH_TOKEN` (fails closed) | Set a non-empty token. A local loopback server can omit the variable to disable auth. The FC artifact will not start without a token | | HTTP 404 Unknown session | `Mcp-Session-Id` expired (idle TTL 3600 s) or instance restarted | Re-send `initialize` to create a new session | | HTTP 503 session limit | More than 100 concurrent sessions in the process | Close idle sessions (`DELETE /mcp`) or raise `max_sessions` via `create_mcp_app()` | diff --git a/docs/en/guide/migrate-from-e2b.md b/docs/en/guide/migrate-from-e2b.md index 8563c8fc..52faae9d 100644 --- a/docs/en/guide/migrate-from-e2b.md +++ b/docs/en/guide/migrate-from-e2b.md @@ -4,7 +4,8 @@ The standard Python API targets `e2b==2.31.0` and `e2b-code-interpreter==2.8.1`, ## Installation and imports -Install `agent-sandbox-client` from this checkout (`pip install ./server-sdk ./client-sdk`) until the new package is released. Keep the existing Alibaba `E2B_API_KEY`, `E2B_API_URL` and `E2B_DOMAIN` configuration. `abx config` and project/home configuration files also feed these settings; explicit SDK keyword arguments take precedence. Standard entries accept `E2B_*` settings; the native `ProviderSandbox` retains canonical `ABX_SANDBOX_*` configuration. Existing project configuration remains the fallback for standard entries. +Install the published client with `python -m pip install --index-url https://pypi.org/simple agent-sandbox-client==0.4.0a2`. Configure the Express account with `ABX_SANDBOX_API_KEY`, `ABX_SANDBOX_BASE_URL` and `ABX_SANDBOX_DOMAIN`; these project settings work for standard `Sandbox` / `AsyncSandbox`, `code_interpreter` and `ProviderSandbox`. `abx config` and project/home configuration files also feed these settings. The standard client's public `api_key=` parameter remains part of its pinned contract. A separate application still using the third-party E2B SDK uses that SDK's native configuration names; do not send credentials from another provider account. + | Previous import | New import | |---|---| diff --git a/docs/en/guide/provider-commands.md b/docs/en/guide/provider-commands.md index b9034353..cfe7114e 100644 --- a/docs/en/guide/provider-commands.md +++ b/docs/en/guide/provider-commands.md @@ -42,18 +42,13 @@ hints for other providers fail with E8004 before loading their implementation. O dictionaries preserve existing request payloads. This creation hint is separate from management commands and does not add a portable -`storage.mount` protocol or runtime attach API. Python's built-in lifecycle retains its local -gRPC engine: additive `CreateRequest.volume_mounts` carries the dictionary, and the existing -Python protocol serializes `POST /sandboxes` as -`"volumeMounts": [{"name": "existing-volume-name", "path": "/mnt/data"}]`. -For nonempty hints, the client first checks `Health.supported_create_options` contains -`volume_mounts`. An older live engine fails with E8004 and an upgrade/restart suggestion, -before `Create`; it is never replaced automatically. This prevents older protobuf handlers -from silently ignoring a mount request. Calls without mounts retain the existing behavior. -Provider management commands continue using the shared Node HTTP engine. Mount wiring is -covered by local gRPC/HTTP regression tests and real OSS mount/read/write/cleanup acceptance -on the base template in cn-hangzhou. The opt-in Volume E2E suite also checks that data survives -sandbox destruction and recreation. +`storage.mount` protocol or runtime attach API. The client validates the selected +provider's `create_options` before creating a sandbox. The built-in provider sends +`"volumeMounts": [{"name": "existing-volume-name", "path": "/mnt/data"}]` in +`POST /sandboxes` using its direct HTTP transport. Provider management commands +use the separate shared Node HTTP engine. The opt-in Volume E2E suite checks +mount/read/write/cleanup and persistence across sandbox recreation; live access +remains subject to the account and image prerequisites above. ## Python API diff --git a/docs/en/guide/sdk-usage.md b/docs/en/guide/sdk-usage.md index 3113f19f..f3c0467a 100644 --- a/docs/en/guide/sdk-usage.md +++ b/docs/en/guide/sdk-usage.md @@ -6,7 +6,7 @@ This page documents the asynchronous **ProviderSandbox** provider/server extensi ## Installation -Follow the [installation guide](install-python.md). The public client/server alpha pair is 0.4.0a1; installing the client installs the matching server dependency. Host package installation does not change existing sandbox images. +Follow the [installation guide](install-python.md). The public client/server alpha pair is 0.4.0a2; installing the client installs the matching server dependency. Host package installation does not change existing sandbox images. Do not run `pip install agent-sandbox`. That name on PyPI is an unrelated project. @@ -22,42 +22,12 @@ from agent_sandbox import ProviderSandbox as Sandbox The template-author example below retains its explicit deployment prerequisite. When connecting to an existing instance returned by the CLI, obtain an application client with `await sandbox.application_client(9000, token=application_token, timeout=330)` and call `client.commands.run(...)`; see [template workflows](template-workflows.md). This preserves provider gateway headers, URL prefixes and signed query parameters. `close()` releases a connection; `kill()` deletes an instance. Do not delete a borrowed instance. An HTTP wait timeout does not guarantee remote cancellation and does not automatically replay a command. -## Template author quick path +## Template applications -Verified 2026-10-15 on Alibaba Cloud Express (`alicloud-express`) with a generation-2 template whose start command runs `agent-sandbox-server`. `Sandbox.create(template=..., provider="alicloud-express")` uses `ABX_SANDBOX_API_KEY`, `ABX_SANDBOX_BASE_URL`, and `ABX_SANDBOX_DOMAIN`. The template argument is the template id or its name. - -```python -import asyncio - -from agent_sandbox import ProviderSandbox as Sandbox - -TEMPLATE = "hello-x" # name or id of a generation-2 template - - -async def main() -> None: - async with await Sandbox.create( - template=TEMPLATE, provider="alicloud-express", timeout=300 - ) as sb: - assert await sb.run("hello", name="Bob") == "Hello, Bob!" - echoed = await sb.commands.run("echo hi", on_stdout=lambda text: None) - assert echoed.stdout == "hi\n" and echoed.exit_code == 0 - await sb.files.write("/home/user/note.txt", "abc") - assert await sb.files.read("/home/user/note.txt") == "abc" - url = sb.network.get_url(9000) - headers = sb.network.get_access_headers() - # GET {url}/health with headers. /health answers 200. - - -asyncio.run(main()) -``` - -`sandbox.run` is the one call for a named command. It returns the function's value. `timeout=` (seconds) is the HTTP limit for a slow command and is not passed to the function. Shell output streams through `on_stdout` / `on_stderr` on `commands.run`. A named command does not stream its own prints; it returns when the function returns. - -An unknown name raises `CommandNotFoundError` and lists the commands the server reported. Bad arguments raise `CommandArgumentError`. A command that raises raises `CommandExecutionError` (`error_type` is the exception class). The context manager calls `kill()`. - -Deploy the template with `abx template deploy . -y --generation 2 --start-cmd 'agent-sandbox-server serve --port 9000 --commands /home/user/app/commands.py' --ready-cmd 'agent-sandbox-server healthcheck --port 9000'`. Full steps: [Express quickstart](express-quickstart.md). - ---- +Launch the complete template with `abx template launch `, then use +`application_client` to call its registered commands with the application token. +Source image preparation and platform configuration belong to the CLI. See +[Express quickstart](express-quickstart.md) and [template launch](template-workflows.md). ## Create and Destroy diff --git a/docs/en/guide/server-sdk.md b/docs/en/guide/server-sdk.md index 23c6f811..fcf96acc 100644 --- a/docs/en/guide/server-sdk.md +++ b/docs/en/guide/server-sdk.md @@ -5,12 +5,12 @@ For current SDK installation, use the [installation guide](install-python.md). The Server SDK runs **inside the sandbox**. It is the HTTP service the image keeps listening on, port 9000 by default. The package is `agent-sandbox-server`. Import `agent_sandbox.server`. A template's `commands.py` uses it to register commands, turn capabilities on, and call `start(9000)`. The following explicitly opts into the published alpha. The matching client version -is 0.3.1a1. The explicit official index makes this example independent of a locally +is 0.4.0a2. The explicit official index makes this example independent of a locally configured mirror; it does not imply that mirrors are generally unavailable. -For a pinned source installation, use the linked installation guide. +Development from a checkout is covered in the installation guide. ```bash -python -m pip install --index-url https://pypi.org/simple "agent-sandbox-server==0.3.1a1" +python -m pip install --index-url https://pypi.org/simple "agent-sandbox-server==0.4.0a2" ``` ```python diff --git a/docs/en/guide/template-server-api.md b/docs/en/guide/template-server-api.md index 3e0abd9e..12a56d4d 100644 --- a/docs/en/guide/template-server-api.md +++ b/docs/en/guide/template-server-api.md @@ -13,7 +13,7 @@ A short client for a server that is already running is [`examples/templates/pyth The server defaults to `0.0.0.0:9000`. The provider must implement the required port resolution and network path, and the service must actually listen. Do not treat every endpoint as a `{port}-{sandbox_id}.{domain}` hostname. Resolve application HTTP independently from internal envd/EPP transport: This example uses the provider-native `ProviderSandbox` API in the published -`agent-sandbox-client==0.3.1a1` alpha; the standard `Sandbox`/`AsyncSandbox` classes +`agent-sandbox-client==0.4.0a2` alpha; the standard `Sandbox`/`AsyncSandbox` classes have a different interface. See [installation](install-python.md) for the exact package/source choices. Set `SANDBOX_ID` to an existing sandbox whose application server is running, and `ABX_SERVER_TOKEN` only if that server was started with it. diff --git a/docs/en/guide/troubleshooting.md b/docs/en/guide/troubleshooting.md index 6a588a76..1e74d2d6 100644 --- a/docs/en/guide/troubleshooting.md +++ b/docs/en/guide/troubleshooting.md @@ -1,6 +1,6 @@ # Troubleshooting (FAQ) -For current SDK installation, use the [paired source installation guide](install-python.md). +For current SDK installation, use the [installation guide](install-python.md). > **Note:** The `abx` commands shown on this page are provided by the Node.js CLI in the `cli` repository ([CLI binary installation](https://github.com/Alibaba-Agent-Sandbox/agent-sandbox/blob/main/docs/en/guide/binary-installation.md)). CLI-specific documentation (CLI design, tutorial, reference) lives there too; this repository documents the Python SDK (`agent-sandbox-client`) and the container-side runtime (`agent-sandbox-server`). @@ -42,7 +42,7 @@ For current SDK installation, use the [paired source installation guide](install ```text [E1001] API key cannot be empty - Suggestion: Check your E2B_API_KEY environment variable or pass sandbox_api_key. + Suggestion: Check your ABX_SANDBOX_API_KEY environment variable or pass sandbox_api_key. ``` **Solution**: @@ -54,7 +54,7 @@ abx config get sandbox_api_key abx config set sandbox_api_key your-api-key # Or set the environment variable -export E2B_API_KEY="your-api-key" +export ABX_SANDBOX_API_KEY="your-api-key" ``` ### E1003 — Invalid AK/SK Credentials @@ -211,9 +211,7 @@ Check file permissions. The default user in the sandbox is `user`; you can speci ```bash # Ensure the correct package name -python -m pip install \ - "agent-sandbox-server @ https://github.com/Alibaba-Agent-Sandbox/python-sdk/archive/3aa5e5ae6bd9c843f62c6689e549437f460b382d.tar.gz#subdirectory=server-sdk" \ - "agent-sandbox-client @ https://github.com/Alibaba-Agent-Sandbox/python-sdk/archive/3aa5e5ae6bd9c843f62c6689e549437f460b382d.tar.gz#subdirectory=client-sdk" +python -m pip install --index-url https://pypi.org/simple "agent-sandbox-client==0.4.0a2" # If dependency conflicts occur python -m pip check diff --git a/docs/en/reference/api-reference.md b/docs/en/reference/api-reference.md index c0ca3ddd..9070baf4 100644 --- a/docs/en/reference/api-reference.md +++ b/docs/en/reference/api-reference.md @@ -1,13 +1,13 @@ # API Reference -This document lists all public API signatures, parameters, return values, and exceptions of the Agent Sandbox Python SDK. +This reference describes the ProviderSandbox extension API. Root Sandbox / AsyncSandbox follow the independent standard contract described in [E2B migration](../guide/migrate-from-e2b.md). --- ## Sandbox Class ```python -from agent_sandbox.api.sandbox import Sandbox +from agent_sandbox import ProviderSandbox as Sandbox ``` ### Class Methods @@ -29,7 +29,7 @@ async def create( memory: int | None = None, disk: int | None = None, gpu: str | None = None, - secure: bool = True, + secure: bool | None = None, sandbox_api_key: str | None = None, sandbox_base_url: str | None = None, sandbox_domain: str | None = None, @@ -44,7 +44,7 @@ Create a new sandbox. |-----------|------|---------|-------------| | `template` | `str` | `"base"` | Sandbox template name | | `timeout` | `int` | `300` | Sandbox lifetime (TTL) in seconds (1–86400); not an HTTP timeout | -| `request_timeout` | `float` | `None` | Per-request HTTP timeout (seconds) for the create call only. When `None`, uses `SANDBOX_HTTP_TIMEOUT` / `http_timeout`. Aligns with the E2B SDK. Raising it does not work around platform-side create stalls. | +| `request_timeout` | `float` | `None` | Per-request HTTP timeout (seconds) for the create call only. When `None`, uses `ABX_HTTP_TIMEOUT` / `http_timeout`. Aligns with the E2B SDK. Raising it does not work around platform-side create stalls. | | `metadata` | `dict` | `None` | Arbitrary metadata key-value pairs | | `envs` | `dict` | `None` | Injected environment variables | | `volume_mounts` | `dict[str, str]` | `None` | Built-in provider only: normalized absolute sandbox path → existing Volume name. Omitted/empty means no mounts. Other providers reject nonempty hints with E8004. See [mount requirements and wire schema](../guide/provider-commands.md#mount-an-existing-volume-when-creating-a-sandbox). | @@ -52,7 +52,7 @@ Create a new sandbox. | `memory` | `int` | `None` | Memory in MB | | `disk` | `int` | `None` | Disk in MB | | `gpu` | `str` | `None` | GPU specification (e.g., `"A10"`) | -| `secure` | `bool` | `True` | Secure mode (port access requires token) | +| `secure` | `bool` | `None` | Secure mode (port access requires token) | | `sandbox_api_key` | `str` | `None` | API Key override | | `sandbox_base_url` | `str` | `None` | Platform API URL override | | `sandbox_domain` | `str` | `None` | Domain override | diff --git a/docs/en/reference/configuration.md b/docs/en/reference/configuration.md index 71abe4fb..880bb198 100644 --- a/docs/en/reference/configuration.md +++ b/docs/en/reference/configuration.md @@ -205,7 +205,7 @@ explain_config() # {"sandbox_api_key": {"value": "****3dc1", "source": "enviro Pass parameters directly in code (highest priority): ```python -from agent_sandbox.api.sandbox import Sandbox +from agent_sandbox import ProviderSandbox as Sandbox sandbox = await Sandbox.create( sandbox_api_key="REPLACE_ME", diff --git a/docs/zh/DESIGN.md b/docs/zh/DESIGN.md index 9145e9e7..03f031f6 100644 --- a/docs/zh/DESIGN.md +++ b/docs/zh/DESIGN.md @@ -21,7 +21,7 @@ ### 快速上手 ```bash -pip install agent-sandbox-client +python -m pip install --index-url https://pypi.org/simple agent-sandbox-client==0.4.0a2 export ABX_SANDBOX_API_KEY=your-api-key ``` @@ -29,8 +29,8 @@ export ABX_SANDBOX_API_KEY=your-api-key from agent_sandbox import ProviderSandbox as Sandbox async with await Sandbox.create(template="base") as sb: - result = await sb.run_code("print('Hello, Agent Sandbox!')") - print(result.text) + result = await sb.commands.run("printf 'Hello, Agent Sandbox!'") + print(result.stdout) ``` --- diff --git a/docs/zh/design/mcp-server.md b/docs/zh/design/mcp-server.md index 9c1cafc6..4ae29cb8 100644 --- a/docs/zh/design/mcp-server.md +++ b/docs/zh/design/mcp-server.md @@ -292,7 +292,7 @@ graph LR - **会话**:进程内 `SessionStore`;空闲 TTL 默认 3600 秒、并发会话上限默认 100;容量满时返回 503 与 JSON-RPC 错误 `-32000` - **版本协商**:`initialize` 在请求版本受支持时原样回显;本传输仅支持 `2025-06-18`,与 `GET /health` 一致。请求缺失或不支持的版本时协商到 `2025-06-18` —— 按 MCP 规范,服务器回复自己支持的版本,无法接受的客户端可自行断开。STDIO 传输独立保持 `2024-11-05` - **适用场景**:远程服务、团队共享、多客户端;用 CLI 的 `abx mcp deploy` 生成的产物部署到阿里云 FC,或本地以 uvicorn 运行 -- **可选依赖**:Starlette + uvicorn(`pip install 'agent-sandbox-client[mcp]'`) +- **可选依赖**:Starlette + uvicorn(`pip install --index-url https://pypi.org/simple 'agent-sandbox-client[mcp]==0.4.0a2'`) ### 认证 diff --git a/docs/zh/design/provider-e2b.md b/docs/zh/design/provider-e2b.md index 518e32aa..fd4079d1 100644 --- a/docs/zh/design/provider-e2b.md +++ b/docs/zh/design/provider-e2b.md @@ -20,9 +20,9 @@ E2B 是目录提供方,源码在 `awesome-providers/e2b`,id 是 `e2b`。用 | `domain` | 字符串 | `ABX_E2B_DOMAIN` | `e2b.app` | | `api_key` | 密钥 | `ABX_E2B_API_KEY` | 不设置 | -这三个名字也可以放在 `provider_options` 里。`Sandbox.create(api_url=...)` 不会改这个源站。解析器读的是 `provider_options["base_url"]`。 +这三个名字也可以放在 `provider_options` 里。通过 `provider_options["base_url"]` 选择源站,而不是顶层 API URL 覆盖。 -设置了密钥时,客户端发送请求头 `X-API-Key`。没有 `ABX_E2B_API_KEY` 时抛出 `InvalidAPIKeyError`,错误信息里写明 `ABX_E2B_API_KEY`。这个提供方不读 `ABX_SANDBOX_API_KEY`(阿里云极速版的密钥),也不读 `ABX_SANDBOX_API_KEY`(本产品拒绝的旧名字)。 +设置了密钥时,客户端发送请求头 `X-API-Key`。没有 `ABX_E2B_API_KEY` 时抛出 `InvalidAPIKeyError`,错误信息里写明 `ABX_E2B_API_KEY`。这个提供方不读 `ABX_SANDBOX_API_KEY`(阿里云极速版的密钥)。 `domain` 是 `https://{port}-{sandboxID}.{domain}` 的后缀。envd 端口是 49983。创建响应里没有 `region` 时保持未知(空字符串),不会落成 `cn-hangzhou`。 diff --git a/docs/zh/guide/authentication.md b/docs/zh/guide/authentication.md index eb4c562d..d4940667 100644 --- a/docs/zh/guide/authentication.md +++ b/docs/zh/guide/authentication.md @@ -2,7 +2,7 @@ 本指南描述异步 `ProviderSandbox` 扩展;根级 `Sandbox` 和 `AsyncSandbox` 遵循固定版本的标准迁移契约,详见[从 E2B 迁移](migrate-from-e2b.md)。 -当前 SDK 安装使用[配套源码安装指南](install-python.md)。 +当前 SDK 安装使用[安装指南](install-python.md)。 > **说明:** 本页出现的 `abx` 命令由 `cli` 仓库中的 Node.js CLI 提供([CLI binary installation](https://github.com/Alibaba-Agent-Sandbox/agent-sandbox/blob/main/docs/en/guide/binary-installation.md))。CLI 专属文档(CLI 设计、教程、参考)也在该仓库;本仓库记录 Python SDK(`agent-sandbox-client`)与容器侧运行时(`agent-sandbox-server`)。 @@ -68,7 +68,7 @@ sandbox_domain = "cn-hangzhou.e2b.fc.aliyuncs.com" #### 5. 代码参数(高于环境变量和 `~/.abx`) ```python -from agent_sandbox.api.sandbox import Sandbox +from agent_sandbox import ProviderSandbox as Sandbox # 创建时直接传入 sandbox = await Sandbox.create(sandbox_api_key="your-api-key") @@ -85,7 +85,7 @@ sandbox = await Sandbox.connect("sbx-xxxx", sandbox_api_key="your-api-key") 过去自动将 AK/SK 换成沙箱密钥的默认路径已删除。仅配置 AccessKey 时,沙箱鉴权 会在本地、任何交换请求或网络请求之前抛出 `InvalidAPIKeyError`(E1001)。 沙箱创建、连接、列表及运行时请求请配置 `ABX_SANDBOX_API_KEY`,或显式传入 -`sandbox_api_key=` / `api_key=`。 +`sandbox_api_key=`。 官方模板、镜像和 ACR 控制面仍使用 `ALICLOUD_ACCESS_KEY_ID`、 `ALICLOUD_ACCESS_KEY_SECRET` 与对应区域;这些操作使用独立客户端,已有支持的 diff --git a/docs/zh/guide/authoring-templates.md b/docs/zh/guide/authoring-templates.md index 092e64bb..10f342f0 100644 --- a/docs/zh/guide/authoring-templates.md +++ b/docs/zh/guide/authoring-templates.md @@ -1,6 +1,6 @@ # 编写模板 -当前 SDK 安装使用[配套源码安装指南](install-python.md)。 +当前 SDK 安装使用[安装指南](install-python.md)。 > **说明:** 本页出现的 `abx` 命令由 `cli` 仓库中的 Node.js CLI 提供([CLI binary installation](https://github.com/Alibaba-Agent-Sandbox/agent-sandbox/blob/main/docs/en/guide/binary-installation.md))。CLI 专属文档(CLI 设计、教程、参考)也在该仓库;本仓库记录 Python SDK(`agent-sandbox-client`)与容器侧运行时(`agent-sandbox-server`)。 @@ -133,7 +133,7 @@ if __name__ == "__main__": 服务端不选择 Provider。9000 是应用 HTTP 默认监听端口;平台注入的 envd、解释器及保留端口属于各后端,不能据此推导应用服务不可用。声明的 `start_cmd` 只运行一次,没有该字段时使用镜像或平台模板入口;不要让原生入口与启动命令重复运行。非空 `ready_cmd` 必须实际检查。构建配置必须明确选择,其有效 Dockerfile 和构建参数进入输入身份。 `commands.py` 只导入 `agent_sandbox.server`,在主入口调用 `start(port)`;镜像显式安装 server SDK。 -已发布 0.3.1a1 alpha 中的 Provider 原生应用 API 使用 `from agent_sandbox import ProviderSandbox`, +已发布 0.4.0a2 alpha 中的 Provider 原生应用 API 使用 `from agent_sandbox import ProviderSandbox`, 再通过 `await ProviderSandbox.connect(ID)` 连接。这个实例支持 `async with await sandbox.application_client(9000, token=application_token)`;标准 `Sandbox`/`AsyncSandbox` 是另一套接口。应用端点解析保留代理前缀,并隔离网关和应用凭据。 diff --git a/docs/zh/guide/client-sdk.md b/docs/zh/guide/client-sdk.md index 77015ecd..dbfcfda2 100644 --- a/docs/zh/guide/client-sdk.md +++ b/docs/zh/guide/client-sdk.md @@ -5,7 +5,7 @@ Client SDK 跑在**你的机器**上。它创建沙箱、连上已经存在的沙箱,然后在沙箱里执行命令、读写文件、调用代码解释器。包名是 `agent-sandbox-client`,导入 `agent_sandbox`。 ```bash -python -m pip install 'agent-sandbox-client==0.4.0a1' +python -m pip install --index-url https://pypi.org/simple 'agent-sandbox-client==0.4.0a2' python -m pip check ``` diff --git a/docs/zh/guide/cloud-examples.md b/docs/zh/guide/cloud-examples.md index 948a668f..2599f966 100644 --- a/docs/zh/guide/cloud-examples.md +++ b/docs/zh/guide/cloud-examples.md @@ -3,7 +3,7 @@ 安装客户端时自动安装同版本服务端: ```bash -python -m pip install "agent-sandbox-client[all]==0.4.0a2" +python -m pip install --index-url https://pypi.org/simple "agent-sandbox-client[all]==0.4.0a2" export ABX_SANDBOX_API_KEY="your-express-sandbox-api-key" # 非默认地域按需配置 ABX_SANDBOX_BASE_URL、ABX_SANDBOX_DOMAIN。 ``` @@ -33,7 +33,7 @@ Node HTTP 入门示例直接使用 `base` 自带的 Node,无需先部署另一 浏览器示例安装 Playwright 和真实无头 Chromium。默认页面由自有沙箱内的 HTTP 服务提供,可稳定验证标题、链接和截图。设置 `BROWSER_URL` 可访问外部站点,HTTP 失败或缺少预期内容会明确报错。安装仍需连接包和浏览器下载源。 -标准客户端导入迁移示例使用配置为极速版账号的 `E2B_API_KEY`、`E2B_API_URL`、`E2B_DOMAIN`,然后执行 `python examples/compat-demos/e2b_import_migration.py`。这些配置名属于标准 E2B 兼容客户端;不要使用其他平台账号的密钥。上述 `ProviderSandbox` 和装饰器示例使用 `ABX_SANDBOX_API_KEY`。 +标准客户端导入迁移示例与其他示例统一使用项目配置 `ABX_SANDBOX_API_KEY`、`ABX_SANDBOX_BASE_URL` 和 `ABX_SANDBOX_DOMAIN`,执行 `python examples/compat-demos/e2b_import_migration.py`。这些值必须属于极速版账号,不要混用不同提供商的凭据。 本地 HTTP、会话示例执行 `python examples/run_examples_e2e.py`。它运行真实本地服务进程及受控 Codex/Qwen 协议程序,不调用模型;云端脚本会明确列为 `needs-provider`。另见[示例目录](../../../examples/README.zh-CN.md)和[模板 HTTP API](template-server-api.md)。 diff --git a/docs/zh/guide/command-map.md b/docs/zh/guide/command-map.md index 08740aa4..e6c03661 100644 --- a/docs/zh/guide/command-map.md +++ b/docs/zh/guide/command-map.md @@ -10,7 +10,7 @@ | 产品 | 命令行 | SDK | |---|---|---| -| Agent Sandbox | `abx`(`@agent-sandbox/cli`) | `agent-sandbox-client`,`from agent_sandbox.api.sandbox import Sandbox` | +| Agent Sandbox | `abx`(`@agent-sandbox/cli`) | `agent-sandbox-client`,`from agent_sandbox import ProviderSandbox` | | E2B | `e2b`(`@e2b/cli`,文档版本 2.16.1) | `e2b`,`from e2b import Sandbox` | | OpenSandbox | `osb`(`opensandbox-cli`,[CLI 文档](https://open-sandbox.ai/cli/)) | `opensandbox`,`from opensandbox import Sandbox`([Python SDK](https://open-sandbox.ai/sdks/python)) | @@ -23,7 +23,7 @@ | 做什么 | abx | Agent Sandbox SDK | e2b | E2B SDK | osb | OpenSandbox SDK | |---|---|---|---|---|---|---| | 安装 | [CLI binary installation](https://github.com/Alibaba-Agent-Sandbox/agent-sandbox/blob/main/docs/en/guide/binary-installation.md) | [Paired source install](install-python.md) | `npm install -g @e2b/cli` | `pip install e2b` | `pip install opensandbox-cli` | `pip install opensandbox` | -| 写入凭证 | `abx config set sandbox_api_key` | 环境变量 `E2B_API_KEY` | `e2b auth login` | 环境变量 `E2B_API_KEY` | `osb config set connection.api_key` | `ConnectionConfig(api_key=…)` 或 `OPEN_SANDBOX_API_KEY` | +| 写入凭证 | `abx config set sandbox_api_key` | 环境变量 `ABX_SANDBOX_API_KEY` | `e2b auth login` | 环境变量 `E2B_API_KEY` | `osb config set connection.api_key` | `ConnectionConfig(api_key=…)` 或 `OPEN_SANDBOX_API_KEY` | | 查看生效配置 | `abx config list` | — | `e2b auth info` | — | `osb config show` | — | 阿里云 AccessKey 保持官方名字 `ALICLOUD_ACCESS_KEY_ID` 和 `ALICLOUD_ACCESS_KEY_SECRET`。OpenSandbox 的连接地址是 `osb config set connection.domain`,对应环境变量 `OPEN_SANDBOX_DOMAIN`。 diff --git a/docs/zh/guide/comparison.md b/docs/zh/guide/comparison.md index 9700b405..fb249e66 100644 --- a/docs/zh/guide/comparison.md +++ b/docs/zh/guide/comparison.md @@ -1,234 +1,66 @@ -# 与其他沙箱工具的对比 +# SDK 入口对照 -当前 SDK 安装使用[配套源码安装指南](install-python.md)。 +根据代码实际使用的 API 选择入口。下列入口共用本项目的配置 +`ABX_SANDBOX_API_KEY`、`ABX_SANDBOX_BASE_URL`、`ABX_SANDBOX_DOMAIN`, +各自保留其方法签名和结果模型。 -> **说明:** 本页出现的 `abx` 命令由 `cli` 仓库中的 Node.js CLI 提供([CLI binary installation](https://github.com/Alibaba-Agent-Sandbox/agent-sandbox/blob/main/docs/en/guide/binary-installation.md))。CLI 专属文档(CLI 设计、教程、参考)也在该仓库;本仓库记录 Python SDK(`agent-sandbox-client`)与容器侧运行时(`agent-sandbox-server`)。 +| 入口 | 用途 | 前提 | +|---|---|---| +| `from agent_sandbox import Sandbox` | 标准同步生命周期、命令和文件 API | 阿里云支持的固定标准契约;极速版账号 | +| `from agent_sandbox import AsyncSandbox` | 在异步代码中使用同样的标准操作 | 对异步方法使用 await | +| `from agent_sandbox.code_interpreter import Sandbox, AsyncSandbox` | 标准解释器结果和上下文 | 使用 `code-interpreter-v1` 等包含解释器的模板 | +| `from agent_sandbox import ProviderSandbox` | 显式提供方扩展、会话和应用客户端 | 所选提供方实现了请求的操作 | +| `from agent_sandbox.declarative import sandbox` | 将 Python 函数放到远程执行 | 模板包含所需 Python 环境及依赖 | +| `from agent_sandbox.server import command, start` | 在镜像内注册并提供应用命令 | 镜像内安装同版本服务端运行时 | -本文档客观对比 Agent Sandbox (abx) 与其他主流沙箱及远程执行平台:E2B、Modal、Docker Sandbox。 +安装[已发布的 Python 包](install-python.md)。Python 包不包含独立的 +[abx CLI](https://github.com/Alibaba-Agent-Sandbox/agent-sandbox)。 ---- - -## 定位与场景 - -| 平台 | 核心定位 | 主要使用场景 | -|------|---------|-------------| -| **Agent Sandbox (abx)** | 可切换提供方的沙箱 SDK。默认提供方是阿里云极速版(FC);还可以安装其他提供方 | AI Agent 代码执行、云端或本地开发环境、模板驱动沙箱 | -| **E2B** | 为 AI 应用构建的云沙箱 | AI Agent 工具调用、代码解释器、LLM 工作流中的数据分析 | -| **Modal** | 面向数据/ML 流水线的 Serverless 计算 | GPU 工作负载、批处理、模型推理、定时任务 | -| **Docker Sandbox** | 基于容器的本地/远程隔离 | 本地开发、CI/CD、可复现环境 | - ---- - -## SDK 对比 - -| 维度 | Agent Sandbox | E2B | Modal | -|------|-------------|-----|-------| -| **语言** | Python | Python, JS/TS, Kotlin, Go | Python | -| **安装** | [配套源码安装指南](install-python.md) | `pip install e2b` | `pip install modal` | -| **沙箱创建** | `await Sandbox.create()`,或 Modal 风格的 `@sandbox` | `await Sandbox.create()` | `@app.function()` 装饰器 | -| **同步支持** | `Sandbox.create_sync()` | `Sandbox()`(同步类) | N/A(原生异步) | -| **命令执行** | `sandbox.commands.run()` | `sandbox.commands.run()` | 远程函数调用 | -| **文件操作** | `sandbox.files.read/write/list` | `sandbox.files.read/write/list` | `modal.Volume` 挂载 | -| **代码执行** | `sandbox.run_code()` | `sandbox.run_code()` | 远程函数执行 | -| **注册命令** | `sandbox.run(name, **kwargs)` | N/A | N/A | -| **网络访问** | `sandbox.network.get_host()` | `sandbox.get_host()` | 内置 URL 路由 | -| **终端 (PTY)** | `sandbox.get_terminal()` | `sandbox.terminal.start()` | `modal shell` | -| **E2B 迁移辅助** | `from agent_sandbox import Sandbox`(部分对应) | 原生 | N/A | -| **认证方式** | 随提供方变化。默认提供方用 `E2B_API_KEY`,阿里云极速版另用官方 AK/SK | API Key | Token | - -### 代码示例 - -**Agent Sandbox:** +## 标准解释器 ```python -from agent_sandbox.api.sandbox import Sandbox +from agent_sandbox.code_interpreter import Sandbox -async with await Sandbox.create(template="python-hello") as sb: - result = await sb.run_code("print('hello')") +with Sandbox.create(template="code-interpreter-v1") as sandbox: + result = sandbox.run_code("print(1 + 1)") + assert result.error is None print(result.text) ``` -**E2B:** - -```python -from e2b import Sandbox - -sandbox = Sandbox() -result = sandbox.run_code("print('hello')") -print(result.text) -sandbox.kill() -``` - -**Modal:** - -```python -import modal -app = modal.App("example") - -@app.function() -def hello(): - print("hello") -``` - -### 使用风格对比 - -Agent Sandbox 同时支持 **命令式**(E2B 风格)和 **声明式**(Modal 风格)两种编程范式: - -| 维度 | E2B 风格(命令式) | Modal 风格(声明式) | -|------|-------------------|---------------------| -| **创建** | 手动 `Sandbox.create()` | 自动(`@sandbox` 装饰器) | -| **依赖安装** | `sb.commands.run("pip install ...")` | 装饰器参数 `packages=[...]` | -| **数据传输** | `files.write()` + `files.read()` | 函数参数和返回值自动序列化 | -| **执行** | `sb.commands.run()` / `sb.run_code()` | 直接调用函数 | -| **结果获取** | 解析 stdout / 读取文件 | 函数返回值 | -| **生命周期** | 手动 `kill()` 或 `async with` | 自动管理 | -| **适用场景** | 细粒度控制、长时间交互、多步骤流程 | 简单计算任务、批处理、函数即服务 | - -**E2B 风格(命令式)— 细粒度控制:** - -```python -from agent_sandbox.api.sandbox import Sandbox - -async with await Sandbox.create() as sb: - await sb.commands.run("pip install pandas") - await sb.files.write("/app/data.csv", csv_content) - result = await sb.commands.run("python3 /app/analyze.py") - report = await sb.files.read("/app/report.txt") -``` - -**Modal 风格(声明式)— 像调本地函数:** - -```python -from agent_sandbox.declarative import sandbox - -@sandbox(packages=["pandas"]) -def analyze(data: list[dict]) -> dict: - import pandas as pd - df = pd.DataFrame(data) - return {"mean": df["value"].mean(), "count": len(df)} - -# 调用方式和本地函数一样,自动在远程沙箱中执行 -result = analyze(my_data) -``` - -> 完整示例参见 [`examples/compat-demos/comparison.py`](../../../examples/compat-demos/comparison.py) +迁移已有 E2B 应用请按[固定迁移契约](migrate-from-e2b.md)操作。替换导入不会消除 +后端权限、账号限制或运行时前提。第三方库仍使用其原生配置。 ---- - -## CLI 对比 - -| 维度 | abx | e2b CLI | modal CLI | -|------|-----|---------|-----------| -| **安装** | [CLI binary installation](https://github.com/Alibaba-Agent-Sandbox/agent-sandbox/blob/main/docs/en/guide/binary-installation.md) | `npm i -g @e2b/cli` | `pip install modal` | -| **运行时** | Node.js (TypeScript) | Node.js | Python (Typer) | -| **创建沙箱** | `abx create` | `e2b sandbox create` | N/A(代码驱动) | -| **列出沙箱** | `abx sandbox list` | `e2b sandbox list` | `modal container list` | -| **连接沙箱** | `abx connect ` | `e2b sandbox connect` | `modal shell` | -| **模板构建** | `abx template build` | `e2b template build` | N/A | -| **模板部署** | `abx template deploy` | `e2b template build --push` | N/A | -| **认证设置** | 通过环境变量(`.env`)| `e2b auth login` | `modal token set` | -| **MCP 集成** | `abx mcp install` | N/A | N/A | -| **密钥管理** | 通过环境变量(`.env`)| N/A | `modal secret create` | - ---- - -## 基础设施 - -| 维度 | Agent Sandbox | E2B | Modal | Docker Sandbox | -|------|-------------|-----|-------|----------------| -| **隔离技术** | 取决于提供方。默认是阿里云 FC 容器;`local-process` 等插件不提供隔离 | Firecracker MicroVM | 容器(gVisor) | 容器(runc/containerd) | -| **启动时间** | 秒级 | ~150ms(MicroVM) | 秒级(冷启动)/ 毫秒级(热启动) | 秒级 | -| **部署区域** | 默认提供方是阿里云区域(cn-hangzhou 等)。其他提供方用自己的区域 | 美国、欧洲 | 美国(aws-us-east-1 等) | 自托管 | -| **平台类型** | 默认提供方是阿里云托管。插件可以是本机或其他云 | 托管(E2B Cloud) | 托管(Modal Cloud) | 自托管 / Docker Desktop | -| **GPU 支持** | 通过模板配置 | N/A | 原生(A10G, A100, H100) | 通过 NVIDIA Container Toolkit | -| **最大生命周期** | 可配置(最长 86400 秒) | 可配置 | 按调用计 | 无限制 | -| **计费** | 阿里云 FC 计费 | 按沙箱秒计费 | 按秒计费 | 基础设施成本 | - ---- - -## Agent Sandbox 的独特能力 - -### E2B 风格的 API - -Agent Sandbox 使用 E2B 风格的方法名,E2B 代码通常只需少量改动即可迁移。标准接口遵循阿里云支持版本的行为契约;导入及后端限制见迁移指南。 +## Provider 命令和文件操作 ```python -# 迁移的起点:改导入,然后按指南逐项处理 -from agent_sandbox import Sandbox -``` - -完整迁移指南参见[从 E2B 迁移](migrate-from-e2b.md)。 - -### 阿里云集成 - -| 功能 | 说明 | -|------|------| -| **AK/SK 认证** | 原生阿里云 AccessKey 认证 | -| **模板构建与部署** | `abx template build` / `abx template deploy` 把镜像推送到阿里云容器镜像服务并注册模板 | - -VPC、OSS 卷、自定义域名是平台侧设置(模板运行时配置和账号级资源),Python SDK 没有对应的 API。 - -### 注册命令 - -注册在沙箱 server 里的函数(`@sandbox.register`,由容器内 Server SDK 实现)通过一个 API 调用: +from agent_sandbox import ProviderSandbox -```python -result = await sandbox.run("analyze", data="input.csv") -``` - -此能力在 E2B 和 Modal 中不可用。 - -### MCP Server 集成 - -Agent Sandbox 内置 MCP (Model Context Protocol) Server,使 AI IDE(Cursor、Claude Desktop、VS Code)可以直接操作沙箱: - -```bash -abx mcp install --target cursor +async with await ProviderSandbox.create(template="base") as sandbox: + result = await sandbox.commands.run("printf hello") + assert result.exit_code == 0 + await sandbox.files.write("/home/user/note.txt", result.stdout) + assert await sandbox.files.read("/home/user/note.txt") == "hello" ``` -提供 7 个工具:`create_sandbox`、`run_code`、`run_command`、`read_file`、`write_file`、`list_files`、`kill_sandbox`。 - -### 声明式沙箱装饰器 - -```python -from agent_sandbox import sandbox - -@sandbox(template="python-hello", timeout=60) -async def my_task(): - ... -``` - ---- - -## 其他平台(简要) - -| 平台 | 说明 | -|------|------| -| **Daytona** | 云开发环境平台。2026 年转为闭源,此前提供开源自托管方案。 | -| **Google Gemini Sandbox** | Google Cloud Gemini Enterprise Agent Platform(原 Vertex AI)中的代码执行沙箱。托管服务,与 Google Cloud 生态紧密耦合。 | -| **Cloudflare Workers** | 使用 V8 Isolates 进行进程内隔离,亚毫秒级冷启动。侧重边缘计算,非通用沙箱。 | -| **Fly.io Machines** | 基于 Firecracker 的临时 VM,支持完整 Linux 环境和快速启动。API 驱动,无专用沙箱 SDK。 | - ---- +这里在极速版 `base` 上使用命令和文件操作,不是解释器 API,也不会启动应用服务。 +极速版 ProviderSandbox 适配器未实现解释器操作,应通过上面的标准解释器入口调用。 +其他提供方的操作声明、账号实际可用性和云端验证是不同的内容,见[提供方指南](providers.md)。 -## 总结 +## 模板应用 -| 考量因素 | 推荐平台 | -|---------|---------| -| 从 E2B 迁移到阿里云 | **Agent Sandbox**——E2B 风格的方法名,代码改动较少(不是直接替代) | -| AI Agent 代码执行需求 | **Agent Sandbox** 或 **E2B**——专为沙箱构建的 SDK | -| GPU 密集型 ML/推理工作负载 | **Modal**——原生 GPU 支持和 Serverless 弹性 | -| 本地开发隔离 | **Docker**——行业标准,自托管 | -| 阿里云生态集成 | **Agent Sandbox**——AK/SK 认证、模板构建并部署到 ACR | -| 基于 MCP 的 AI IDE 集成 | **Agent Sandbox**——内置 MCP Server | +使用 `abx template launch ` 准备并启动完整模板。高级 `template build` / +`template deploy` 可单独准备镜像。启动后通过 +`await sandbox.application_client(9000, token=application_token)` 绑定应用客户端, +再调用 `client.commands.run("hello", name="Python")`。前提是运行中的模板注册了 hello, +普通 `base` 不包含该服务。见 [Express 快速开始](express-quickstart.md)和 +[模板启动](template-workflows.md)。 ---- +应用令牌与平台凭据分开使用。提供方负责网关解析,保留所需请求头及 URL 前缀。 +借用的客户端只关闭连接;仅删除自己拥有的沙箱和构建资源。 -## 延伸阅读 +## 验证范围 -- [命令与 SDK 对照](command-map.md) -- [从 E2B 迁移](migrate-from-e2b.md) -- [SDK 使用指南](sdk-usage.md) -- [CLI 教程](https://github.com/alibaba-agent-sandbox/agent-sandbox/blob/main/docs/zh/guide/cli-tutorial.md) -- [MCP 集成](mcp-integration.md) -- [认证详解](authentication.md) +接口签名一致或提供方声明支持,并不等于已经通过真实云测试。 +[云端示例](cloud-examples.md)提供可复现脚本及前提。每条验证记录只覆盖其实际账号、 +模板、提供方及调用路径。本文不做跨平台启动耗时、GPU、最长寿命或价格对比; +这些取决于平台和账号条件,不能通过 API 对照得出。 diff --git a/docs/zh/guide/declarative-usage.md b/docs/zh/guide/declarative-usage.md index b77bac76..2d944b36 100644 --- a/docs/zh/guide/declarative-usage.md +++ b/docs/zh/guide/declarative-usage.md @@ -33,9 +33,9 @@ print(result) serializer="json", # 序列化方式(默认 "json") sandbox_id=None, # 复用已有沙箱 ID(不为 None 时跳过创建) keep_alive=False, # True 时执行后不销毁沙箱 - api_key=None, # API Key 覆盖 - api_url=None, # 平台 API URL 覆盖 - domain=None, # 域名覆盖 + sandbox_api_key=None, # API Key 覆盖 + sandbox_base_url=None, # 平台 API URL 覆盖 + sandbox_domain=None, # 域名覆盖 cpu=None, # CPU 核数 memory=None, # 内存 MB ) @@ -54,9 +54,9 @@ def my_func(): | `serializer` | `str` | `"json"` | 序列化模式(仅支持 `json`) | | `sandbox_id` | `str` | `None` | 复用已有沙箱 ID | | `keep_alive` | `bool` | `False` | 执行后不销毁沙箱 | -| `api_key` | `str` | `None` | API Key 覆盖 | -| `api_url` | `str` | `None` | 平台 URL 覆盖 | -| `domain` | `str` | `None` | 平台域名 | +| `sandbox_api_key` | `str` | `None` | API Key 覆盖 | +| `sandbox_base_url` | `str` | `None` | 平台 URL 覆盖 | +| `sandbox_domain` | `str` | `None` | 平台域名 | | `cpu` | `int` | `None` | CPU 核数 | | `memory` | `int` | `None` | 内存 MB | diff --git a/docs/zh/guide/environment-variables.md b/docs/zh/guide/environment-variables.md index b9f18774..7d9117fa 100644 --- a/docs/zh/guide/environment-variables.md +++ b/docs/zh/guide/environment-variables.md @@ -2,7 +2,7 @@ 本指南描述异步 `ProviderSandbox` 扩展;根级 `Sandbox` 和 `AsyncSandbox` 遵循固定版本的标准迁移契约,详见[从 E2B 迁移](migrate-from-e2b.md)。 -当前 SDK 安装使用[配套源码安装指南](install-python.md)。 +当前 SDK 安装使用[安装指南](install-python.md)。 > **说明:** 本页出现的 `abx` 命令由 `cli` 仓库中的 Node.js CLI 提供([CLI binary installation](https://github.com/Alibaba-Agent-Sandbox/agent-sandbox/blob/main/docs/en/guide/binary-installation.md))。CLI 专属文档(CLI 设计、教程、参考)也在该仓库;本仓库记录 Python SDK(`agent-sandbox-client`)与容器侧运行时(`agent-sandbox-server`)。 diff --git a/docs/zh/guide/express-quickstart.md b/docs/zh/guide/express-quickstart.md index da2e84bd..80666d90 100644 --- a/docs/zh/guide/express-quickstart.md +++ b/docs/zh/guide/express-quickstart.md @@ -1,62 +1,49 @@ # Express 快速开始 -2026-10-15 在阿里云 Express(`alicloud-express`)上用 `agent-sandbox-client` 0.3.0 验证。模板是 generation 2,启动命令运行 `agent-sandbox-server`。 +安装[当前 Python 双包](install-python.md)和独立的 +[abx CLI](https://github.com/Alibaba-Agent-Sandbox/agent-sandbox/blob/main/docs/zh/guide/binary-installation.md)。 +按 CLI 的[模板启动指南](https://github.com/Alibaba-Agent-Sandbox/agent-sandbox/blob/main/docs/zh/guide/using-templates.md) +配置极速版提供方;源码构建还需文档要求的 Docker 和镜像仓库配置。 -## 部署 +## 启动应用 ```bash -abx template scaffold --template python --name hello-x -cd hello-x -abx template deploy . -y --generation 2 \ - --start-cmd 'agent-sandbox-server serve --port 9000 --commands /home/user/app/commands.py' \ - --ready-cmd 'agent-sandbox-server healthcheck --port 9000' +export ABX_SERVER_TOKEN='replace_me' +abx --provider alicloud-express template launch 'alibaba-agent-sandbox/awesome-templates//python-hello' ``` -python 脚手架注册了 `hello(name="World")`,返回 `Hello, {name}!`。从部署输出里复制模板 id。 +启动器准备提供方引用、创建沙箱、执行模板启动命令并检查声明的服务,不需要选择 +workflow。保留返回的沙箱 ID 和清理说明。 -`--start-cmd` 和 `--ready-cmd` 需要 `--generation 2`。如果已有同名的 generation-1 模板,先删掉(`abx template delete -y`)。如果部署报 `base must be a mapping`,把 `template.yaml` 改成: +## 从 Python 调用 -```yaml -base: - image: "fc-e2b-registry.cn-hangzhou.cr.aliyuncs.com/runtime/base:v0.0.49" -``` - -把地域和当前运行时基础镜像标签换成你自己的。 - -## 调用 +将返回的标识写入 `SANDBOX_ID`,并保持相同的 `ABX_SERVER_TOKEN`。 +`ABX_SANDBOX_API_KEY` 配置平台访问,与应用令牌分开。 ```python import asyncio +import os -from agent_sandbox import ProviderSandbox as Sandbox +from agent_sandbox import ProviderSandbox -TEMPLATE = "" - -async def main() -> None: - sb = await Sandbox.create(template=TEMPLATE, timeout=300) +async def main(): + sandbox = await ProviderSandbox.connect( + os.environ["SANDBOX_ID"], provider="alicloud-express" + ) try: - echoed = await sb.commands.run("echo hi") - assert echoed.stdout == "hi\n" and echoed.exit_code == 0 - assert await sb.run("hello", name="Bob") == "Hello, Bob!" - url = sb.network.get_url(9000) - headers = sb.network.get_access_headers() - # 用 headers 对 {url}/health 发 GET。/health 返回 200。 + async with await sandbox.application_client( + 9000, token=os.environ["ABX_SERVER_TOKEN"] + ) as client: + result = await client.commands.run("hello", name="Python") + print(result) finally: - await sb.kill() + await sandbox.close() asyncio.run(main()) ``` -`sandbox.run` 不发送沙箱访问令牌。`get_access_headers()` 是给平台网关的 `X-Access-Token`。 - -Generation 1 仍然支持 `commands.run` 和 `files`(同一天在平台模板 `base`、envd 0.5.2 上验证)。镜像入口点是固定的,所以 generation-1 模板不能自己启动 `agent-sandbox-server`。命名命令需要上面的 generation-2 启动命令和就绪命令。 - -## 清理 - -`sb.kill()` 会删掉沙箱。用完后删除模板: - -```bash -abx template delete -y -``` +这段代码借用 CLI 创建的沙箱并关闭连接。使用完毕后,按启动器的清理说明删除沙箱 +及自己创建的构建资源。等价的 Python 预备引用启动方式及生命周期归属见 +[模板启动指南](template-workflows.md)。 diff --git a/docs/zh/guide/getting-started.md b/docs/zh/guide/getting-started.md index aff0cc5c..5aa6c059 100644 --- a/docs/zh/guide/getting-started.md +++ b/docs/zh/guide/getting-started.md @@ -1,224 +1,97 @@ -# 快速入门 +# 快速开始 -当前 SDK 安装使用[配套源码安装指南](install-python.md)。 +在自己的机器上安装 Client SDK,即可创建和使用沙箱。 +[Server SDK](server-sdk.md) 用于运行沙箱镜像内的应用。 +本文使用 Provider 扩展入口 `ProviderSandbox`。标准同步 `Sandbox` 和异步 +`AsyncSandbox` 入口见 [E2B 迁移指南](migrate-from-e2b.md)。 -这是 **Client SDK**:在你的机器上安装、创建并使用沙箱。要写进镜像、在沙箱里启动的服务见 [Server SDK](server-sdk.md)。 +## 1. 安装和配置 -本教程覆盖从安装到销毁的完整生命周期。 - ---- - -## 前置条件 - -- Python 3.10 或更高版本 -- 默认提供方是 `alicloud-express`。API Key 从[智能体沙箱产品文档](https://help.aliyun.com/zh/functioncompute/product-overview-of-fc-agent-sandbox)获取。变量名是 `E2B_API_KEY`。标准 SDK 读取 `E2B_API_KEY`、`E2B_API_URL`、`E2B_DOMAIN`。 -- 网络可访问阿里云杭州区域(默认 `cn-hangzhou`) - -## 1. 安装 - -```bash -# 安装 SDK -python -m pip install \ - "agent-sandbox-server @ https://github.com/Alibaba-Agent-Sandbox/python-sdk/archive/3aa5e5ae6bd9c843f62c6689e549437f460b382d.tar.gz#subdirectory=server-sdk" \ - "agent-sandbox-client @ https://github.com/Alibaba-Agent-Sandbox/python-sdk/archive/3aa5e5ae6bd9c843f62c6689e549437f460b382d.tar.gz#subdirectory=client-sdk" - -# 安装全部额外依赖(推荐) -python -m pip install \ - "agent-sandbox-server @ https://github.com/Alibaba-Agent-Sandbox/python-sdk/archive/3aa5e5ae6bd9c843f62c6689e549437f460b382d.tar.gz#subdirectory=server-sdk" \ - "agent-sandbox-client[all] @ https://github.com/Alibaba-Agent-Sandbox/python-sdk/archive/3aa5e5ae6bd9c843f62c6689e549437f460b382d.tar.gz#subdirectory=client-sdk" -``` - -不要执行 `pip install agent-sandbox`。PyPI 上的 `agent-sandbox` 是另一个无关项目。 - -`abx` CLI 不属于 Python 包(没有 `[cli]` extra),它是独立的 Node.js 项目,见[相关:abx CLI](#相关abx-cli)。容器侧运行时(`agent_sandbox.server`)是独立的 -`agent-sandbox-server` 包([配套源码安装指南](install-python.md));`agent-sandbox-client` 依赖它,安装客户端时会一并安装。 - -### 从源码检出目录开发 - -在仓库根目录激活虚拟环境后,安装两个本地分发包及开发工具: +使用 Python 3.10 及以上版本,先按[安装指南](install-python.md)创建并激活虚拟环境,再安装: ```bash -uv pip install -e ./server-sdk -e "./client-sdk[dev]" +python -m pip install --index-url https://pypi.org/simple 'agent-sandbox-client==0.4.0a2' +python -m pip check +export ABX_SANDBOX_API_KEY='your-api-key' ``` -根目录的 uv workspace 会将客户端的运行时依赖解析为 `server-sdk/`,无需 -`--no-sources` 临时绕过。普通 `pip install` 也接受相同的 editable 参数; -发布包仍保留服务端同版本的精确依赖。 +按[智能体沙箱产品文档](https://help.aliyun.com/zh/functioncompute/product-overview-of-fc-agent-sandbox) +获取极速版沙箱 API Key。默认提供方为 `alicloud-express`,地域为 `cn-hangzhou`。 +本项目各入口,包括标准 `Sandbox` / `AsyncSandbox` 和 `ProviderSandbox`, +均支持 `ABX_SANDBOX_API_KEY`、`ABX_SANDBOX_BASE_URL` 和 `ABX_SANDBOX_DOMAIN`, +项目配置统一推荐这些名称。Provider 扩展的 `sandbox_api_key=` 覆盖见 +[认证指南](authentication.md);标准入口保留其文档中的公开 `api_key=` 参数。 -## 2. 配置 API Key +安装客户端会安装同版本的服务端发行包,但不会更新已有镜像内的服务端。 +PyPI 上名为 `agent-sandbox` 的发行包是其他项目。可选依赖及源码开发安装见 +[安装指南](install-python.md)。 -有三种方式配置认证凭证。真正生效时按下面的优先级(从高到低)。完整的凭证表见 [配置参考 — 凭证解析](../reference/configuration.md#凭证解析)。 +## 2. 创建沙箱、执行命令和传输文件 -### 方式一:代码参数(只影响这一次调用) - -```python -from agent_sandbox.api.sandbox import Sandbox - -sandbox = await Sandbox.create(sandbox_api_key="your-api-key-here") -``` - -### 方式二:环境变量(推荐用于 CI/CD) - -```bash -export E2B_API_KEY="your-api-key-here" -``` - -### 选项 3:持久化文件(`~/.abx/.env`) - -环境变量和项目 `.env` 都没写这个键时,才用这里保存的值。该文件由 `abx` CLI 写入(`abx config set sandbox_api_key your-api-key`,权限 600;见[相关:abx CLI](#相关abx-cli)),也可以手工编辑:`E2B_API_KEY=your-api-key`。 - -## 3. 创建第一个 Sandbox - -### 使用 SDK(异步) +保存为 `quickstart.py`,然后执行 `python quickstart.py`: ```python import asyncio -from agent_sandbox.api.sandbox import Sandbox -async def main(): - # 创建沙箱(默认模板: base,超时: 300 秒) - sandbox = await Sandbox.create(template="base", timeout=300) - print(f"Sandbox 已创建: {sandbox.id}") - print(f"状态: {sandbox.status.value}") - -asyncio.run(main()) -``` +from agent_sandbox import ProviderSandbox -`base` 是默认模板(`Sandbox.create()` 不传 template 时就是它)。仓库 README 使用 `python-base`,因为那张镜像注册了 README 里的 `hello` 命令。 -### 使用 SDK(同步) - -```python -from agent_sandbox.api.sandbox import Sandbox - -sandbox = Sandbox.create_sync(template="base") -print(f"Sandbox ID: {sandbox.id}") -``` - -## 4. 执行代码 - -### SDK - -```python -result = await sandbox.run_code("print('Hello, Agent Sandbox!')") -print(result.text) # "Hello, Agent Sandbox!" -print(result.stdout) # "Hello, Agent Sandbox!\n" -print(result.exit_code) # 0 -``` - -## 5. 运行 Shell 命令 - -### SDK - -```python -result = await sandbox.commands.run("ls -la /home/user") -print(result.stdout) -print(f"退出码: {result.exit_code}") -``` - -在 Express 的 `ProviderSandbox` 上,`commands.run`、`start` 和 `stream` -接受 `user="root"` 或其他已存在的操作系统账号。从 0.3.1a2 开始,原生 envd -适配器会为当前请求选择该账号: - -```python -result = await sandbox.commands.run("id -u", user="root") -assert result.exit_code == 0 and result.stdout.strip() == "0" -``` - -省略 `user` 或传入 `""` 会保留提供方默认账号;显式选择不会影响后续或并发请求。 -账号不存在时抛出 envd 错误,不会悄悄改用默认账号。账号名不允许冒号、NUL 或换行。 -这个参数选择进程的操作系统身份,不是应用服务 token,也不增加提供方权限。 -早期原生客户端(包括 0.3.1a1 和历史固定源码方案)会忽略该参数;标准 -`AsyncSandbox` 入口此前已支持它。 - -## 6. 文件操作 - -### 上传文件到沙箱 - -```python -# 写入文本文件 -await sandbox.files.write("/home/user/hello.py", "print('hello world')") - -# 上传本地文件 -await sandbox.files.upload("./local_script.py", "/home/user/script.py") -``` +async def main(): + async with await ProviderSandbox.create(template="base", timeout=300) as sandbox: + print(f"Sandbox ID: {sandbox.id}") + result = await sandbox.commands.run("printf 'Hello, Agent Sandbox!'") + assert result.exit_code == 0 + print(result.stdout) -### 从沙箱下载文件 + path = "/home/user/note.txt" + await sandbox.files.write(path, "Hello from Python!") + assert await sandbox.files.read(path) == "Hello from Python!" + await sandbox.files.download(path, "note.txt") + await sandbox.files.upload("note.txt", "/home/user/copied-note.txt") + assert await sandbox.files.read("/home/user/copied-note.txt") == "Hello from Python!" -```python -# 读取文本 -content = await sandbox.files.read("/home/user/hello.py") -print(content) + # 退出上下文时销毁自己创建的沙箱,出现异常也会清理。 -# 下载到本地 -await sandbox.files.download("/home/user/output.csv", "./output.csv") -``` -## 7. 列出目录内容 - -```python -files = await sandbox.files.list("/home/user") -for f in files: - print(f"{f.name} ({f.type.value}, {f.size} bytes)") +asyncio.run(main()) ``` -## 8. 销毁 Sandbox +`base` 提供命令和文件操作,不代表包含解释器或应用服务。原生命令可传入 +`user="root"` 或其他已存在的系统账号,仅影响当前请求。 -### SDK +连接已有沙箱使用 `await ProviderSandbox.connect(sandbox_id)`。使用完调用 +`await sandbox.close()` 释放客户端连接;仅在自己拥有沙箱生命周期时调用 +`await sandbox.kill()` 删除实例。 -```python -await sandbox.kill() -``` +## 3. 运行 Python 程序 -### 使用 Context Manager(推荐) +在 `base` 上运行 Python 程序可直接使用命令执行: ```python -async with await Sandbox.create(template="base") as sandbox: - result = await sandbox.run_code("print('auto cleanup')") - print(result.text) -# 退出 with 块后自动销毁 +result = await sandbox.commands.run("python3 -c 'print(1 + 1)'") +assert result.exit_code == 0 and result.stdout.strip() == "2" ``` -## 9. 完整示例 +将这段代码放进第 2 步的上下文中。这是进程执行,不是解释器 API。极速版的结构化 +解释器结果应通过标准 `agent_sandbox.code_interpreter` 入口获取,见 +[E2B 迁移指南](migrate-from-e2b.md);极速版 `ProviderSandbox` 适配器未实现解释器操作。 -```python -import asyncio -from agent_sandbox.api.sandbox import Sandbox - -async def main(): - async with await Sandbox.create(template="base") as sandbox: - # 安装依赖 - await sandbox.commands.run("pip install requests") - - # 执行代码 - result = await sandbox.run_code(""" -import requests -resp = requests.get('https://httpbin.org/get') -print(resp.status_code) -""") - print(f"状态码: {result.text}") - - # 写入和读取文件 - await sandbox.files.write("/home/user/note.txt", "Hello!") - content = await sandbox.files.read("/home/user/note.txt") - print(f"文件内容: {content}") - -asyncio.run(main()) -``` +## 4. 启动模板应用 ---- - -沙箱服务端也可以托管编程代理 CLI。目前支持 Codex(`codex`,npm 包 `@openai/codex`)和 Qwen Code(`qwen`,npm 包 `@qwen-code/qwen-code`)。路径是 `/v1/agents/sessions`,需要 `ABX_SERVER_ENABLED_GROUPS` 包含 `agents`。见[托管代理](hosted-agents.md)。 +使用独立安装的 [abx CLI](https://github.com/Alibaba-Agent-Sandbox/agent-sandbox) +启动目录中的模板,执行模板声明的启动与就绪检查。如何调用应用 API 和清理自己 +创建的资源见[模板启动指南](template-workflows.md)。创建普通 `base` 沙箱不会自动 +启动模板应用。 ## 下一步 -- [认证详解](authentication.md) — 多种认证方式与配置优先级 -- [SDK 使用指南](sdk-usage.md) — 完整的 API 使用方法 -- [错误码参考](../reference/error-codes.md) — 错误排查 -- [故障排查](troubleshooting.md) — 常见问题与解决方案 - ---- +- [SDK 用法](sdk-usage.md):Provider 扩展及其同步封装。 +- [声明式函数](declarative-usage.md):将 Python 函数放到远程执行。 +- [MCP 集成](mcp-integration.md):连接 IDE 或 Agent。 +- [故障排查](troubleshooting.md):处理安装和运行错误。 ## 相关:abx CLI -上述步骤对应的命令行用法(用 npm 或独立二进制安装 `abx`、`abx config set`、`abx create`、`abx exec`、`abx upload` / `download`、`abx kill`)见 CLI 仓库:[快速开始(CLI)](https://github.com/alibaba-agent-sandbox/agent-sandbox/blob/main/docs/zh/guide/getting-started.md)、[二进制安装](https://github.com/alibaba-agent-sandbox/agent-sandbox/blob/main/docs/zh/guide/binary-installation.md)、[CLI 教程](https://github.com/alibaba-agent-sandbox/agent-sandbox/blob/main/docs/zh/guide/cli-tutorial.md)与[模板使用](https://github.com/alibaba-agent-sandbox/agent-sandbox/blob/main/docs/zh/guide/using-templates.md)。 +CLI 是独立的 Node.js 包 `@agent-sandbox/cli`。安装 Python 包不会安装 `abx`, +也不存在 Python `[cli]` extra。请按 +[CLI 安装指南](https://github.com/Alibaba-Agent-Sandbox/agent-sandbox/blob/main/docs/zh/guide/binary-installation.md)操作。 diff --git a/docs/zh/guide/install-python.md b/docs/zh/guide/install-python.md index e1d82336..19dd9929 100644 --- a/docs/zh/guide/install-python.md +++ b/docs/zh/guide/install-python.md @@ -1,6 +1,6 @@ # 安装 Python 配套包 -> 规范 5 的模板启动需要本指南使用的配套 alpha 包:`agent-sandbox-client==0.4.0a1` 和 `agent-sandbox-server==0.4.0a1`。旧 0.3.x 包不实现此入口。验证源码修订时,请按下文从同一份检出同时安装两个发行包。 +> 规范 5 的模板启动需要本指南使用的配套 alpha 包:`agent-sandbox-client==0.4.0a2` 和 `agent-sandbox-server==0.4.0a2`。旧 0.3.x 包不实现此入口。验证源码修订时,请按下文从同一份检出同时安装两个发行包。 使用 Python 3.10 或更高版本及虚拟环境: @@ -9,7 +9,7 @@ python -m venv .venv # Linux 或 macOS: source .venv/bin/activate # Windows PowerShell:.venv\Scripts\Activate.ps1 -python -m pip install --index-url https://pypi.org/simple 'agent-sandbox-client==0.4.0a1' +python -m pip install --index-url https://pypi.org/simple 'agent-sandbox-client==0.4.0a2' python -m pip check ``` @@ -23,18 +23,22 @@ python -c "from importlib.metadata import version; print(version('agent-sandbox- [abx CLI](https://github.com/Alibaba-Agent-Sandbox/agent-sandbox) 需要独立安装。本指南中的模板启动使用 CLI 0.5.0 或更高版本;创建沙箱前先配置所选平台。 +本项目配置统一使用 `ABX_SANDBOX_API_KEY`、`ABX_SANDBOX_BASE_URL` 和 +`ABX_SANDBOX_DOMAIN`,标准 Sandbox / AsyncSandbox 与 ProviderSandbox 均支持。 +公开关键字参数仍遵循各入口的文档契约;标准入口的 `api_key=` 仍然有效。 + ## 可选依赖 ```bash -python -m pip install 'agent-sandbox-client[all]==0.4.0a1' +python -m pip install --index-url https://pypi.org/simple 'agent-sandbox-client[all]==0.4.0a2' ``` -可把 `[all]` 换成 `[mcp]`、`[session]` 或 `[fast]`。工作流 YAML 和声明式装饰器属于基础客户端,无需 extra。浏览器自动化需要在沙箱镜像内安装 Playwright。 +可把 `[all]` 换成 `[mcp]`、`[session]` 或 `[fast]`。模板 YAML 和声明式装饰器属于基础客户端,无需 extra。浏览器自动化需要在沙箱镜像内安装 Playwright。 ## 镜像内只安装服务端 ```bash -python -m pip install 'agent-sandbox-server==0.4.0a1' +python -m pip install --index-url https://pypi.org/simple 'agent-sandbox-server==0.4.0a2' ``` 服务端负责在镜像内运行应用,安装它不会创建沙箱。注册命令与启动服务见[服务端指南](server-sdk.md)。 diff --git a/docs/zh/guide/mcp-integration.md b/docs/zh/guide/mcp-integration.md index e43096f2..d1cc6742 100644 --- a/docs/zh/guide/mcp-integration.md +++ b/docs/zh/guide/mcp-integration.md @@ -13,8 +13,8 @@ MCP(Model Context Protocol)是一个开放协议,允许 AI 模型与外部 ### 环境要求 ```bash -pip install agent-sandbox-client # SDK 自带的 MCP STDIO server:python -m agent_sandbox.agent.mcp -export E2B_API_KEY=your-api-key +pip install --index-url https://pypi.org/simple "agent-sandbox-client==0.4.0a2" # SDK 自带的 MCP STDIO server:python -m agent_sandbox.agent.mcp +export ABX_SANDBOX_API_KEY=your-api-key ``` Node.js `abx` CLI 提供同一服务器的另一套实现(`abx mcp ...`,用 `npm install -g @agent-sandbox/cli` 安装);见[相关:abx CLI](#相关abx-cli)。 @@ -29,13 +29,13 @@ Node.js `abx` CLI 提供同一服务器的另一套实现(`abx mcp ...`,用 "agent-sandbox": { "command": "python", "args": ["-m", "agent_sandbox.agent.mcp"], - "env": { "E2B_API_KEY": "your-api-key" } + "env": { "ABX_SANDBOX_API_KEY": "your-api-key" } } } } ``` -`python -m agent_sandbox.agent.mcp` 读取 `E2B_API_KEY`、`E2B_API_URL`、`E2B_DOMAIN`,默认模板取自 `ABX_DEFAULT_TEMPLATE`(默认 `base`)。修改 IDE 配置后重启 IDE。该 server 通过 STDIO 提供同一组工具,因此下文的[可用工具](#可用工具)完全适用。 +`python -m agent_sandbox.agent.mcp` 读取 `ABX_SANDBOX_API_KEY`、`ABX_SANDBOX_BASE_URL`、`ABX_SANDBOX_DOMAIN`,默认模板取自 `ABX_DEFAULT_TEMPLATE`(默认 `base`)。修改 IDE 配置后重启 IDE。该 server 通过 STDIO 提供同一组工具,因此下文的[可用工具](#可用工具)完全适用。 `abx mcp install --target cursor|claude|vscode` 与 `abx mcp status` 命令会替你写入并检查这些文件;见[相关:abx CLI](#相关abx-cli)。 @@ -96,10 +96,10 @@ printf '%s\n' \ ### 本地以 uvicorn 运行 ```bash -pip install "agent-sandbox-client[mcp]" +pip install --index-url https://pypi.org/simple "agent-sandbox-client[mcp]==0.4.0a2" export ABX_MCP_AUTH_TOKEN=replace_me # Bearer token(省略则关闭认证) -export E2B_API_KEY=your-api-key +export ABX_SANDBOX_API_KEY=your-api-key uvicorn agent_sandbox.agent.mcp_http:asgi_app --host 0.0.0.0 --port 9000 ``` @@ -113,7 +113,7 @@ from agent_sandbox.agent.mcp_http import create_mcp_app app = create_mcp_app( auth_token="replace_me", # None 关闭客户端认证 - api_key="your-api-key", + sandbox_api_key="your-api-key", template="base", ) ``` @@ -124,7 +124,7 @@ app = create_mcp_app( | 入口 | 客户端认证 | 如何配置 | |------|-----------|----------| -| `python -m agent_sandbox.agent.mcp`(STDIO) | 没有 Bearer。进程由本机 IDE 拉起,不对外监听 | 沙箱调用用 `E2B_API_KEY` | +| `python -m agent_sandbox.agent.mcp`(STDIO) | 没有 Bearer。进程由本机 IDE 拉起,不对外监听 | 沙箱调用用 `ABX_SANDBOX_API_KEY` | | `uvicorn agent_sandbox.agent.mcp_http:asgi_app` / `create_mcp_app()` | Bearer。回环地址可以不配 token(启动时会警告) | `ABX_MCP_AUTH_TOKEN` 或 `auth_token=` | | 阿里云 FC 上的远程函数 | Bearer 必填。产物里的 `app.py` 在 token 为空时拒绝启动,不会变成“免认证” | token 作为函数环境变量 `ABX_MCP_AUTH_TOKEN` 写入。FC HTTP 触发器使用 `anonymous`,MCP 客户端不需要阿里云签名;真正的校验是应用层 Bearer。`GET /health` 只返回状态与协议,不校验 token,也不含任何密钥 | @@ -166,7 +166,7 @@ token 比较使用常量时间算法。可用 `openssl rand -base64 32` 生成 | 文件 | 内容 | |------|------| | `requirements.txt` | `agent-sandbox-client[mcp]`、`uvicorn>=0.29` | -| `app.py` | ASGI 入口,读取 FC 环境变量(`ABX_MCP_AUTH_TOKEN`、`E2B_API_KEY`、`E2B_API_URL`、`E2B_DOMAIN`、`ABX_DEFAULT_TEMPLATE`) | +| `app.py` | ASGI 入口,读取 FC 环境变量(`ABX_MCP_AUTH_TOKEN`、`ABX_SANDBOX_API_KEY`、`ABX_SANDBOX_BASE_URL`、`ABX_SANDBOX_DOMAIN`、`ABX_DEFAULT_TEMPLATE`) | | `config.yaml` | YAML 清单:函数名、地域、运行时 `python3.10`、handler `app.app`、内存/超时、环境变量、HTTP 触发器(POST/GET/DELETE)、会话亲和 | 部署步骤:打包 → 创建函数 → 创建 HTTP 触发器 → 若支持则启用 `Mcp-Session-Id` 亲和。 @@ -246,8 +246,8 @@ curl -s -X DELETE http://localhost:9000/mcp \ | 症状 | 可能原因 | 解决方法 | |------|----------|----------| | IDE 显示 server 失败 / 无工具 | IDE `PATH` 中的 `python` 不是安装了 `agent-sandbox` 的解释器 | 在 IDE 配置的 `command` 中使用解释器的绝对路径 | -| 工具列表正常但每次调用报错 | API key 缺失或无效 | 在 server 的 `env` 块中设置 `E2B_API_KEY` | -| IDE 重启后 `create_sandbox` 失败 | 后端 API URL/地域不匹配 | 在 server 的 `env` 块中设置 `E2B_API_URL` | +| 工具列表正常但每次调用报错 | API key 缺失或无效 | 在 server 的 `env` 块中设置 `ABX_SANDBOX_API_KEY` | +| IDE 重启后 `create_sandbox` 失败 | 后端 API URL/地域不匹配 | 在 server 的 `env` 块中设置 `ABX_SANDBOX_BASE_URL` | | HTTP 每个请求都 401 | `ABX_MCP_AUTH_TOKEN` 为空(fail-closed) | 设置非空 token。本机回环可以删掉该变量来关闭认证。FC 产物没有 token 时不会启动 | | HTTP 404 Unknown session | `Mcp-Session-Id` 已过期(空闲 TTL 3600 秒)或实例重启 | 重新发送 `initialize` 创建新会话 | | HTTP 503 会话上限 | 进程内并发会话超过 100 | 关闭空闲会话(`DELETE /mcp`)或经 `create_mcp_app()` 调高 `max_sessions` | diff --git a/docs/zh/guide/migrate-from-e2b.md b/docs/zh/guide/migrate-from-e2b.md index 2fe85356..16344a06 100644 --- a/docs/zh/guide/migrate-from-e2b.md +++ b/docs/zh/guide/migrate-from-e2b.md @@ -4,7 +4,8 @@ ## 安装与导入 -新版本发布前,在当前检出目录执行 `pip install ./server-sdk ./client-sdk`。保留原有阿里云 `E2B_API_KEY`、`E2B_API_URL`、`E2B_DOMAIN` 配置,也可使用 `abx config` 与项目/用户配置文件。SDK 显式参数优先。不保留旧 `ABX_SANDBOX_*` 别名。 +使用已发布客户端:`python -m pip install --index-url https://pypi.org/simple agent-sandbox-client==0.4.0a2`。通过 `ABX_SANDBOX_API_KEY`、`ABX_SANDBOX_BASE_URL` 和 `ABX_SANDBOX_DOMAIN` 配置极速版账号;本项目标准 `Sandbox` / `AsyncSandbox`、`code_interpreter` 和 `ProviderSandbox` 均支持这些项目配置。也可使用 `abx config` 与项目/用户配置文件。标准客户端公开 `api_key=` 参数仍属于其固定契约。仍使用第三方 E2B SDK 的独立应用按该 SDK 的原生配置操作,不要混用不同提供商账号的凭据。 + | 原导入 | 新导入 | |---|---| diff --git a/docs/zh/guide/provider-commands.md b/docs/zh/guide/provider-commands.md index 79166927..36611c0a 100644 --- a/docs/zh/guide/provider-commands.md +++ b/docs/zh/guide/provider-commands.md @@ -37,15 +37,11 @@ Volume 目前要求提交阿里云工单申请邀测,准备存储前应确认 其他提供方的非空挂载参数会在加载插件实现前返回 E8004。省略参数或传空字典不改变原请求。 这是创建参数,与资源管理命令独立,不增加可移植的 `storage.mount` 协议或运行时追加挂载 API。 -Python 内置生命周期仍通过本地 gRPC 引擎:新增的 `CreateRequest.volume_mounts` 传递字典, -由现有 Python 协议序列化为 `POST /sandboxes` 的 +客户端先检查所选提供方的 `create_options`,再创建沙箱。内置提供方通过直接 HTTP 传输, +在 `POST /sandboxes` 中发送 `"volumeMounts": [{"name": "existing-volume-name", "path": "/mnt/data"}]`。 -非空参数会先检查 `Health.supported_create_options` 是否包含 `volume_mounts`;旧的运行中引擎 -会在 `Create` 前返回 E8004 和升级、重启提示,不会自动替换引擎,避免旧 protobuf 实现静默 -忽略挂载参数。未请求挂载的调用保留原行为。 -提供方管理命令继续使用共享 Node HTTP 引擎。本地 gRPC/HTTP 回归覆盖参数链路,且已在 -杭州地域的 base 模板完成真实 OSS 挂载、读写和清理验收。显式启用的 Volume E2E 套件还会检查 -销毁并重建沙箱后数据是否保留。 +提供方资源管理命令使用独立的共享 Node HTTP 引擎。显式启用的 Volume E2E 套件检查 +挂载、读写、清理及重建后的数据保留;实际可用性仍取决于上文的账号及镜像前提。 ## Python API diff --git a/docs/zh/guide/sdk-usage.md b/docs/zh/guide/sdk-usage.md index 9dc07de2..bbabef5d 100644 --- a/docs/zh/guide/sdk-usage.md +++ b/docs/zh/guide/sdk-usage.md @@ -7,7 +7,7 @@ ## 安装 -请按[安装指南](install-python.md)安装。公开客户端/服务端 alpha 版本为 0.4.0a1;安装客户端会安装匹配的服务端依赖。宿主机安装不会更新已有沙箱镜像。 +请按[安装指南](install-python.md)安装。公开客户端/服务端 alpha 版本为 0.4.0a2;安装客户端会安装匹配的服务端依赖。宿主机安装不会更新已有沙箱镜像。 不要执行 `pip install agent-sandbox`。PyPI 上的 `agent-sandbox` 是另一个无关项目。 @@ -23,42 +23,11 @@ from agent_sandbox import ProviderSandbox as Sandbox 下面的模板作者示例保留其明确部署前提。连接 CLI 返回的已有实例时,优先通过 `await sandbox.application_client(9000, token=application_token, timeout=330)` 获取应用客户端,再调用 `client.commands.run(...)`;见[模板工作流](template-workflows.md)。它保留 Provider 网关头、URL 前缀与签名查询参数。`close()` 只释放连接,`kill()` 删除实例;不要销毁借用的实例。HTTP 等待超时不保证取消远端执行,也不会自动重试命令。 -## 模板作者快速路径 +## 模板应用 -2026-10-15 在阿里云 Express(`alicloud-express`)上验证。模板是 generation 2,启动命令运行 `agent-sandbox-server`。`Sandbox.create(template=..., provider="alicloud-express")` 使用 `ABX_SANDBOX_API_KEY`、`ABX_SANDBOX_BASE_URL` 和 `ABX_SANDBOX_DOMAIN`。`template` 可以是模板 id 或名称。 - -```python -import asyncio - -from agent_sandbox import ProviderSandbox as Sandbox - -TEMPLATE = "hello-x" # generation-2 模板的名称或 id - - -async def main() -> None: - async with await Sandbox.create( - template=TEMPLATE, provider="alicloud-express", timeout=300 - ) as sb: - assert await sb.run("hello", name="Bob") == "Hello, Bob!" - echoed = await sb.commands.run("echo hi", on_stdout=lambda text: None) - assert echoed.stdout == "hi\n" and echoed.exit_code == 0 - await sb.files.write("/home/user/note.txt", "abc") - assert await sb.files.read("/home/user/note.txt") == "abc" - url = sb.network.get_url(9000) - headers = sb.network.get_access_headers() - # 用 headers 对 {url}/health 发 GET。/health 返回 200。 - - -asyncio.run(main()) -``` - -`sandbox.run` 是调用命名命令的那一次调用,返回函数的值。`timeout=`(秒)是 HTTP 时限,不会传给函数。Shell 输出通过 `commands.run` 的 `on_stdout` / `on_stderr` 流式输出。命名命令不会把自己的 print 流出来;函数返回时调用才结束。 - -名字不存在抛 `CommandNotFoundError`,消息里带有服务端列出的命令。参数错误抛 `CommandArgumentError`。命令函数抛出的异常是 `CommandExecutionError`(`error_type` 是异常类名)。上下文管理器会调用 `kill()`。 - -部署:`abx template deploy . -y --generation 2 --start-cmd 'agent-sandbox-server serve --port 9000 --commands /home/user/app/commands.py' --ready-cmd 'agent-sandbox-server healthcheck --port 9000'`。完整步骤见 [Express 快速开始](express-quickstart.md)。 - ---- +通过 `abx template launch ` 启动完整模板,再使用 `application_client` +携带应用令牌调用注册命令。源码镜像准备和平台配置由 CLI 负责。见 +[Express 快速开始](express-quickstart.md)和[模板启动](template-workflows.md)。 ## 创建与销毁 diff --git a/docs/zh/guide/server-sdk.md b/docs/zh/guide/server-sdk.md index 5cd691d9..c5914514 100644 --- a/docs/zh/guide/server-sdk.md +++ b/docs/zh/guide/server-sdk.md @@ -4,12 +4,12 @@ Server SDK 跑在**沙箱里面**。它是镜像启动后一直听着的 HTTP 服务,默认端口 9000。包名是 `agent-sandbox-server`,导入 `agent_sandbox.server`。模板的 `commands.py` 用它注册命令、打开能力,然后 `start(9000)`。 -下面显式选择已发布的 alpha 测试版,配套 client 版本同为 0.3.1a1。 +下面显式选择已发布的 alpha 测试版,配套 client 版本同为 0.4.0a2。 指定官方索引使示例不依赖本机配置的镜像源,不表示镜像源普遍不可用。 -固定源码安装请按上方安装指南操作。 +开发源码安装请按上方安装指南操作。 ```bash -python -m pip install --index-url https://pypi.org/simple "agent-sandbox-server==0.3.1a1" +python -m pip install --index-url https://pypi.org/simple "agent-sandbox-server==0.4.0a2" ``` ```python diff --git a/docs/zh/guide/template-server-api.md b/docs/zh/guide/template-server-api.md index e468d660..048da7e6 100644 --- a/docs/zh/guide/template-server-api.md +++ b/docs/zh/guide/template-server-api.md @@ -12,7 +12,7 @@ Dockerfile 里的 `FROM` 镜像随模板而变。本 HTTP API 不变。凡是启 服务器默认监听 `0.0.0.0:9000`。Provider 必须支持所需端口解析和访问路径,服务也必须实际监听;不能把所有入口都当作 `{port}-{sandbox_id}.{domain}` 主机名拼接。已有沙箱的应用调用独立于内部 envd/EPP 传输: -此示例使用已发布 `agent-sandbox-client==0.3.1a1` alpha 中的 Provider 原生 +此示例使用已发布 `agent-sandbox-client==0.4.0a2` alpha 中的 Provider 原生 `ProviderSandbox`,标准 `Sandbox`/`AsyncSandbox` 是另一套接口。精确安装版本与源码方案见 [安装指南](install-python.md)。将 `SANDBOX_ID` 设为应用服务已启动的现有沙箱;仅当服务 启动时配置了令牌,才设置对应的 `ABX_SERVER_TOKEN`。 diff --git a/docs/zh/guide/troubleshooting.md b/docs/zh/guide/troubleshooting.md index 9cdc01b4..214505e0 100644 --- a/docs/zh/guide/troubleshooting.md +++ b/docs/zh/guide/troubleshooting.md @@ -1,6 +1,6 @@ # 常见问题(FAQ) -当前 SDK 安装使用[配套源码安装指南](install-python.md)。 +当前 SDK 安装使用[安装指南](install-python.md)。 > **说明:** 本页出现的 `abx` 命令由 `cli` 仓库中的 Node.js CLI 提供([CLI binary installation](https://github.com/Alibaba-Agent-Sandbox/agent-sandbox/blob/main/docs/en/guide/binary-installation.md))。CLI 专属文档(CLI 设计、教程、参考)也在该仓库;本仓库记录 Python SDK(`agent-sandbox-client`)与容器侧运行时(`agent-sandbox-server`)。 @@ -42,7 +42,7 @@ ```text [E1001] API key cannot be empty - Suggestion: Check your E2B_API_KEY environment variable or pass sandbox_api_key. + Suggestion: Check your ABX_SANDBOX_API_KEY environment variable or pass sandbox_api_key. ``` **解决**: @@ -54,7 +54,7 @@ abx config get sandbox_api_key abx config set sandbox_api_key your-api-key # 或设置环境变量 -export E2B_API_KEY="your-api-key" +export ABX_SANDBOX_API_KEY="your-api-key" ``` ### E1003 — AK/SK 凭证无效 @@ -211,9 +211,7 @@ entries = await sandbox.files.list("/home/user") ```bash # 确保使用正确的包名 -python -m pip install \ - "agent-sandbox-server @ https://github.com/Alibaba-Agent-Sandbox/python-sdk/archive/3aa5e5ae6bd9c843f62c6689e549437f460b382d.tar.gz#subdirectory=server-sdk" \ - "agent-sandbox-client @ https://github.com/Alibaba-Agent-Sandbox/python-sdk/archive/3aa5e5ae6bd9c843f62c6689e549437f460b382d.tar.gz#subdirectory=client-sdk" +python -m pip install --index-url https://pypi.org/simple "agent-sandbox-client==0.4.0a2" # 如果遇到依赖冲突 python -m pip check diff --git a/docs/zh/reference/api-reference.md b/docs/zh/reference/api-reference.md index a875fa1c..78b6e8c0 100644 --- a/docs/zh/reference/api-reference.md +++ b/docs/zh/reference/api-reference.md @@ -1,13 +1,13 @@ # API 参考 -本文档列出 Agent Sandbox Python SDK 的全部公开 API 签名、参数、返回值和异常。 +本文介绍 ProviderSandbox 扩展 API。根入口 Sandbox / AsyncSandbox 使用独立标准契约,见 [E2B 迁移](../guide/migrate-from-e2b.md)。 --- ## Sandbox 类 ```python -from agent_sandbox.api.sandbox import Sandbox +from agent_sandbox import ProviderSandbox as Sandbox ``` ### 类方法 @@ -29,7 +29,7 @@ async def create( memory: int | None = None, disk: int | None = None, gpu: str | None = None, - secure: bool = True, + secure: bool | None = None, sandbox_api_key: str | None = None, sandbox_base_url: str | None = None, sandbox_domain: str | None = None, @@ -44,7 +44,7 @@ async def create( |------|------|--------|------| | `template` | `str` | `"base"` | 沙箱模板名称 | | `timeout` | `int` | `300` | 沙箱生存时长(TTL)秒数(1~86400);非 HTTP 请求超时 | -| `request_timeout` | `float` | `None` | 仅针对本次创建请求的 HTTP 超时(秒)。为 `None` 时使用 `SANDBOX_HTTP_TIMEOUT` / `http_timeout`。与 E2B SDK 对齐。调大它无法绕过平台侧创建挂起。 | +| `request_timeout` | `float` | `None` | 仅针对本次创建请求的 HTTP 超时(秒)。为 `None` 时使用 `ABX_HTTP_TIMEOUT` / `http_timeout`。与 E2B SDK 对齐。调大它无法绕过平台侧创建挂起。 | | `metadata` | `dict` | `None` | 任意元数据键值对 | | `envs` | `dict` | `None` | 注入的环境变量 | | `volume_mounts` | `dict[str, str]` | `None` | 仅内置提供方:规范化的沙箱绝对路径 → 已有 Volume 名称。省略或空字典不挂载,其他提供方的非空参数返回 E8004。见[挂载要求与请求 schema](../guide/provider-commands.md#创建沙箱时挂载已有-volume)。 | @@ -52,7 +52,7 @@ async def create( | `memory` | `int` | `None` | 内存 MB | | `disk` | `int` | `None` | 磁盘 MB | | `gpu` | `str` | `None` | GPU 规格(如 `"A10"`) | -| `secure` | `bool` | `True` | 安全模式(端口访问需 token) | +| `secure` | `bool` | `None` | 安全模式(端口访问需 token) | | `sandbox_api_key` | `str` | `None` | API Key 覆盖 | | `sandbox_base_url` | `str` | `None` | 平台 API URL 覆盖 | | `sandbox_domain` | `str` | `None` | 域名覆盖 | diff --git a/docs/zh/reference/configuration.md b/docs/zh/reference/configuration.md index fbe77569..495a55ae 100644 --- a/docs/zh/reference/configuration.md +++ b/docs/zh/reference/configuration.md @@ -205,7 +205,7 @@ explain_config() # {"sandbox_api_key": {"value": "****3dc1", "source": "enviro 在代码中直接传参(最高优先级): ```python -from agent_sandbox.api.sandbox import Sandbox +from agent_sandbox import ProviderSandbox as Sandbox sandbox = await Sandbox.create( sandbox_api_key="REPLACE_ME", diff --git a/examples/README.md b/examples/README.md index e89a9333..245849b2 100644 --- a/examples/README.md +++ b/examples/README.md @@ -14,10 +14,10 @@ Examples are split by which package they exercise. ```bash # Full install (recommended — includes the declarative decorator, MCP server, ...) -python -m pip install "agent-sandbox-client[all]==0.4.0a2" +python -m pip install --index-url https://pypi.org/simple "agent-sandbox-client[all]==0.4.0a2" # Or install selectively -python -m pip install "agent-sandbox-client==0.4.0a2" +python -m pip install --index-url https://pypi.org/simple "agent-sandbox-client==0.4.0a2" # From source (run from the python-sdk repository root) pip install -e ./server-sdk -e ./client-sdk @@ -79,8 +79,8 @@ discover and install them with `abx template search` / `abx template launch **Note:** `sandbox.run(name, **kwargs)` calls a command registered in the template's server; it never runs a shell string. Use `sandbox.commands.run(cmd)` for that. +This releases a borrowed connection; follow the launch cleanup instructions +to delete owned resources after use. A plain base sandbox has no hello server. ### File Operations ```python # Write and read files - await sandbox.files.write("/app/data.txt", "content") - content = await sandbox.files.read("/app/data.txt") + await sandbox.files.write("/home/user/data.txt", "content") + content = await sandbox.files.read("/home/user/data.txt") ``` ### Network @@ -165,7 +199,7 @@ async with await Sandbox.create(template="base", sandbox_api_key="...") as sandb ```python from agent_sandbox.declarative import sandbox -@sandbox(template="code-interpreter", packages=["numpy"]) +@sandbox(template="code-interpreter-v1", packages=["numpy"]) def compute(n: int) -> float: import numpy as np return float(np.random.random(n).mean()) @@ -179,4 +213,4 @@ Run `python examples/run_examples_e2e.py` for local real-server/file/process exa `agents/codex_agent.py` requires a real `OPENAI_API_KEY`; optional `OPENAI_BASE_URL` and `OPENAI_MODEL` select a compatible model. It does not substitute simulated responses. `agents/browser_automation.py` installs real Chromium and defaults to an owned HTTP page; set `BROWSER_URL` to exercise your external page. -`compat-demos/e2b_import_migration.py` uses the standard synchronous interpreter client and the E2B configuration names described in its docstring. The other cloud examples use `ProviderSandbox` or `@sandbox` and `ABX_SANDBOX_API_KEY`. See [cloud examples](../docs/en/guide/cloud-examples.md) for the complete commands. +`compat-demos/e2b_import_migration.py` uses the standard synchronous interpreter client. All project examples use the shared ABX sandbox configuration; the other cloud examples use `ProviderSandbox` or `@sandbox`. See [cloud examples](../docs/en/guide/cloud-examples.md) for the complete commands. diff --git a/examples/README.zh-CN.md b/examples/README.zh-CN.md index 6235004e..34a2c05b 100644 --- a/examples/README.zh-CN.md +++ b/examples/README.zh-CN.md @@ -14,10 +14,10 @@ ```bash # 完整安装(推荐,包含声明式装饰器、MCP 服务等) -python -m pip install "agent-sandbox-client[all]==0.4.0a2" +python -m pip install --index-url https://pypi.org/simple "agent-sandbox-client[all]==0.4.0a2" # 或按需安装 -python -m pip install "agent-sandbox-client==0.4.0a2" +python -m pip install --index-url https://pypi.org/simple "agent-sandbox-client==0.4.0a2" # 从源码安装(在 python-sdk 仓库根目录执行) pip install -e ./server-sdk -e ./client-sdk @@ -73,8 +73,8 @@ examples/ |------|------|----------| | [`01_hello.py`](quickstart/01_hello.py) | **基础沙箱操作** —— 创建、执行命令、生命周期管理 | SDK 入门 | | [`02_file_ops.py`](quickstart/02_file_ops.py) | **文件操作** —— 读写文件、目录管理、二进制文件 | 数据交换 | -| [`03_web_service.py`](quickstart/03_web_service.py) | **Web 服务** —— 启动 Express 服务、获取公网 URL | Web 开发、API 测试 | -| [`04_data_analysis.py`](quickstart/04_data_analysis.py) | **数据分析** —— 上传 CSV、pandas 分析、run_code | 数据科学 | +| [`03_web_service.py`](quickstart/03_web_service.py) | **Web 服务** —— 启动 Node.js 内置 HTTP 服务并调用公网 URL | Web 开发、API 测试 | +| [`04_data_analysis.py`](quickstart/04_data_analysis.py) | **数据分析** —— 上传 CSV、通过 Python 命令进行 pandas 分析 | 数据科学 | | [`05_decorator_usage.py`](quickstart/05_decorator_usage.py) | **@sandbox 装饰器** —— 声明式远程执行 | 简化调用 | ### agents/ —— Client SDK @@ -116,35 +116,67 @@ python examples/compat-demos/e2b_data_analysis.py ## 核心 API 速览 -### 执行方法 +### base 上的 Shell 执行 ```python -from agent_sandbox import ProviderSandbox as Sandbox +from agent_sandbox import ProviderSandbox -async with await Sandbox.create(template="base", sandbox_api_key="...") as sandbox: - - # 1. 裸 Shell —— sandbox.commands.run(cmd) +async with await ProviderSandbox.create(template="base") as sandbox: proc = await sandbox.commands.run("echo hello") print(proc.stdout, proc.exit_code) +``` + +### 结构化解释器结果 + +使用标准解释器入口及包含解释器的模板。极速版 ProviderSandbox 适配器未实现解释器操作。 + +```python +from agent_sandbox.code_interpreter import Sandbox + +with Sandbox.create(template="code-interpreter-v1") as sandbox: + result = sandbox.run_code("print(1 + 1)") + assert result.error is None + print(result.text) +``` - # 2. 代码解释器 —— sandbox.run_code(code) - code_result = await sandbox.run_code("print(1 + 1)") - print(code_result.text) # "2" +完整脚本见[导入迁移示例](compat-demos/e2b_import_migration.py)和 +[装饰器示例](quickstart/05_decorator_usage.py)。 - # 3. 命名命令 —— sandbox.run(name, **kwargs) - # 对模板 SandboxServer 发 POST /commands/hello - value = await sandbox.run("hello", name="Alice") - print(value) # 命令返回值 +### 注册的应用命令 + +先按[模板指南](../docs/zh/guide/template-workflows.md)配置所选提供方并启动 +python-hello。源码准备需要 CLI 文档中的 Docker 和镜像仓库配置。 + +```bash +export ABX_SERVER_TOKEN='replace_me' +abx --provider alicloud-express template launch 'alibaba-agent-sandbox/awesome-templates//python-hello' +``` + +将返回的标识写入 `SANDBOX_ID`,使用相同的应用令牌: + +```python +import os +from agent_sandbox import ProviderSandbox + +sandbox = await ProviderSandbox.connect(os.environ["SANDBOX_ID"]) +try: + async with await sandbox.application_client( + 9000, token=os.environ["ABX_SERVER_TOKEN"] + ) as client: + print(await client.commands.run("hello", name="Alice")) +finally: + await sandbox.close() ``` -> **说明:** `sandbox.run(name, **kwargs)` 调用注册在模板 server 里的命令,不会执行 shell 字符串。要执行 shell 请用 `sandbox.commands.run(cmd)`。 +这里只释放借用的连接;使用完按启动器的清理说明删除自己创建的资源。 +普通 base 沙箱不包含 hello 服务。 ### 文件操作 ```python # 写入和读取文件 - await sandbox.files.write("/app/data.txt", "内容") - content = await sandbox.files.read("/app/data.txt") + await sandbox.files.write("/home/user/data.txt", "内容") + content = await sandbox.files.read("/home/user/data.txt") ``` ### 网络 @@ -159,7 +191,7 @@ async with await Sandbox.create(template="base", sandbox_api_key="...") as sandb ```python from agent_sandbox.declarative import sandbox -@sandbox(template="code-interpreter", packages=["numpy"]) +@sandbox(template="code-interpreter-v1", packages=["numpy"]) def compute(n: int) -> float: import numpy as np return float(np.random.random(n).mean()) @@ -173,4 +205,4 @@ result = compute(1000) # 自动在远程沙箱中执行 `agents/codex_agent.py` 必须提供真实 `OPENAI_API_KEY`;可选 `OPENAI_BASE_URL`、`OPENAI_MODEL` 指定兼容模型,不会使用模拟回答。`agents/browser_automation.py` 安装真实 Chromium,默认访问沙箱内自建 HTTP 页面;设置 `BROWSER_URL` 可测试外部页面。 -`compat-demos/e2b_import_migration.py` 使用标准同步解释器客户端及其文档中的 E2B 配置名;其他云端示例使用 `ProviderSandbox` 或 `@sandbox` 和 `ABX_SANDBOX_API_KEY`。完整命令见[云端示例](../docs/zh/guide/cloud-examples.md)。 +`compat-demos/e2b_import_migration.py` 使用标准同步解释器客户端;本项目示例统一使用 ABX 沙箱配置,其他云端示例通过 `ProviderSandbox` 或 `@sandbox` 调用。完整命令见[云端示例](../docs/zh/guide/cloud-examples.md)。 diff --git a/examples/compat-demos/e2b_import_migration.py b/examples/compat-demos/e2b_import_migration.py index e3001a9a..639f496c 100644 --- a/examples/compat-demos/e2b_import_migration.py +++ b/examples/compat-demos/e2b_import_migration.py @@ -1,6 +1,6 @@ """Import-only migration example / 仅替换导入的迁移示例. -Configure E2B_API_KEY, E2B_API_URL, E2B_DOMAIN for Alibaba Express. +Configure ABX_SANDBOX_API_KEY, ABX_SANDBOX_BASE_URL, ABX_SANDBOX_DOMAIN for Alibaba Express. 配置阿里云极速版连接参数后直接执行。 """ diff --git a/examples/quickstart/05_decorator_usage.py b/examples/quickstart/05_decorator_usage.py index 3bcd75dc..24c15826 100644 --- a/examples/quickstart/05_decorator_usage.py +++ b/examples/quickstart/05_decorator_usage.py @@ -3,7 +3,7 @@ 演示使用 @sandbox 装饰器将普通函数声明式地在远程沙箱中执行。 Shows how to use the @sandbox decorator for declarative remote execution. -需要安装: pip install agent-sandbox-client +需要安装: pip install --index-url https://pypi.org/simple agent-sandbox-client==0.4.0a2 工作流程: 1. 创建远程沙箱 diff --git a/examples/quickstart/README.md b/examples/quickstart/README.md index acae391b..258bcd0f 100644 --- a/examples/quickstart/README.md +++ b/examples/quickstart/README.md @@ -11,7 +11,7 @@ Quickstart demos showing core **Agent Sandbox** SDK capabilities — sandbox lif - Environment variables: ```bash -python -m pip install "agent-sandbox-client[all]==0.4.0a2" +python -m pip install --index-url https://pypi.org/simple "agent-sandbox-client[all]==0.4.0a2" export ABX_SANDBOX_API_KEY="your-express-sandbox-api-key" # Set ABX_SANDBOX_BASE_URL and ABX_SANDBOX_DOMAIN for your region if needed. ``` diff --git a/server-sdk/README.md b/server-sdk/README.md index 5fe6aae5..96fb63dc 100644 --- a/server-sdk/README.md +++ b/server-sdk/README.md @@ -12,7 +12,7 @@ Import path: `agent_sandbox.server` (a namespace shared with `agent-sandbox-clie ## Install ```bash -python -m pip install --upgrade --pre agent-sandbox-server +python -m pip install --index-url https://pypi.org/simple --upgrade --pre agent-sandbox-server python -m pip check ``` diff --git a/server-sdk/RELEASING.md b/server-sdk/RELEASING.md index 307f56e2..f6d8085a 100644 --- a/server-sdk/RELEASING.md +++ b/server-sdk/RELEASING.md @@ -4,7 +4,12 @@ Publish `agent-sandbox-server` first, then `agent-sandbox-client`, from the same ## Candidate and versions -The current candidate is **0.3.1a1**, an opt-in alpha, not a production-readiness claim. It is not published until the workflow and public readback succeed. This alpha follows the existing source version 0.3.0; unlike 0.3.0a1, it satisfies the catalog providers' `sdk >=0.3` requirement without weakening the compatibility check. The Node provider doctor requires the companion CLI initialize endpoint (planned CLI 0.4.11); public CLI 0.4.10 does not implement it. +The current published pair is **0.4.0a2**, an opt-in alpha. The public release +workflow, artifact hashes and fresh-install readback passed; this does not certify +all templates, cloud account features or production workloads. Use a new lockstep +version and reviewed tag for the next release; never replace existing a2 files. +Provider-plugin integration additionally needs the compatible separately installed +CLI and the selected provider's configuration. Keep four locations equal; existing version-lockstep tests enforce them: @@ -18,12 +23,13 @@ Update CHANGELOG and run the repository CI and real-component acceptance gates b ## Build and inspect ```bash +# First update the lockstep version and substitute its actual reviewed tag below. make build dist-check -python scripts/check_release.py candidate --tag v0.3.1a1 +python scripts/check_release.py candidate --tag 'v' python scripts/check_release.py preflight ``` -Both wheels and sdists must pass metadata checks; a fresh wheel install must expose the standard clients, ProviderSandbox, workflow YAML parser and server imports. `dist/` is generated and must not be committed. The server owns only `agent_sandbox/server/`; the client owns the root namespace. A different file already published under a candidate filename fails preflight rather than being silently skipped. +Both wheels and sdists must pass metadata checks; a fresh wheel install must expose the standard clients, ProviderSandbox, template YAML parser and server imports. `dist/` is generated and must not be committed. The server owns only `agent_sandbox/server/`; the client owns the root namespace. A different file already published under a candidate filename fails preflight rather than being silently skipped. ## Authentication and execution @@ -35,7 +41,7 @@ Manual dispatch **defaults to dry_run=true** and accepts a version tag, not a br ```http POST /repos/Alibaba-Agent-Sandbox/python-sdk/actions/workflows/publish.yml/dispatches -{"ref":"v0.3.1a1","inputs":{"dry_run":"true"}} +{"ref":"v","inputs":{"dry_run":"true"}} ``` After dry-run validation, publish a GitHub **prerelease** for that reviewed tag, or dispatch the same tag with `dry_run=false`. Publishing a GitHub Release triggers upload. Merely creating a draft release does not. Do not publish a stable release for an alpha version. @@ -43,20 +49,26 @@ After dry-run validation, publish a GitHub **prerelease** for that reviewed tag, ## Recovery and public verification If one upload fails, preserve and reuse the exact candidate artifact from that run. Preflight compares existing filenames and SHA-256 before `skip-existing` can resume the missing files. Rebuilding is not proof of identical bytes; if hashes differ, stop and investigate instead of overwriting or silently accepting them. Only call the release published after both projects' public metadata, downloads and fresh installation pass. +The workflow retries missing public metadata and fresh official-index installation +at most six times, ten seconds apart. Artifact digest mismatches fail immediately; +pip check and import failures are not retried. After verified publication, consumers can explicitly opt in: ```bash -python -m pip install 'agent-sandbox-client==0.3.1a1' +python -m pip install --index-url https://pypi.org/simple 'agent-sandbox-client==0.4.0a2' python -m pip check ``` ## 中文发布说明 -client/server 必须同版本发布,先上传 server。当前候选为 `0.3.1a1` alpha;它满足现有 provider 的 `sdk >=0.3` 要求,不需要放宽 gate。它不是生产就绪承诺,公开回读成功前不得称为已发布。Node provider doctor 需要配套的新 CLI initialize 接口,0.4.10 不具备此接口。 +client/server 必须同版本发布,先上传 server。当前已公开配套版本为 `0.4.0a2` +alpha,发布流程、产物摘要及全新公开安装验证均已通过;这不代表所有模板、账号能力 +或生产负载已完成验证。下一次发布须选择新的同版本双包和已审查标签,不得替换已有 +a2 文件。Provider 插件还需兼容的独立 CLI 和所选提供方配置。 四处版本(两个 `_version.py`、client 的 server 精确依赖、MCP `SERVER_VERSION`)一起更新。先通过同一标签的完整 CI、产物检查和真实组件验收。将 token 保存在 GitHub repository 或 `pypi` environment 的 `PYPI_API_TOKEN` secret 中,由上传步骤直接引用;不要复制到源码或日志。此流程发布到正式 PyPI 的预发布版本,不是 TestPyPI,也不声明 OIDC 证明。 -手动执行默认 `dry_run=true`,必须选择 `v0.3.1a1` 这样的版本标签,选择 main 会失败。验证后创建该标签的 GitHub prerelease,或显式设置 `dry_run=false`。工作流保存本次产物,先检查已有公开文件摘要,再按顺序上传;最后仅安装固定版本 client,验证 server 自动依赖、导入与 `pip check`。 +手动执行默认 `dry_run=true`,必须选择实际已审查的 `v` 版本标签,选择 main 会失败。验证后创建该标签的 GitHub prerelease,或显式设置 `dry_run=false`。工作流保存本次产物,先检查已有公开文件摘要,再按顺序上传;最后仅安装固定版本 client,验证 server 自动依赖、导入与 `pip check`。 部分上传失败时保留并使用同一批候选文件。重新构建后如摘要不同,应停止调查,不得依赖 skip-existing 掩盖差异。全部公开包下载与安装验证通过后,才更新对外的发布状态。