Engineering

Every AI Coding Agent Needs a Sandbox

An AI coding agent sandbox is an environment contract, not a prompt. Here is how we made every checkout, cloud session, and worktree prove it is ready before an agent writes code.

Jonathan Wage

Founder / CEO

10 Min Read Reviewed by Mike Christensen Fact-checked by Mike Christensen
BluSky — The Future of Trading. Prop firm futures trading. Sign up at BluSky.pro.

Bottom Line

  • Agents fail at the environment layer before the model layer: missing dependencies, an old PHP runtime, or the wrong database produces confident work on a broken base.
  • One command detects the context (local, cloud, or CI), converges the environment, and prints a machine-readable contract with stable error codes and a remediation for each failure.
  • The rule is simple: do not implement until the verify step exits zero, and follow the reported remediation instead of hand-assembling setup steps.
  • Parallel agents get sibling git worktrees with their own app container and isolated state, while sharing the expensive data plane.
  • Isolation is ongoing engineering: real parallel use surfaced leaking cookies, a stale proxy block that took down a shared edge, and a bare Docker Compose command that changed the wrong stack.

An AI coding agent sandbox is not a paragraph in a prompt telling the agent to be careful. It is an environment that a script can create, a command can verify, and a second agent cannot trample. In our experience the first thing to break on a production codebase is not the model but the checkout: missing dependencies, the wrong runtime, a database pointing somewhere it should not, or another session already using the same working tree.

This is part of a series on how we run agents safely, and the hub post shows where the environment layer fits. Our guardrails overview covered worktrees in one section. This post goes deeper: the setup contract, cloud and CI behavior, and the isolation bugs that surfaced in parallel runs.

Agents fail at the environment first

A human who lands in a broken checkout notices and fixes it. An agent often does not stop. It improvises a fix, installs something on the host, or edits code to work around a missing extension. Two hours later the diff passes only in a setup nobody can reproduce.

Our early answer was a long setup section listing ports, hostnames, database names, and container configuration files. It did not hold: those facts differ per worktree, and an agent reconstructing them from prose will get one wrong. We moved that knowledge out of the agent’s context and into the repository, behind one command.

One command, one machine-readable contract

The entry point is a single command-line tool in the repository. It detects where it is running, calls the repository’s existing tooling in the right order (worktree scripts, build targets, containers, database tooling), and reports one machine-readable object on standard output. Progress goes to standard error so the output stays parseable. It orchestrates existing primitives rather than reimplementing them.

The agent-facing sequence is two steps: create the environment, then verify it. Creation is idempotent: each step is gated on its own check, so a second run skips whatever already passes. When verification exits zero, development can start. The corollary is the rule agents actually follow: do not implement until verification exits zero.

What the result carries

Every result has an overall status (ready, incomplete, failed, or destroyed), a boolean matching the exit code, the detected provider, the workspace location, the app URL and database names, and a capabilities summary saying whether this context has a database, services, an app URL, and can run the database-backed test suites. Each check has a severity, a status, an error identifier, and a remediation.

Failures carry stable identifiers for cases like an unreachable database, pending migrations, missing dependencies, an incompatible language runtime, or an unavailable container engine. The remediation for a missing database, for example, is to run creation again and then verify. Hence: follow the reported remediation instead of hand-assembling setup. An agent that improvises a container sequence misses the test database or targets the wrong one.

Developers run the same tool on a new laptop. We did not name it after agents; a human gets the same pass or fail answer.

Three providers, one contract

The tool picks a provider automatically; an explicit flag or setting wins.

ProviderWhere it appliesData plane
LocalA developer machine, or a hosted agent that has a reachable Docker daemonThe main checkout’s Docker stack
CloudA hosted agent without Docker, using the platform’s checkout as isNone (source-only profile)
CIA CI runner, with the runner’s checkoutJob service containers

One detection rule surprised us: a hosted agent that also has Docker gets the local provider, even when CI markers are present, so it gets the full Compose stack instead of a thin CI profile. Without Docker, it falls back to the source-only cloud profile. The choice is recorded on disk so later agent turns keep it, which mattered where setup-phase environment settings do not carry into the coding phase.

Degraded is a warning, not silence

A cloud checkout may have an older PHP runtime than the repository pins, or lack extensions the dependency manager needs. The tool skips the install, reports the skipped step, and raises a dependencies warning rather than installing an unusable tree. Failed optional checks become warnings: the environment is still ready, with reduced capabilities.

