Thank you for your interest in contributing! This guide will help you get started.
This repository (python-sdk) holds the Python SDK, which is released as two PyPI
distributions that share the agent_sandbox namespace and are versioned in lockstep:
| Folder | PyPI distribution | Import path | Purpose |
|---|---|---|---|
client-sdk/ |
agent-sandbox-client |
agent_sandbox |
Standard sync/async clients and native provider/server extensions (ProviderSandbox, ServerClient, @sandbox, MCP server, ...) |
server-sdk/ |
agent-sandbox-server |
agent_sandbox.server |
Container-side runtime that runs inside sandbox images |
The abx command-line tool is a separate Node.js/TypeScript project that lives in the
agent-sandbox repository. CLI issues and pull requests belong there, not here.
- Python 3.10+
- Git
# 1. Fork and clone the repository
git clone https://github.com/<your-username>/python-sdk.git
cd python-sdk
# 2. Install both packages in development mode (includes all extras + test/lint tooling)
pip install -e ./server-sdk -e "./client-sdk[dev]" # or: make dev
# With uv, in an activated virtual environment:
uv pip install -e ./server-sdk -e "./client-sdk[dev]"
# 3. Install pre-commit — its checks are invoked automatically by .githooks/pre-commit
pip install pre-commit # or: make hooks
# 4. Verify your setup
make testThe root uv workspace maps agent-sandbox-server to server-sdk/, so the
client uses the matching local runtime during development. No --no-sources
workaround is needed. Published client metadata keeps the lockstep version pin.
Note on Git hooks: This repository ships
.githooks/and uses it as the hook entry point viacore.hooksPath=.githooks(a local Git config)..githooks/pre-commitfirst runs the custom secret scan (.githooks/check-secrets.sh), then — if thepre-commitcommand is installed — invokes the full.pre-commit-config.yamlsuite (ruff, ruff-format, detect-secrets, bandit, …). Installing the package (pip install pre-commit, ormake hooks) is all that is needed:pre-commit installis not used here because it writes to.git/hooks/, which Git bypasses whilecore.hooksPath=.githooksis set. On a fresh clone (wherecore.hooksPathis unset), rungit config core.hooksPath .githooks— orpre-commit install— to activate the hooks.
-
Fork the repository on GitHub
-
Create a branch from
main:git checkout -b feat/my-feature
-
Make your changes — write code, tests, and docs
-
Run checks before committing:
make lint # Lint with ruff (client-sdk and server-sdk) make format # Format with ruff make typecheck # Type-check with mypy make test # Run tests with pytest
Every
maketarget runs on both packages. To work on a single package, run the tools from inside its folder instead, for example:cd client-sdk && ruff check src tests && mypy src/agent_sandbox && pytest -m "not integration" cd server-sdk && ruff check src tests && mypy src/agent_sandbox/server && pytest
Or run the full local CI equivalent in one command:
make ci # ruff check + ruff format --check + mypy + pytest (not integration) + build both packages + twine check + py.typed check + combined-install import checkNote:
make ciruns on your single local Python interpreter. It does not replace the Python 3.10 / 3.11 / 3.12 test matrix enforced by GitHub Actions CI — the matrix can only be fully covered by CI itself. -
Commit using Conventional Commits:
feat: add sandbox snapshot support fix: resolve timeout issue in pool manager docs: update CLI usage examples chore: bump ruff to 0.5.0 -
Push and open a Pull Request against
main
We use Ruff for both linting and formatting (replacing the former black / isort / flake8 setup). The configuration lives in each package's pyproject.toml (client-sdk/pyproject.toml, server-sdk/pyproject.toml) under [tool.ruff].
- Type Hints: All public APIs must have type annotations; we enforce this with mypy.
- Docstrings: Use Google-style docstrings for public functions and classes.
async def create_sandbox(template: str, timeout: int = 300) -> Sandbox:
"""Create a new sandbox instance.
Args:
template: Name of the sandbox template.
timeout: Maximum creation time in seconds.
Returns:
A configured Sandbox instance.
Raises:
SandboxError: If sandbox creation fails.
"""A custom hook (.githooks/check-secrets.sh) scans every commit for hardcoded secrets — API keys, tokens, passwords, and cloud credentials. Commit-time checks flow through a single entry point:
| Component | Role |
|---|---|
.githooks/pre-commit |
Primary hook entry point. Git calls it because this repository is configured with core.hooksPath=.githooks. |
check-secrets.sh |
Runs first: scans staged files for hardcoded secrets and blocks the commit if any are found. |
| pre-commit framework | Runs second (when the pre-commit command is installed): executes every hook in .pre-commit-config.yaml — ruff, ruff-format, detect-secrets, bandit, plus the check-secrets local hook — via pre-commit run --hook-stage pre-commit. |
To enable the full suite locally, install the package once:
pip install pre-commit
# or:
make hooksIf pre-commit is not installed, .githooks/pre-commit still runs the secret
scan and prints an install hint; the framework step is skipped without blocking
the commit.
If the hook detects a secret, the commit is blocked and the offending file + line is printed. False positives can be suppressed by adding placeholder, example, or REPLACE_ME to the line.
- We use pytest for testing.
- Write tests for all new features and bug fixes.
- Place tests in the
tests/directory of the package you are changing (client-sdk/tests/orserver-sdk/tests/), mirroring that package'ssrc/structure.
# Run all tests (both packages)
make test
# Run a specific test file
pytest client-sdk/tests/test_api/test_sandbox.py
# Run with verbose output
pytest -vA change is done only when it is verified end to end against real components and recorded under
.agents/. Every PR must provide: unit tests, an E2E run against the real cloud (make e2e, see
e2e/README.md) recorded in .agents/evidence/verify/<date>-<topic>.md (never
containing credentials), an ADR/note under .agents/notes/, English and Chinese docs, and a
CHANGELOG.md entry. Real credentials live only in gitignored .env files and must never be printed,
logged or committed. The full rule, the evidence-file and ADR templates are in
.agents/notes/DEFINITION-OF-DONE.md (English and 中文:
完成定义——所有功能必须针对真实组件完成端到端验证,并在 .agents/ 中记录,文档需中英文齐全并附 CHANGELOG 条目)。
Sandbox templates — content, the machine-readable index (awesome-templates.yaml), releases and CI — live in the dedicated repository alibaba-agent-sandbox/awesome-templates. It is the single source of truth for official & community templates; this repository no longer bundles a template collection (it keeps only a minimal python-hello offline fixture for tests).
Read the owning repository's contributor guide and template specification before submitting there. Those files own the current manifest, catalog fields and required validation. Maintenance labels do not certify runtime behavior. Do not duplicate their schema or a template-status checklist in this SDK repository.
Use the CLI (abx, from the agent-sandbox repository) to search the remote index:
abx template search python # search by tag or keyword
abx template search ai-agent # find AI agent templates
abx template search browser # find browser automation templatesWe follow Conventional Commits:
| Prefix | Purpose |
|---|---|
feat: |
New feature |
fix: |
Bug fix |
docs: |
Documentation only |
chore: |
Build, CI, or tooling changes |
test: |
Adding or updating tests |
refactor: |
Code change that neither fixes a bug nor adds a feature |
perf: |
Performance improvement |
- Use GitHub Issues with our templates
- For security vulnerabilities, see our Security Policy
- Open a Discussion for general questions
- Check existing issues and discussions before creating new ones
By contributing, you agree that your contributions will be licensed under the Apache-2.0 License.
The complete CI workflow runs on pull requests targeting any branch, including a
feature branch. Wait for the runtime, typecheck, test and build jobs on the latest
head; a Markdown-only result does not establish product validation. Push events
remain limited to main. Real-component evidence and all other definition-of-done
requirements still apply.
完整 CI 会验证目标为任意分支的拉取请求,包括以功能分支为基底的堆叠 PR。
须确认最新提交的运行、类型、测试和构建任务实际完成;仅 Markdown 检查通过
不能证明产品验证完成。直接推送仍仅在 main 触发;真实组件证据和其余完成
标准继续适用。
Publish both distributions from a matching v<version> tag. The publication workflow runs the full reusable CI suite at that tag, builds and preserves one wheel/sdist pair per distribution, and verifies a combined clean installation. Manual runs default to dry-run. Before upload, existing PyPI files must match the candidate SHA-256; skip-existing is not sufficient verification. Upload server before client, then verify public digests and a fresh exact-version client installation with its automatic server dependency and pip check. Inspect the README embedded in both packages: it must not send users to an obsolete version. Preserve tags and artifacts; a content change uses a new version.
两个发行包从匹配的 v<version> 标签发布,先执行完整 CI,再构建、保存并检查配套产物。手动运行默认 dry-run。上传前核对 PyPI 已有文件的 SHA-256,不能只依赖 skip-existing。先上传服务端,再上传客户端;随后检查公开摘要、新环境精确版本安装、自动服务端依赖和 pip check。检查双包内的 README,避免把用户导向旧版本。保留既有标签与产物,内容变更使用新版本号。