Agent Sandbox Registry

python-sdk

Decision: Command Capability Model (Vocabulary + Default Baseline + Gating)

无中文版

.agents/notes/implemented/architecture/2026-09-03-capability-model.md

Decision: Command Capability Model (Vocabulary + Default Baseline + Gating)

Status: implemented

Problem

Not every sandbox exposes the same operations. Previously the SDK assumed all sandboxes support shell/upload/download, so calling a missing operation failed with an opaque protocol error deep in the transport layer. We need a first-class model that lets a template declare which command capabilities it provides, and a well-defined behavior when a caller invokes a capability the sandbox does not have.

Decision

Introduce a standard capability vocabulary and gate every standard-capability call against the sandbox's effective capability set.

  1. Standard capability vocabulary (extensible): shell / files / code / terminal / ports. Capabilities are declared by the template, not assumed. New members can be added to the vocabulary later.
  2. System default baseline: a single constant DEFAULT_CAPABILITIES = {shell, files, code}. terminal and ports are NOT in the baseline and must be declared explicitly by a template. Templates SHOULD follow the baseline but MAY opt out: a template declares its supported capability set via capabilities: in template.yaml (a subset of the baseline, or the baseline plus terminal/ports). When a template omits capabilities, it inherits DEFAULT_CAPABILITIES. Keeping the baseline as one constant makes it trivial to adjust.
  3. Gating always applies: invoking a standard capability that is not in the sandbox's effective capability set raises CapabilityNotSupportedError (E3xxx). The error is explicit — no silent degradation — and its message includes a suggestion.

The effective capability set is resolved at sandbox connect time from the template metadata (see command-source-resolution ADR); when metadata is unavailable it falls back to DEFAULT_CAPABILITIES.

API Design

# models/config.py (or a new capability module)
Capability = Literal["shell", "files", "code", "terminal", "ports"]

DEFAULT_CAPABILITIES: frozenset[Capability] = frozenset({"shell", "files", "code"})

class CapabilityNotSupportedError(ExecutionError):
    """Raised when a standard capability is not in the sandbox's effective set."""
    code = "E3004"
    # message includes the missing capability; suggestion lists available capabilities
    # and how to declare it in template.yaml

Effective set resolution: - template.capabilities declared → use it (validated against the vocabulary). - omitted → DEFAULT_CAPABILITIES.

Alternatives considered

Dependencies

Test Strategy

Acceptance criteria

Consequences