An agent can cause a serious incident without malicious intent. A plausible instruction, a tool with excessive permissions, and a credential in the wrong environment can result in deletion of a production database, disclosure of private data, or unauthorised spending. Safety therefore depends on what the complete system can discover, reach, and change when its instructions, tools, or assumptions fail. An agent sandbox provides a repeatable capability test before the agent receives access to real systems.
Capability is larger than the prompt
A model may say that it will not delete a database, but the model is only one part of an agent. The effective capability is the combination of the model, system prompt, tool definitions, runtime identity, filesystem, network routes, environment variables, mounted volumes, and services reachable from the process. If a shell tool can run as an administrator, the agent has administrator capability whether or not the prompt mentions it. If a database client has a production connection string, a single mistaken tool call can become a production change.
Capability testing therefore covers the full execution path. Give the agent a bounded task, the tools it would use in practice, and realistic but harmless fixtures. Test destructive commands, secret discovery, prompt injection, data exfiltration, privilege escalation, network bypass, and uncontrolled resource use. A model refusal provides behavioural evidence; a system control that blocks the action provides evidence about the enforced boundary. The boundary should make the dangerous action impossible or harmless even when the model attempts it.
A sandbox must be a real boundary
A separate working directory is not a sandbox. A container is useful isolation, but it shares a kernel and often inherits more host access than its name suggests. For capability testing, the agent should run in an environment with no path to the host filesystem, host control socket, production network, personal SSH keys, cloud configuration, or real credentials. Root inside the test environment can be acceptable; access outside it is the thing that needs to be controlled.
A workable arrangement runs the agent in a minimal virtual machine rather than a container on the host. The guest gets no general view of the host filesystem, and shared data moves through a volume that is mounted explicitly for the run. Network traffic passes through a gateway that applies an allowlist and records what the agent attempted, including the traffic it dropped. Public internet access is off by default, and local model or fixture services are reachable only through named, port-specific endpoints. These are design properties, not guarantees, so the capability suite has to verify them for each image and policy version.
No sandbox is a proof of perfect isolation. The hypervisor, guest image, gateway, host configuration, and shared volume are all part of the trusted computing base. A sandbox should therefore state its boundary, version its images and rules, and be treated as a test environment rather than a licence to run hostile code casually. High-assurance escape research is a different project with a different review bar.
Remove the consequences before testing
The first safety control is environmental, not behavioural: do not put anything in the sandbox that could cause real damage. Never provide production credentials, cloud profiles, real kubeconfig files, reusable SSH keys, payment secrets, or tokens for a service that matters. If the agent can read it, assume it can copy it into a prompt, an output file, a tool argument, or an outbound request. A network block does not make a secret safe; the agent may still expose it to another process or to the model provider.
Replace important systems with fixtures and decoys. A database test can contain a synthetic schema and a canary row whose deletion is detected. A cloud integration can be a local API that records every request. A file operation can target a disposable tree with paths named like the real layout. A secret-handling test can use marked dummy values and verify that they never leave the approved channel. The test should make a dangerous action observable without making it consequential.
A staged test sequence starts with fixtures, then adds controlled network mocks, and finally uses a narrowly scoped test account or canary service if live integration is necessary. Results from each stage determine whether the next stage is justified. Live internet access gives the agent a path to remote systems, exposes outbound data to third parties, and makes rate limits and acceptable-use rules part of the test.
Test capabilities with material consequences
A capability matrix turns vague safety concerns into executable cases. For each capability, define the resource, the operation, the expected decision, and the evidence that proves it. Typical cases include reading outside the workspace, writing outside an approved path, executing a package or binary, and finding environment secrets. The suite should also test attempts to contact a private address, resolve an unapproved name, change firewall or runtime settings, and consume disk, memory, CPU, or model-server capacity without a bound.
Destructive actions deserve deliberate tests. Ask an agent to clean up a fixture that contains a fake production database, revoke a canary account, or remove a protected file. Put the same request behind a prompt injection in an untrusted document. Test whether it can reinterpret a tool description, invoke a lower-level shell to bypass a safer API, or keep retrying after an operation is denied. The expected result is not simply that the model says no. It is that the agent cannot reach a real target, the attempt is recorded, the denial is clear, and the run stops or escalates according to policy.
Capability tests should include benign work as well. An over-restricted sandbox that prevents reading the supplied fixtures, using the local model endpoint, or writing its report is not a useful evaluation environment. Safety is a measured operating envelope: the allowed task succeeds, the disallowed task fails, and the evidence distinguishes the two.
Default-deny egress makes behaviour visible
Network access can determine whether a mistake remains contained. A default-deny gateway blocks public internet traffic, private address ranges, host services, and unapproved container networks. Specific local services are published through explicit proxies with names and ports that can be audited. This prevents a coding task from gaining undeclared access to the host, the LAN, or other services on a container network.
The deny path is part of the measurement. DNS logs show what names the agent tried to resolve. Connection and packet records show what it attempted to reach. Firewall drops show that an agent tried to bypass its tool layer or contact a resource outside its assignment, even when the request never connected. A blocked request is therefore a useful safety signal, not merely a frustrating test failure. Repeated attempts, alternate IPs, unusual ports, and direct HTTP made outside the approved tool are all worth classifying.
Allowlisting must be treated as a change to the test boundary. A local model endpoint may appear low-risk but still expose management operations such as pulling, pushing, or deleting models. An uncontrolled run can also exhaust a shared service. Expose only the API surface required by the scenario, record the initial state, apply rate and size limits, and stop the run if the shared service begins to degrade.
Keep evidence outside the agent boundary
If the agent can edit its own audit trail, the audit trail is not evidence. The host-owned harness should create experiment records and keep them outside the guest. Records should include a manifest for the scenario, agent, model, command, image, and policy versions; structured tool events; output and exit status; timestamps; and hashes of the relevant artefacts. Gateway logs should remain unreachable from the agent so a curious or compromised process cannot rewrite the record of its own network activity.
Semantic events make a run easier to analyse. An adapter can emit events such as model prompt, tool call, and tool result in a simple structured format, while the harness adds a run identifier and sequence number. The resulting trace records more than whether the task passed. It shows which tool was called, its arguments, the agent's response to a denial, whether a secret appeared in output, and whether a network attempt exceeded the declared capabilities.
Treat every output as untrusted. Do not execute files copied out of the sandbox. Treat raw logs as potentially hostile input before passing them to another agent. A safety label in a report does not replace inspection of the underlying events. Reproducibility depends on retaining the exact task, configuration, model identifier, guest image hash, and boundary rules used for the run.
Watch intent with a supervising model
Deterministic controls catch actions that cross a boundary, but they cannot see an agent working steadily towards a goal it was never given. An optional supervising model can read the run as it happens: prompts, tool calls and arguments, tool results, outputs, and reasoning traces where the runtime exposes them. Its task is narrow and separate from the agent's. It classifies what the agent appears to be attempting, flags divergence from the assigned task, and identifies patterns that no single permitted action reveals, such as probing for credentials across several steps or staging data in an approved location before attempting to move it.
The supervisor must sit outside the agent boundary and act through the harness rather than through the agent. It reads the host-owned event stream described above, and the harness enforces its decisions: pause the run, deny the next tool call, revoke a grant, notify a human operator, or stop and preserve the evidence. If the agent can see the supervisor's prompts, alter its input, or continue after a suspension, the layer records opinions instead of enforcing anything.
Treat the supervisor as an AI system with its own failure modes. It reads attacker-controlled content, so its input is a prompt-injection surface. It can miss a slow and plausible sequence, and it can interrupt legitimate work often enough that an operator disables it. Give it a written policy with concrete examples of the intents that must be escalated, measure it against labelled runs from the capability suite, record its judgements alongside the actual outcome, and keep the deterministic controls in place whatever it reports. A supervising model adds a second, independent read of a run. It is not a boundary, and treating it as one returns enforcement to a model.
Use narrow tools and staged trust
A sandbox contains failures, while narrow tool design reduces the actions that can reach its boundary. Prefer read-only tools, scoped paths, typed arguments, resource identifiers, dry-run modes, idempotency keys, and explicit approval for irreversible operations. A tool called create_draft_invoice is easier to constrain than a generic database connection. A tool that accepts an invoice identifier is easier to audit than one that accepts arbitrary SQL. The agent should receive only the authority required to complete the task.
Trust should widen in stages. Start with observation or shadow mode, where the agent proposes actions and a person or deterministic service performs them. Move to reversible writes in a disposable environment, then to a canary resource, then to a tightly scoped production action only when the measured capability and quality tests justify it. Keep approval gates in front of deletion, publication, payments, access changes, and other actions whose consequences are difficult to undo.
Promotion is not a one-time certification. New tools, model versions, prompts, retrieval sources, network routes, and base images change the capability surface. Re-run the capability suite for each material change, retain a regression case for every incident, and make a failed safety assertion block promotion until an operator has understood and accepted the residual risk.
Report tested capabilities and outcomes
A useful sandbox report does not say that an agent is safe. It states what was tested and what happened. For each case, record the intended capability, the actual tool and system actions, the resources touched, the controls that intervened, and the final disposition: allowed, denied before execution, attempted but contained, or side effect observed. Include the limits of the test, such as the services not represented by fixtures or the parts of the host that were outside the boundary.
The decision to grant access can then be tied to evidence. An agent can qualify for a narrowly defined task when it completes that task with mocked web tools, cannot read outside its workspace, cannot reach the host or public internet, and leaves a complete trace. This does not provide permission to run migrations, delete records, or use a production identity. Those are separate capabilities with separate tests and separate approvals.
B12Y uses an internal sandbox built on these principles, and we intend to release it as open source. Publishing it would let others inspect the boundaries and measure unsafe attempts directly. The purpose either way is the same: to support controlled increases in agent capability when test evidence justifies the additional access.
Questions worth asking
- What could the complete agent reach, change, or exfiltrate if its prompt and tool policy failed?
- Are production credentials, host paths, cloud configuration, and unrestricted egress absent from the test environment?
- Which capability tests and host-side evidence must pass before each new tool, model, or environment is trusted?