Guide
Give your agent its own computer, not SSH to production
Give the agent a machine of its own instead of a shell on a production server. On Sanbox, that's a Computer whose network policy doesn't include any production host, whose only credential is a staging one held in a Secret Proxy, and which you snapshot before risky work. You review the diff it produces and ship it through your normal pipeline. The same pattern works anywhere: a separate machine, separate credentials, a separate network path and a human check before production.
Run this with your agent
Read https://sanbox.cloud/kb/security/agent-own-computer-not-ssh-to-production.md and follow it to set up a staging-only agent Computer.
If the Sanbox CLI is missing, install it with `npm install -g @sanlabs/sanbox-cli@latest`
and sign in with `sanbox login`. Show me each command before you create, stop or delete a Computer.
Why not a shell on production?
When an agent has a shell on a production server, any misunderstanding plays out on production: a request to restart a service can become changed mounts, removed containers or scripts nobody asked for. You can't fully control how a model reads an instruction, but you can control where its commands run.
What does "its own computer" need?
- No route to production. The egress allowlist leaves out every production host.
- No production credentials. The only key is a staging key, kept outside the machine.
- A restore point. A snapshot taken before the risky part.
- A human gate. You read the diff, and your CI and deploy process take it to production.
Steps
1. Write a network policy
List only what the work needs, and save it as staging-policy.json:
{
"default_action": "deny",
"rules": [
{ "destination": "registry.npmjs.org", "ports": [{ "from": 443, "to": 443 }], "description": "npm packages" },
{ "destination": "api.staging.example.com", "ports": [{ "from": 443, "to": 443 }], "description": "Staging API only" }
]
}
2. Store the staging token as a Secret Proxy
Save the settings, without the token, as proxy.json:
{
"name": "staging-api",
"host": "api.staging.example.com",
"authentication": { "type": "bearer" },
"attach_run_id": false
}
Then read the token from a private file outside the repository. Replace --all-paths with one --path per API path if the work needs only part of the API:
sanbox secret-proxies create --file proxy.json --secret-stdin --all-paths --json < ~/.config/staging-api-token
3. Create the template
Creating templates needs the admin or owner role. Pick the provider and model from the lists, then validate the template:
sanbox model-providers list --json
sanbox model-providers models <provider-id> --json
sanbox templates create --name "Staging agent" --type opencode-computer \
--model-provider <provider-id> --model <model-id> \
--network-policy staging-policy.json --secret-proxy staging-api --json
sanbox templates validate <template-id> --json
4. Start a Computer and copy in a clean checkout
Start the Computer and wait until runs get shows it running. Then clone your repository from its root and copy the clone in. A clone carries committed files and history only, so untracked files such as .env stay behind:
sanbox run --template <template-id> --json
sanbox runs get <run-id> --json
git clone . /tmp/app
sanbox cp /tmp/app <run-id>:/workspace
5. Snapshot it before the risky part
sanbox runs stop <run-id> --wait --json
sanbox snapshots create --run <run-id> --name app-before-change --wait
sanbox runs resume <run-id> --wait --json
You can also keep the stopped Computer as your restore point and do the work in a fork, which starts on its own: sanbox runs fork <run-id> --request-key <uuid> --wait --json.
6. Let the agent work
Use the console chat, or connect your own code with sanbox opencode connect <run-id> --expires 1h --json. Tell the agent that the staging API is the only service it can reach.
7. Review the diff
Look at the change before anything leaves the Computer, then copy it out as a patch:
sanbox exec <run-id> --cwd /workspace/app -- 'git add -A && git diff --cached --stat'
sanbox exec <run-id> --cwd /workspace/app -- 'git diff --cached > /workspace/change.patch'
sanbox cp <run-id>:/workspace/change.patch .
git apply --check change.patch
Apply the patch on a branch, open a pull request, and let your normal checks and deploy process take it from there.
8. Roll back if it went wrong
Start a fresh copy from the snapshot and delete the broken Computer:
sanbox runs stop <run-id> --wait --json
sanbox run --snapshot app-before-change --json
sanbox runs delete <run-id> --yes --json
Lock down egress
Check three things in the policy before you start:
- No production hostnames, including databases, admin panels and internal APIs.
- Separate staging hosts. If staging and production share a hostname, a host rule can't tell them apart. Give staging its own host.
- No inbound ports. Inbound access is off unless you add
--inbound-portto the template, and even then each caller needs a short-lived token.
What this doesn't do
- It doesn't make the change correct. Your review and your tests do that.
- Staging credentials are still credentials. The agent can do anything the staging token allows. Limit the Secret Proxy to the API paths the work needs, and keep real customer data out of staging.
- It doesn't help with work that has to happen on production, such as an actual reboot. Do that yourself, or through a runbook or pipeline a person approves.
- A snapshot restores the Computer, not the world. Anything the agent changed through the staging API stays changed.