A cloud context has no Postgres, Redis, or queue, so database-backed suites are unavailable by construction, and the capabilities summary says so. Agents read that before promising to run something. A strict verification mode promotes every optional check to required, for jobs that need a hard gate. We would rather an agent say “this environment cannot run the integration suite” than find out three commits later.

One fallback is a trade-off. If a local bootstrap cannot obtain the base PHP image on a locked-down agent VM, creation falls back to the source-only cloud provider with a warning instead of failing outright. A flag makes that a hard failure.

Use wrappers, never host tools

The third rule is the one agents break most often: run PHP, dependency installs, and Node tooling only through the build tool or container wrappers, never bare host binaries.

PHP lives in the application container, and Node dependencies are built for a pinned Node image with Linux native dependencies, so host Node cannot be trusted to match. We provide no path shims, because a shim makes the wrong command look right. The sanctioned routes are a small set of build-tool targets (running the app console, installing dependencies, checking files, opening a shell) plus a wrapper for Node tooling. Host PHP is only for the source-only cloud profile, and a few tools, such as the headless smoke-test browser, are documented exceptions.

There is a trap even inside Docker. In a worktree, running a command directly inside a container, instead of through the sanctioned wrapper, can silently target the shared main database. The current database came back as the main one through that route and as the worktree’s own through the build-tool wrapper. Such a command looks completely fine.

Worktrees give each agent a sibling

For local work, isolation is a git worktree created as a sibling checkout of the main repository. A worktree gets its own application container and its own installed dependencies and built assets (seeded from main with copy-on-write clones, never symlinks, because Docker bind mounts do not follow out-of-tree links). It also gets per-slug state:

  • An app database and a test database named from the slug.
  • A Redis key prefix and a message-queue virtual host per worktree.
  • Its own session, remember-me, and trusted-device cookie names.
  • Its own URL, routed by hostname through the shared edge proxy.

It does not get its own database server. Postgres, Redis, the queue, and the mail catcher are shared, because duplicating them per agent makes parallel work too expensive to be routine. Isolation by names and namespaces on a shared server was the compromise.

A worktree is created before coding when another session may need the main checkout, when the task needs its own branch and database, or when someone is reviewing a branch that main should not leave. Creation runs from the main checkout with the interactive shell disabled; the agent then works only in the sibling path. A reviewer gets a checkout without a running stack (an idle one costs roughly 1.6 GiB); a running stack is opt in. Several reviewers on one pull request get an instance name so nothing collides. The setup command wraps all of this and then verifies it.

Keeping many worktrees cheap

Expensive isolation does not get used, so we added limits. Only the services a branch needs start by default: the queue worker only when the branch touches async-message code, the asset watcher only when it touches front-end files. A PHP-only stack is about 85 MiB. Starting a stack stops the least recently used ones once more than four others are running (stopped, never removed). Idle stacks stop after eight hours.

Postgres connections were the sharpest limit. Without pooling, each running worker held 15 to 25 real connections, so the stock limit of 100 ran out at about four stacks with workers. A shared pooler now fronts the main database, and a worker holds 4 server connections (measured, against 15 to 26 connecting directly).

Review workers get their own worktree

When an unattended supervisor runs our reviews, each review worker gets its own worktree for the pull request head and tears it down when it finishes. The exception is a finding with a recorded repro command: that worktree stays warm, so when the author pushes a fix we rerun the repro on the new head instead of building a stack from scratch. Warm workspaces are reaped when the pull request closes, after 24 hours idle, or beyond two kept. Each end-to-end review may bring up its own Docker stack, so the live-review cap is 2 by default. Raise it only with Docker memory headroom.

Isolation bugs real use surfaced

None of this was right the first time. These three bugs appeared only once agents and humans used worktrees concurrently.

A stale proxy block stopped the edge

Each worktree gets a generated route in the shared web proxy. The route named its worktree container literally, and the proxy resolves those names when it loads its configuration. A block for a container that no longer existed failed validation, which stopped the main edge from starting and failed every later worktree command. It happened after a worktree was removed with plain git, or after a stopped stack or reboot. The container is now resolved at request time, so a leftover block returns a gateway error on that worktree’s own hostnames instead of taking down the shared edge.

An uninitialized worktree changed main

