Agents and human users have fundamentally different permission needs
When you grant SSH to a human, they know what resources they need; giving an AI Agent the same access is a different story.
Agent frameworks (LangGraph, AutoGen, Cursor Background Agent, etc.) inherit the full OS user permissions when executing tool calls.
An Agent asked to "find all TODO comments in the repo and compile them into a Markdown table" only needs read access to finish /workspace and write one output file,
but in practice it can also access ~/Library/Keychains, read your SSH private key directory, or exfiltrate data with curl.
Agents will not do this on purpose, but built-in wildcard shell tools or external plugins might—and you may not be at the screen when it happens.
Apple M4 makes this more important, not less. M4's 38 TOPS Neural Engine cuts local inference cost, so Agents on Mac run far more often than a year ago—and the risk window scales the same way. OpenClaw assumes Agents do not need Docker isolation (that breaks the full Xcode toolchain) or a fresh VM per task (too expensive); on real macOS it intercepts overreach at the syscall layer via a policy engine, and the policy file is plain YAML versioned in Git with your code.
Hardware: Mac mini M4 · 10-core CPU · 16 GB unified memory · 256 GB NVMe SSD · 1 Gbps dedicated bandwidth (VPSRox Singapore node).
OS: macOS 15 Sequoia. OpenClaw CLI 0.9.x, policy format v2.
Demo task: clone a public GitHub repo in the sandbox → scan TODO comments with rg → write a Markdown report; read/write only /workspace, no outbound network.
Entire flow over SSH; VNC not required.
Before you start: four prerequisites you cannot skip
Your local machine can be Windows, Linux, or macOS—as long as you have an SSH client. But all four items below must be ready before you start, or you will get stuck mid-flow.
M4 instance
from the console
instance-token
(template in Section 4)
M4 instance: not provisioned yet? Go to the order page, pick a node and term; after payment the instance is ready in 1–5 minutes, and SSH credentials appear under Access Info in the console. All five nodes (Singapore, Tokyo, Seoul, Hong Kong, US East) share the same hardware and pricing—choose by target network latency.
instance-token: generated when you first enable OpenClaw on Security & Sandbox in the console; shown only once. Store it immediately in your team secrets tool (1Password, Bitwarden, etc.). Once you leave the page, the original token cannot be viewed again— you can only rotate it on the same page (the old token becomes invalid immediately).
Enable OpenClaw in the console
OpenClaw is not enabled by default—each instance is controlled independently so workloads that do not need audit avoid extra overhead. The console path is short; confirm you see an enabled state on screen before moving on.
-
01
Open instance detail page
Log in to the VPSRox console and open the target instance detail page. Under the Security & Sandbox tab, find the OpenClaw toggle.
-
02
Enable and save instance-token
Click the enable switch; the page shows an
instance-token(formatoct-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx). Copy it to your secrets store before closing the dialog, confirm it is saved, then click I have saved it, continue. -
03
Confirm status shows Enabled
After the dialog closes, the OpenClaw section should show a green Enabled badge. If it still says Enabling after 30 seconds, refresh and check again. This is the only step that must be done in the browser.
CLI install and three health checks
After SSH login, install the OpenClaw CLI in one command. The installer detects macOS version and CPU architecture; on M4 it usually finishes in under 30 seconds.
curl -fsSL https://api.vpsrox.com/openclaw/install.sh | bash
openclaw auth login --token <instance-token>
openclaw status
openclaw status should return status for three components; each must be healthy before you continue:
| Component | Role | Expected status |
|---|---|---|
| Policy Engine | Parses YAML policies and decides before syscalls | healthy |
| Sandbox Runtime | Manages sandbox lifecycle, process isolation, and file mapping | healthy |
| Audit Bus | Writes all decision events asynchronously to persistent logs without blocking the main path | healthy |
All three green is necessary but not sufficient—Policy Engine healthy only means the engine process is up,
not that your YAML is valid. Policy validation is a separate step below.
If any item shows degraded or unavailable,
run openclaw doctor first; a common cause is the kernel extension waiting for approval—
open System Settings → Privacy & Security on the instance (SSH cannot do this; use VNC briefly).
Least-privilege YAML: line-by-line policy fields
The policy file defines what the Agent may and may not do in the sandbox. Principle: start strict, relax later—
the first YAML opens only the minimum paths the task needs; watch deny records in audit logs,
then widen as needed instead of starting loose and tightening later.
Below is a read-only template for clone a public repo → static scan → write report;
save it as ~/policies/quickstart-readonly.yaml.
apiVersion: openclaw.vpsrox.com/v2
kind: SandboxPolicy
metadata:
name: quickstart-readonly
spec:
filesystem:
allow:
- path: /workspace
access: [read, write] # Agent writes scan report here
deny:
- path: "**/Keychains/**" # block signing certificates
- path: "**/.ssh/**" # block private keys
- path: "**/Library/Cookies/**" # block browser session data
process:
allow: [git, rg, python3, zsh, bash]
network:
egress: deny-all # no outbound in quickstart mode
A few design choices matter. filesystem.deny overrides allow: even if /workspace is open read/write,
paths on the deny list stay blocked—the engine checks deny before allow regardless of order.
process.allow is an executable whitelist: only listed binaries can start;
if your Agent toolchain needs node or npm, add them or calls fail with E_POLICY_DENY: process.
network.egress: deny-all blocks even DNS on purpose for this demo,
so you see a deny record in audit logs and confirm the policy engine is active.
After writing your YAML, run validation to catch syntax errors before creating a sandbox:
openclaw policy validate -f ~/policies/quickstart-readonly.yaml
Expected output: policy valid (0 warnings). If paths conflict or field names are misspelled, validate reports the exact line number.
Run your first Agent task: create a sandbox and execute
Before wiring LangGraph or a custom framework, run a deterministic shell script through the full loop. Script behavior is predictable, so you can separate policy decisions from Agent logic— when something fails, you know whether to change policy or Agent code.
-
01
Create sandbox
openclaw sandbox create --name quickstart --policy ~/policies/quickstart-readonly.yaml
On success you get a sandbox ID and statusready. Creation is idempotent—running the same name again reports already exists instead of erroring. -
02
In another terminal, tail audit logs live
openclaw audit tail --sandbox quickstart --follow
Keep this window open—you want to watch Agent execution and audit records together. Each decision event usually appears within 50–200 ms after the Agent action. -
03
Run Agent entry script in the first terminal
Put the sample script below at
/workspace/agent-entry.sh(create on the host; the sandbox maps it automatically), then run inside the sandbox:
openclaw sandbox exec quickstart -- /bin/zsh /workspace/agent-entry.sh -
04
Stop sandbox after task
openclaw sandbox stop quickstart
After stop, workspace data stays on the host at/workspaceand remounts on the nextsandbox create. For full cleanup, add--rm.
#!/bin/zsh
set -euo pipefail
cd /workspace
# Attempt network — will be denied by policy (intentional demo)
git clone --depth 1 https://github.com/apple/swift-sample-code.git repo 2>/dev/null || echo "clone blocked (expected)"
rg -rn "TODO|FIXME" . --glob '*.swift' > scan-report.txt 2>/dev/null || true
echo "Scan complete: $(wc -l < scan-report.txt | tr -d ' ') matches" > summary.txt
cat summary.txt
With network.egress: deny-all, git clone is blocked by network policy and the script prints "clone blocked (expected)"—
that is intentional so audit logs get a decision: deny network event
for you to verify log structure in the next section. If the script reaches the rg step, /workspace filesystem permissions are correct.
On our M4 Singapore node the full script (including blocked clone) took about 2.3 seconds;
cumulative policy engine overhead stayed under 80 ms.
Reading audit logs: what each field means
Audit logs are what set OpenClaw apart from other sandbox options. They are not after-the-fact reports— they are a real-time event stream synchronized with policy decisions, viewable during a task or exported later. Each record has a fixed set of fields; understanding them is how you spot problems in the logs.
A typical allow record (file read) looks like this:
ts=2026-07-24T08:03:12.481Z
sandbox=quickstart
pid=8231
syscall=open
resource=filesystem
path=/workspace/agent-entry.sh
access=read
decision=allow
policy_rule=filesystem.allow[0]
latency_us=34
latency_us is microseconds the policy engine spent deciding; policy_rule points to the YAML rule index that triggered the decision,
so you can quickly see which allow or deny rule is in effect.
A deny record (network blocked) looks like this:
ts=2026-07-24T08:03:12.512Z
sandbox=quickstart
pid=8233
syscall=connect
resource=network
dst=140.82.113.4:443
decision=deny
policy_rule=network.egress.deny-all
latency_us=19
This record matches a blocked git clone in the Agent script.
dst=140.82.113.4:443 is GitHub's IP—you can add a precise allow rule:
set network.egress to allow-list and add github.com:443,
re-validate, then update the sandbox policy (openclaw sandbox update --name quickstart --policy ...)
without destroying and recreating the sandbox.
Common log query commands:
All deny records in the last hour: openclaw audit query --decision deny --since 1h.
Filter by path: openclaw audit query --resource filesystem --path "/workspace/**".
Export JSON (for SIEM or automation): openclaw audit export --sandbox quickstart --since 24h --format json > audit.json.
Six common errors and how to diagnose them
Almost everyone hits at least one of these on first setup. This table is ordered by how often each issue occurs; every row gives the root cause and the shortest fix—no need to dig through the full docs.
| Symptom | Root cause | Quickest fix |
|---|---|---|
auth login reports invalid token |
Leading/trailing spaces when copying, or token was rotated | Copy again from Security & Sandbox in the console; use pbpaste to confirm the clipboard has no extra characters |
openclaw status shows unavailable for one component |
Kernel extension awaiting user approval (first install) | Log in via VNC → System Settings → Privacy & Security → approve the OpenClaw system extension → restart the CLI service |
policy validate reports unknown field |
Misspelled YAML field name, or legacy v1 field names | Check that apiVersion is openclaw.vpsrox.com/v2; see the template in Section 5 of this article |
E_POLICY_DENY: filesystem |
Agent accessed a path outside the YAML allow list | openclaw audit query --decision deny --since 1h to find the target path, then add it to filesystem.allow as needed |
E_POLICY_DENY: process |
Agent invoked an executable outside the process.allow whitelist |
In audit logs, find deny records with resource=process and add the process name to the whitelist |
git clone times out inside the sandbox with no deny log |
DNS was blocked, but the request timed out before connect reached deny |
Add --verbose to see git output; add 8.8.8.8:53 to the YAML network allow list or use domain whitelist mode |
Treat instance-token like high-privilege instance credentials—do not put it in code comments, .env files, or Git commits.
For production with multiple people, configure per-member zero-trust device certificates and least-privilege roles (viewer / operator / admin) in the console
instead of sharing one instance-token.
From quick trial to a stable Agent workflow
A five-minute read-only sandbox proves the environment; production is more complex:
Agents calling xcodebuild (more processes and temp dirs), npm or PyPI (fine-grained egress allow lists),
or CI creating and destroying sandboxes per pull request (REST API or GitHub Actions integration).
The shared path: iterate policy from audit deny records, not from guessing with a loose policy upfront.
On a single Mac mini M4 · 16 GB unified memory, benchmarks show two xcodebuild sandboxes with DerivedData cache running stably in parallel,
with ~4 GB left for OpenClaw audit processes and system services. If Agent load grows,
VPSRox Thunderbolt 5 clustering links multiple Mac minis at 80 Gbps;
policy files stay per instance, and OpenClaw audit logs are stored per instance.
Teams without a dedicated cloud Mac often hit clear limits with common alternatives. Running Agents 24/7 on a dev laptop interferes with daily work; sustained load makes thermals worse; public macOS VMs (e.g. GitHub Actions hosted macOS runners) share pools, lack native OpenClaw integration, and queue delays hurt interactive Agent workflows; buying a Mac mini for the office adds depreciation, maintenance, and fixed public IP setup cost.
VPSRox offers dedicated physical Mac mini M4 (10-core CPU · 16 GB unified memory · 256 GB NVMe · 38 TOPS Neural Engine), OpenClaw built into every standard instance with no extra setup; five nodes (Singapore, Tokyo, Seoul, Hong Kong, US East) each with dedicated public IPv4 and 1 Gbps bandwidth, delivered in 1–5 minutes after payment, from $21.8/day. Rent daily while experimenting; switch to $109.1/month when stable—no contract, change term anytime.
A dedicated cloud Mac with OpenClaw built in for your AI Agent
VPSRox dedicated Mac mini M4 nodes ship with OpenClaw built in: policy engine + sandbox runtime + audit bus, ready out of the box with no self-hosted deploy. 16 GB unified memory and 38 TOPS Neural Engine let Agent inference run alongside macOS tooling; five global nodes with dedicated IPv4, daily rental with no contract lock-in.