NemoClaw Policy Cookbook
A NemoClaw policy is a network egress rule, not a content filter. NemoClaw runs your agent inside an NVIDIA OpenShell sandbox with deny-by-default egress, so the sandbox can open a connection only to hosts named in its policy, and the provider API key never enters the sandbox at all. You change policy with the nemoclaw <sandbox> policy add command or by editing the blueprint YAML.
:::note What changed on this page
An earlier version of this cookbook described NemoClaw as a Colang policy sidecar that intercepts every LLM call, deployed from ghcr.io/openclaw/nemoclaw and keyed off an X-OpenClaw-User header. All three were wrong. Rewritten 2026-09-09 against NVIDIA's NemoClaw architecture reference and OpenClaw's trusted-proxy auth docs, both fetched that day. If you want Colang if/then rules, see the last section.
:::
What does a NemoClaw policy actually control?
NemoClaw is three pieces: a Node.js host CLI, a runtime adapter that injects sandbox context into the agent, and a versioned blueprint of sandbox images, security policies and inference profiles (architecture reference, verified 2026-09-09). Nothing in that list sits in the request path as a rule engine deciding whether a prompt is allowed.
NVIDIA describes the enforcement as "deny-by-default security controls across five layers" (security posture, verified 2026-09-09):
| Layer | Mechanism | What it stops |
|---|---|---|
| Network | Deny-by-default egress policy | Unauthorised outbound connections, exfiltration |
| Filesystem | Landlock LSM plus container mounts; writes limited to /sandbox and /tmp | Binary tampering, credential theft, config edits |
| Process | Container runtime security context, seccomp | Privilege escalation, fork bombs, syscall abuse |
| Gateway auth | Device and client authorisation at onboarding | Unauthorised clients reaching the OpenShell gateway |
| Inference | Requests routed through inference.local | The agent ever receiving the real provider API key |
That last row is the design decision worth understanding before you write any policy. Credentials are registered with OpenShell's placeholder system at onboarding. The gateway then runs an L7 egress proxy that, in NVIDIA's words, "intercepts agent egress and rewrites Authorization headers (Bearer/Bot) and URL-path segments to inject the real credential at the network boundary." The sandbox holds a placeholder. A compromised agent can spend your API budget, but it cannot walk off with the key.
Which policy tier should you pick at onboarding?
Onboarding asks you to choose one of four tiers. They differ only in which presets are pre-applied on top of the same baseline (network policies reference, verified 2026-09-09).
| Tier | Presets applied on top of baseline | Use it when |
|---|---|---|
| Restricted | None | The agent only calls inference and reads its own docs |
| Balanced (default) | npm, pypi, huggingface, brew, brave, optional tavily | The agent installs packages or runs web search |
| Open | Balanced plus messaging, weather, productivity and public-reference APIs | Internal automation with a wide integration surface |
| Personal | Mandatory personal-open-internet, permitting TCP to public and private ranges on ports 80 and 443 | You have accepted that egress control is off |
Personal is not a slightly looser Balanced. It allows outbound 80/443 to private address ranges too, which means the sandbox can reach your LAN, and connections matching those ports skip the approval prompt entirely. Pick Restricted and add presets one at a time. Set NEMOCLAW_POLICY_TIER if you are onboarding non-interactively.
What can a fresh sandbox reach?
Every tier starts from the same five baseline endpoint groups, all enforced at port 443:
| Group | Endpoint | Purpose |
|---|---|---|
nvidia | integrate.api.nvidia.com:443 | Inference and model listings |
clawhub | clawhub.ai:443 | OpenClaw and Node package management |
openclaw_api | openclaw.ai:443 | OpenClaw API services |
openclaw_docs | docs.openclaw.ai:443 | Documentation, GET only |
npm_registry | registry.npmjs.org:443 | npm registry, GET only |
GitHub is not on that list. NVIDIA says so explicitly: "GitHub access (github.com, api.github.com) is not included in the baseline policy." This is the first thing that breaks for most people, because an agent that can install from npm but cannot clone a repository looks like a broken agent rather than a working policy.
How do you open access for GitHub, Slack or Jira?
Presets are named bundles of host rules. The pattern is the same for all of them (integration policy examples, verified 2026-09-09):
- Preview what a preset would open, without applying it:
The dry run prints the host and port entries. This is the only way to see them; the docs describe the presets by purpose, not by host list.nemoclaw my-assistant policy add github --dry-run
- Apply it:
nemoclaw my-assistant policy add github --yes
- Confirm what is now in force, and remove anything you added by mistake:
nemoclaw my-assistant policy listnemoclaw my-assistant policy remove github
Slack needs a second step, because a network rule alone does not give the agent a channel. Run nemoclaw my-assistant channels add slack first, supply the bot and app tokens as environment variables, then nemoclaw my-assistant policy add slack --yes.
The jira preset is the one to read closely before you trust it. NVIDIA notes that it "intentionally allows Node.js access to Atlassian Cloud and does not allow curl". A skill that shells out to curl against Jira will fail under a policy that a reasonable person would assume covers Jira. Presets are scoped by process as well as by host.
For a private host that no preset covers, load rules from a custom preset file. NVIDIA's instruction is to run it with --dry-run first, review the generated address pins and the binary, method, path, port and access limits, then rerun the same command without --dry-run (customize the network policy, verified 2026-09-09):
nemoclaw my-assistant policy add --from-file ./policies/internal.yaml \
--trusted-private-host db.internal.example.com --dry-run
--trusted-private-host belongs to custom presets applied with --from-file or --from-dir, not to the built-in presets. NVIDIA's own instruction is to rehearse it first: "pass --trusted-private-host <exact-host-or-ip> --dry-run and review the generated address pins plus the binary, method, path, port, and access limits before applying the same command without --dry-run" (Customize the Sandbox Network Policy, verified 2026-09-09). The full YAML schema lives in the OpenShell policy schema reference, which is the document to read before hand-writing rules.
How do you approve a blocked request while the agent is running?
When the agent reaches for a host that is not on the policy, OpenShell blocks the connection and logs the attempt rather than failing silently. You approve or deny from the terminal UI (approve network requests, verified 2026-09-09):
- Run
openshell termon the host, or SSH in first for a remote box. - Select the running sandbox with
j/k, then Enter. - Press
rto focus the Network Rules panel. Blocked requests show up as pending entries. - Press
ato approve one,xto reject it, orAto approve all pending rules.
Two traps live in that workflow. The first is that approvals do not survive a rebuild: they "reset to the baseline when you destroy and recreate the sandbox," so anything you want permanently has to become a preset or a blueprint edit. The second is scope. NVIDIA's own residual-risk list warns that "approving a broad domain (such as a CDN that hosts arbitrary content)" means "the agent can fetch anything from that domain." Approving a CDN to unblock one JavaScript file is how a deny-by-default policy quietly becomes an allow-list of one entry that means everything.
How do you scope per-user permissions?
This is not a NemoClaw setting. Per-user identity belongs to the OpenClaw gateway, and the header carrying that identity is configurable rather than fixed. Set gateway.auth.trustedProxy.userHeader to match whatever your reverse proxy actually sends (OpenClaw trusted-proxy auth, verified 2026-09-09):
| Proxy | Documented header |
|---|---|
| Caddy with OAuth | x-forwarded-user |
| Traefik | x-forwarded-user |
| nginx + oauth2-proxy | x-auth-request-email |
| Pomerium | x-pomerium-claim-email |
There is no header named X-OpenClaw-User in the current docs. There is an x-openclaw-scopes header, but it declares operator scopes rather than identity, and on Control UI WebSocket upgrades it acts only as a cap on the negotiated session scopes, not as a grant.
Scopes are assigned by identity in the gateway config:
{
gateway: {
bind: "lan",
trustedProxies: ["10.0.0.1", "172.17.0.1"],
auth: {
mode: "trusted-proxy",
identityScopes: {
"admin@company.org": ["operator.admin"],
},
trustedProxy: {
userHeader: "x-forwarded-user",
requiredHeaders: ["x-forwarded-proto", "x-forwarded-host"],
allowUsers: ["nick@example.com", "admin@company.org"],
allowLoopback: false,
},
},
},
}
The proxy has to strip or overwrite client-supplied identity headers. OpenClaw's docs are blunt about why: "required headers alone do not distinguish the proxy from another local process," and any local process able to reach the gateway can impersonate a loopback reverse proxy by sending identity headers. Keep trustedProxies to your actual proxy IPs. Not the subnet.
While you are in that file: OpenClaw ships date-based releases such as v2026.7.1. Any guide that gates a feature on a semantic version like 2.4.0 is describing a release that does not exist.
What does NemoClaw not protect against?
The security posture page is unusually candid, and it is the part of the docs most worth reading before you tell a compliance reviewer that the agent is sandboxed.
- Prompt injection. The page documents no defence against it, and sandboxing is not one. A prompt-injected agent still holds every permission you granted it.
- Agent config as a boundary. The generated config tree holds model routing, channel settings and integration state, and NemoClaw "supports this state as mutable, so the agent can change it independently of host-managed policy."
- Anything launched outside the managed path. "Network policy and inference auth are not enforced when an agent runtime is launched outside the NemoClaw-managed gateway path."
- Encoded secrets. Content scanning does not detect base64 or hex-encoded secrets.
- Raw filesystem writes. Scanners "can intercept agent tool calls, not arbitrary raw filesystem writes" such as shell redirection.
- Cost. An unattended agent with inference access can accumulate spend. Nothing in the policy layer caps it.
Sandbox confinement is a blast-radius control. It answers "what can this process reach if it turns hostile," not "is this request appropriate." For regulated data the controls you still owe separately are infrastructure encryption, physical access, workforce training and a BAA with every vendor in the path, which is what the HIPAA-ready OpenClaw deployment guide covers. A BAA with your host does not extend to Anthropic, OpenAI or NVIDIA.
Can you run NemoClaw on a VPS?
Yes, within limits. NVIDIA's prerequisites (verified 2026-09-09):
| Resource | Minimum | Recommended |
|---|---|---|
| CPU | 4 vCPU | 4+ vCPU |
| RAM | 8 GB | 16 GB |
| Disk | 20 GB free | 40 GB free |
Ubuntu 24.04 is the validated Linux target; other distributions "may work but are not validated." You need Docker Engine, Docker Desktop or Colima, or rootless Podman on qualified paths. Native Windows is unsupported, WSL2 only. No GPU appears in the prerequisites, because the default profile does not do local inference.
That last point sets the honest boundary on the word "sandboxed." The baseline policy allows integrate.api.nvidia.com:443, so out of the box your prompts leave the machine and go to NVIDIA. The sandbox constrains what the agent process can touch; it does not keep your data on the box. If keeping data local is the actual requirement, you need the local-inference preset pointed at Ollama or vLLM through the host gateway, and hardware to match, which is a different budget from the 8 GB above.
What if you wanted Colang if/then rules?
Then you want a different NVIDIA project. NeMo Guardrails is the one with Colang, the English-like DSL where you define user, define bot and define flow to shape what a model will and will not answer. It sits around the model call. NemoClaw sits around the process. They are complementary and neither substitutes for the other.
Running both is reasonable for a regulated deployment: NemoClaw to bound what the agent can reach, NeMo Guardrails to bound what the conversation can contain. If you only need one, start with the layer that matches your threat. Data leaving the box is a NemoClaw problem. A model answering the wrong question is a Guardrails problem.
If neither is your problem and you just want a self-hosted assistant on a VPS you control, plain OpenClaw behind an authenticating reverse proxy is less machinery to maintain. The comparison of OpenClaw, NemoClaw and Hermes sets out where each one stops being worth its overhead, and what NemoClaw is covers installation and the blueprint in more depth than this cookbook does.
No. NemoClaw enforces network, filesystem, process, gateway and inference controls, and NVIDIA's security posture page documents no prompt-injection or content-filtering defence. Content-level rules are a separate product, NeMo Guardrails. Verified against docs.nvidia.com on 2026-09-09.
No. NVIDIA states that approved endpoints remain in the running policy for that sandbox instance and reset to the baseline when you destroy and recreate it. To keep an approval, apply a preset with nemoclaw <name> policy add, or edit nemoclaw-blueprint/policies/openclaw-sandbox.yaml and rerun onboarding.
No. Credentials are registered with OpenShell's placeholder system at onboarding, and the gateway's L7 egress proxy rewrites Authorization headers to inject the real credential at the network boundary. The sandbox holds a placeholder. The agent can still spend the budget, so set provider-side spend limits separately.
Whichever one you configure. Set gateway.auth.trustedProxy.userHeader to match your proxy: x-forwarded-user for Caddy or Traefik, x-auth-request-email for nginx with oauth2-proxy, x-pomerium-claim-email for Pomerium. There is no fixed X-OpenClaw-User header in the current OpenClaw docs.
Because it is not in the baseline policy. NVIDIA lists five baseline endpoint groups: integrate.api.nvidia.com, clawhub.ai, openclaw.ai, docs.openclaw.ai and registry.npmjs.org, and states that github.com and api.github.com are excluded. Run nemoclaw <name> policy add github --yes to allow it.
Common mistakes and fixes
Sandbox containers cannot reach the gateway at host.openshell.internal:8080.
A host firewall is blocking the Docker bridge. Read the bridge subnet with `docker network inspect openshell-docker` and allow it to reach port 8080/tcp, which is what the ufw one-liner on NVIDIA's troubleshooting reference does. Apply the exact command the installer prints for your host rather than a hand-typed subnet.
An endpoint you approved at runtime is blocked again after a rebuild.
Runtime approvals are session-scoped. NVIDIA states approved endpoints 'reset to the baseline when you destroy and recreate the sandbox'. Make an approval permanent by applying a preset (nemoclaw <name> policy add <preset>) or by editing nemoclaw-blueprint/policies/openclaw-sandbox.yaml and rerunning onboarding.
Per-user restrictions are not taking effect.
Per-user identity is an OpenClaw gateway setting, not a NemoClaw one, and the header name is configurable rather than fixed. Set gateway.auth.trustedProxy.userHeader to whatever your proxy actually sends (x-forwarded-user for Caddy or Traefik, x-auth-request-email for nginx + oauth2-proxy, x-pomerium-claim-email for Pomerium), then grant scopes with gateway.auth.identityScopes.