Our container configuration pins the project name, which outranks the directory name. In a linked worktree that was never initialized, the start command recreated the main stack’s containers from that worktree’s files and the stop command stopped them, with no warning. The guard now detects an uninitialized linked worktree (its git metadata is a file, not a directory) and refuses, pointing at the initialization step.

Cookies leaked between worktrees

Worktrees shared a cookie domain, so every stack read and wrote the same remember-me and trusted-device cookies. The remember-me signature includes the password hash and a two-factor flag, and those drift between copied databases. The stack that disagreed rejected and deleted the cookie, logging the developer out everywhere once the session expired. The session cookie was already per worktree; the other two now are too.

None would show up in a design review, none is a model problem, and a prompt telling the agent to stay in its own worktree would not have changed any of them.

What we have not solved

Documented gaps: local creation still needs the developer’s Docker daemon running, and the tool cannot start it. Trusting the local certificate authority can need root, so unattended runs print the manual trust step instead of hanging. Our CI workflows are not yet migrated onto the CI provider, though a job can call the same create and verify pair.

Lessons

  1. Treat readiness as a command. A verify step that exits zero or does not is a gate agents cannot argue with.
  2. Put remediation in the output. Stable error codes plus a remediation keep agents from improvising.
  3. Report degraded environments honestly. A warning beats a silent partial install.
  4. Close the host-binary escape hatch. Wrappers only, and no shims that hide the mistake.
  5. Share the data plane, isolate the names. Per-worktree databases, key prefixes, and cookies keep parallel agents affordable.
  6. Budget for isolation bugs. Every leak came from real concurrent use and needed a regression test.

The environment contract also lets the rest of the factory stay small: our always-on instructions point at the setup command instead of describing setup, a large part of why they could shrink. Once an agent can prove its sandbox is sound, the next question is how much checking to demand.

All In Engineering
  • Engineering Oct 13, 2026

    How to Build an AI Software Factory

    An AI software factory is a pipeline where agents propose and deterministic gates and accountable humans dispose. Here is how we follow one change through seven stages.

  • Engineering Oct 13, 2026

    Browser Verification for AI Agents

    Passing tests do not prove a page works. Here is how we make AI agents open the real page, read the screenshot, and fix the browser path until proof is fast.

  • Engineering Oct 13, 2026

    AI Agent Dispatcher: Packets, Not Spawns

    Our ai agent dispatcher never starts sibling chats. It prints a copy-paste packet and keeps a ledger, while a separate supervisor runs bounded workers inside its own session.

  • Engineering Oct 13, 2026

    Compliance as an AI Agent Constraint

    Some product boundaries are too important for an agent's judgment. Here is how we encode them as ai agent compliance guardrails: status labels, a checklist, escalation by default, and a golden test.

Start trading at scale today. Sign up for free.

Free 7-day trial

Set-up in 3 minutes

Paper account for testing

TradersPost operates as a non-custodial automated trading platform, enabling users to connect alerts from their preferred trading platforms to their selected brokerage or exchange accounts. It abstains from the transmission, custody, or management of customer funds, covering both traditional and cryptocurrency assets. Typically, registration requirements set by regulatory entities such as the SEC, FINRA, or FinCEN apply to entities that hold or transmit customer funds. To ensure ongoing compliance, TradersPost regularly engages with regulatory authorities to confirm its adherence to all relevant local and federal laws.

TradersPost does not provide alerts, signals, research, analysis, or trading advice of any kind. It is designed to assist traders and investors in making their own trading decisions based on their alerts. The platform does not offer recommendations regarding securities to buy or sell, nor does it provide trading or investing advice. The platform and its features, capabilities, and tools are provided 'as-is' without any warranty.

Risk Disclosure: The use of automated trading systems involves inherent risks, including the potential for significant financial loss. These systems operate based on predetermined algorithms that may not fully adapt to changing market conditions, possibly making them unsuitable for some investors. Individuals are advised to thoroughly assess their financial situation and risk tolerance before using this platform.

Testimonials appearing on this website may not be representative of other clients or customers and is not a guarantee of future performance or success.

Broker, exchange, trading platform, company names, product names, service marks, trademarks, and logos appearing on this website are the property of their respective owners and are used solely to identify supported connections and technical compatibility. TradersPost is an independent third-party platform and is not affiliated with, endorsed by, sponsored by, or authorized by any of these organizations unless expressly stated. Technical compatibility does not imply a commercial partnership, sponsorship, endorsement, or authorization. See Important Disclosures for trademark information.

© 2026 TradersPost, Inc. All rights reserved.