Repository navigation
refactor(providers)!: each sandbox provider declares what it runs, and nothing outside the providers asks which one it is - #143
Merged
Conversation
…build The build cache and its locks, the build, the Dockerfile rewrite and fetching the context move out of the provider module unchanged; the provider asks context_image for the built image. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… nothing outside the providers asks which one it is A provider declares whether its sandboxes run on this machine (ON_THIS_MACHINE), how it runs an image for an agent, a lone server and a gateway's servers (runs: in a VM it creates, by name, or building it first), the providers a deploy on it may run on (links), how its sandboxes reach a URL (url_from_sandbox) and the options a gateway's containers take on it (gateway_container_options). Preflight, the agent and server deploys, the gateway's choice between containers and a VM, chain unwrapping, teardown and put_from_github read those instead of checking for Local, Modal or chain classes; image_problem is the one rule a deploy and preflight share. A test fails on any class check outside the providers. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ovider their declared facts Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
earakely-scale
force-pushed
the
edgararakelyan/provider-capabilities
branch
from
October 9, 2026 20:19
12cc409 to
620cb59
Compare
Collaborator
Author
|
@greptileai review |
…s create_sandbox and create_container, and containers share a private network A provider now declares how it runs an image it's given through create_sandbox or create_container, rather than for an agent, a lone server or a gateway. The gateway takes a VM on a provider that creates VMs and a container per server on one that doesn't, and its containers ask create_container for private_network and reach one another at their sandbox's private_host. Modal maps that to i6pn in its configured region, so the i6pn vocabulary stays in the Modal provider. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Collaborator
Author
|
@greptileai review |
…al call The gateway now asks for private_network rather than i6pn, which an override that refuses i6pn up front no longer sees, so the provider refuses the combination before it looks up its App or builds an image. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ch deploy says what it runs there A provider declares CREATES_VMS, SANDBOX_ACCEPTS, CONTAINER_ACCEPTS and PRIVATE_NETWORK with ON_THIS_MACHINE, rather than having them inferred from the methods it overrides; one that declares nothing runs images by name and creates no VM and no private network. Accepts names the forms of image it takes: LOADABLE (a VM's tar.gz, registry name or build context), NAME, and NAME_OR_CONTEXT (built first, by prepare_image). The agent, the lone server and the gateway each say what they accept on a provider, and preflight asks them rather than re-deriving it. The gateway owns its rule (a VM where its provider creates VMs, else a container per server on the provider's private network), so preflight and the deploy read one answer, and both refuse a gateway on a provider with neither. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…d every deploy prepares every image Modal's create_container drops i6pn and region, which nothing passed any more: private_network is the one way to ask for i6pn, in the configured region. The agent, the lone server and the gateway call prepare_image for every image, as its contract says; a provider that has nothing to prepare, as Modal for an image that isn't only a build context, returns at once. The container gateway's own refusal of websites, which the deploy now refuses first, goes, and EnvironmentProvider reads a chain's links directly. Co-Authored-By: Claude Opus 5.5 (1M context) <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.
Follows #137 (merged).
Code outside the sandbox providers used to choose by checking a provider's class (
isinstance(LocalSandboxProvider),isinstance(ModalSandboxProvider),isinstance(ChainedSandboxProvider)) or by guessing from which methods a class overrides. That happened in more than a dozen places across preflight, the agent and server deploys, the gateway, chain handling, teardown andput_from_github. Now each provider declares what it runs, each deploy says what it runs on a provider, and everything else reads those.What a provider declares (
SandboxProvider)The sandbox layer knows sandboxes, containers, VMs and networks, never what a caller deploys (an agent, a server, a gateway).
ON_THIS_MACHINECREATES_VMScreate_vmgives a VMSANDBOX_ACCEPTS/CONTAINER_ACCEPTScreate_sandbox/create_containerrunNAME/NAMENAME/NAMENAME_OR_CONTEXT/NAME_OR_CONTEXTLOADABLE/NAMEPRIVATE_NETWORKcreate_container(private_network=True)puts containers on a network they share, each reached at its sandbox'sprivate_hostlinksurl_from_sandbox(url)host.docker.internalAcceptsnames the forms of image a provider takes, andAccepts.problem(image)says why one is refused:LOADABLE: anything a VM can get, whether a tar.gz it loads, a registry name it pulls, or a build context it builds.NAME: an image it starts by name, so not one that is only a build context.NAME_OR_CONTEXT: by name, or a build context it builds first, throughprepare_image.The declarations are explicit, not inferred from which methods a class overrides. A provider that declares nothing runs images by name and creates no VM and no private network, so a provider that hasn't said what it does is refused up front rather than misdescribed.
What each deploy says it runs
A2AAgent.accepts(provider)is the provider'sSANDBOX_ACCEPTS.EnvironmentServerProvider.accepts(provider)is itsCONTAINER_ACCEPTS.EnvironmentGatewayProviderowns its rule.in_vm(provider)is true where the provider creates VMs; elsewhere the gateway runs a container per server on the provider's private network.acceptsandsandbox_problemfollow from that: a container gateway needs the private network and serves no websites.Preflight passes these to one check instead of re-deriving each deploy's rules, and the deploys read the same answers, so the two can't drift.
Breaking for plugins
create_containergainsprivate_network, which an override without**kwargsdoesn't accept. The built-ins and agentenvhub-sdk's one override take it.create_vmmust now declareCREATES_VMS = True, andSANDBOX_ACCEPTS = Accepts.LOADABLEwhen its sandboxes are VMs. Undeclared, it is taken for one that creates no VM: its gateways are refused, and so are context-only images for its agents.create_containerdropsi6pnandregion, which nothing passed any more:private_networkis the one way to ask for i6pn, in the configured region.beta_scaleandarpneed those two declarations, andmodal_gpuneedsPRIVATE_NETWORK = Falseand an override that no longer takesi6pn. That sdk change rides the pin bump to this release, with its CUA env reading a provider'slinksandCREATES_VMSinstead of checking its class.Also here
modal_image_build.py, unchanged: the cache and its locks, the build, the Dockerfile rewrite and fetching the context.prepare_imagefor every image, as its contract says; a provider with nothing to prepare (Modal, for an image that isn't only a build context) returns at once.EnvironmentProvider._sandbox_providers, a hook nothing overrode (it reads a chain'slinksdirectly).Tests
Accepts.problem;src/and fails on anyisinstance/issubclasscheck for a concrete sandbox or provider class outside the provider package.beta_scaleruns gateways in a VM; without them it would be refused, which is why they ride the pin bump.@localids: the integration bundle (four agents, plus a server through Modal's container gateway) and the Slack env through the gateway. Earlier commits on this PR also ran the bundle onbeta_scale,modal, a lone server, a project App build, concurrent builds and a stale image id.🤖 Generated with Claude Code


Confidence Score: 5/5
The PR appears safe to merge with the acknowledged SDK rollout requirement.Summary
Providers now declare where they run, which images they accept, and whether they offer VMs or a private network. Deploys and preflight read those declarations instead of checking provider classes.
Diagram
%%{init: {'theme': 'neutral'}}%% flowchart TD P[Provider declarations] --> F[Preflight checks] P --> A[Agent image choice] P --> S[Server image choice] P --> G[Gateway choice] G --> V{Creates VMs?} V -->|Yes| VM[Run services in one VM] V -->|No| N{Has private network and no websites?} N -->|Yes| C[Run separate containers] N -->|No| R[Refuse before creating containers]Reviews (6) · Last reviewed commit: "refactor(providers): one way to ask Moda..." · Reviewed by Greptile