feat(sandbox): expand sandbox provider catalog with E2B, Modal, Runloop, Vercel, and LangSmith - #8
Merged
Merged
Conversation
Combine Unreleased changelog entries from the sandbox catalog and robust Ollama integration branches under shared Added/Changed/Fixed sections. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Pull Request
Summary
AnyCode shipped exactly one remote sandbox backend (Daytona). This PR brings the catalog to parity with the LangChain deepagents sandbox lineup: E2B, Modal, Runloop, Vercel Sandbox, and LangSmith now implement the
SandboxProviderprotocol alongside Daytona, each behind its own install extra with lazy SDK imports and honest capability reports. Observable changes:E2BSandboxProvider,ModalSandboxProvider,RunloopSandboxProvider,VercelSandboxProvider,LangSmithSandboxProvider, plus acreate_sandbox_provider(name)factory (all exported from the package root andanycode.sandbox).sandbox-e2b,sandbox-modal,sandbox-runloop,sandbox-vercel,sandbox-langsmith— each with a matching CIoptional-extrasmatrix entry (enforced bytests/test_ci.py) and refresheduv.lock. Deliberately not added to theallextra (Modal is heavyweight; the Vercel Python SDK is beta).SandboxSpec.secret_referencesvalues are now generic provider-prefixed references (<provider>:<name>) instead ofdaytona:-only; each backend validates its own prefix at create time and returnssandbox_secret_reference_invalidfor foreign prefixes.create()with a typed error (sandbox_network_policy_unsupported,sandbox_snapshot_unsupported,sandbox_secrets_unsupported) — never silently granting more than requested.command_streaming=False(buffered v1 — output delivered after command completion, streaming contract still satisfied); Modal (snapshot_filesystem) and Runloop (snapshot_disk) declare and implement real snapshots; every report carries an explicitlimitationstuple.Change type
Compatibility
SandboxProviderprotocol is unchanged. TheSandboxSpecsecret validator is loosened, not tightened — every previously valid spec (daytona:*references) still validates, and plaintext values are still rejected. Daytona now additionally rejects foreign-prefixed references atcreate()with a typed error; that input was previously unreachable (model validation rejected it), so no working caller changes behavior. CLI, YAML/TOML, checkpoints, durable run data: none.Verification
New
tests/test_sandbox_providers.py: a shared lifecycle-conformance helper (create → execute → stream → file write/read roundtrip → cancel → snapshot → destroy → health, evidence digestssha256:*, monotone stream sequences,isinstance(provider, SandboxProvider)) run against all five backends with injected fake clients — fully offline, no SDK installs needed. Per-provider tests cover network fail-closed, secret rejection/prefix mapping (Modalmodal:<name>→Secret.from_name), Runloop blueprint/snapshot argument mapping, Vercel runtime mapping, LangSmith shell-based file transfer including the missing-file error path, and missing-SDKpip install "anycode-py[sandbox-<name>]"guidance viasys.modulesmonkeypatching.tests/test_sandbox.pyextended for the generalized secret prefixes.uv run python -m pytestuv run python -m ruff check .uv run python -m ruff format --check src/uv run python -m pyrightuv run python -m mkdocs build --strict(plusscripts/check_docs.py: 409 exports validated)Documentation and release notes
reference/public-api.mdSandboxes section lists all backends + factory; the generated API inventory picks up the new exports at build time)site_docs/llms.txtupdated where needed (guides/sandbox-providers.mdgained a provider-selection matrix and factory section;getting-started/installation.mdextras table now lists all sandbox extras — the basesandboxextra was previously missing there)[Unreleased]changelog entry added, or no user-visible changeE2B_API_KEY, Modal tokens,RUNLOOP_API_KEY,VERCEL_TOKEN/VERCEL_OIDC_TOKEN+ team/project ids,LANGSMITH_API_KEY)Reviewer notes
stream()as buffered execute (sharedbuffered_streamhelper in_base.py) and declarecommand_streaming=False. Live streaming exists in some SDKs (E2B background commands, Modal stdout iteration) but claiming it requires verification against each real SDK surface; upgrading a backend later is additive. This is the capability-honesty rule: never claim what is not implemented.call_maybe_async(handles sync/async/.aiovariants) and getattr-based response parsing, mirroring the defensive style of the existing Daytona adapter. All constructors accept an injected client, so tests never import an SDK.base64shell commands (the SDK surface is run()-centric); the capability report's limitations note the image must provide a POSIX shell and base64.Secret.from_namemapping.tools/bash.pythrough aSandboxProviderbackend; live streaming upgrades after real-SDK verification; real-credential integration tests.