9.2 KiB
Run OpenCode with NVIDIA Inference
This tutorial walks through a realistic setup where you run opencode inside a NemoClaw sandbox with inference routed to NVIDIA API endpoints. Along the way, you will hit policy problems, diagnose them from logs, write a custom policy, and configure inference routing. This is the full policy iteration loop.
What you will learn:
- Creating a provider manually with
--from-existing - Writing a custom policy to replace the defaults
- Reading sandbox logs to diagnose denied actions
- The difference between agent traffic and userland inference
- Setting up inference routes for code running inside the sandbox
Prerequisites
Before you begin:
NVIDIA_API_KEYenvironment variable set on your host machine with a valid NVIDIA API key- NemoClaw CLI installed (
pip install nemoclaw)
Step 1: Create the Provider
Unlike the Claude Code tutorial where the CLI auto-discovered credentials, here you create a provider explicitly. This gives you control over the provider name and type.
$ nemoclaw provider create --name nvidia --type nvidia --from-existing
The --from-existing flag tells the CLI to discover credentials from your local environment. It finds NVIDIA_API_KEY and stores it securely. The provider is now available to attach to any sandbox.
Verify the provider:
$ nemoclaw provider list
Step 2: Create the Sandbox
Create a sandbox with the NVIDIA provider attached and opencode as the startup command:
$ nemoclaw sandbox create --name opencode-sandbox --provider nvidia --keep -- opencode
The --keep flag keeps the sandbox alive after you exit, which you will need for the iteration steps ahead. The CLI creates the sandbox with the default policy, injects the NVIDIA credentials, and starts opencode.
Step 3: Hit a Problem
Try using opencode inside the sandbox. You will likely find that calls to NVIDIA inference endpoints fail or behave unexpectedly. The default policy is designed around Claude Code, not opencode.
Open a second terminal and check the logs:
$ nemoclaw sandbox logs opencode-sandbox --tail
Or launch the NemoClaw Terminal for a live view:
$ nemoclaw term
Look for lines like these in the output:
action=deny host=integrate.api.nvidia.com binary=/usr/local/bin/opencode reason="no matching network policy"
action=deny host=opencode.ai binary=/usr/bin/node reason="no matching network policy"
action=inspect_for_inference host=integrate.api.nvidia.com binary=/bin/bash
These log entries tell you exactly what the policy blocks and why.
Step 4: Understand Why
The default policy has a nvidia_inference network policy entry, but it is configured for a narrow set of binaries, typically /usr/local/bin/claude and /usr/bin/node. If opencode makes HTTP calls through a different binary (its own binary, curl, or a shell subprocess), those connections do not match any policy rule and get denied.
There are two separate problems:
- OpenCode's own traffic. opencode contacts
opencode.aifor its API andintegrate.api.nvidia.comfor inference. Neither of these endpoints has a matching policy entry for the binaries opencode uses. - No opencode.ai endpoint. The default policy has no entry for
opencode.aiat all. Even if the binary matched, the destination is not listed.
This is the expected behavior. NemoClaw denies by default. You need to write a policy that explicitly allows what opencode needs.
Step 5: Write a Custom Policy
Create a file called opencode-policy.yaml with the following content:
version: 1
inference:
allowed_routes:
- nvidia
filesystem_policy:
include_workdir: true
read_only:
- /usr
- /lib
- /proc
- /dev/urandom
- /app
- /etc
- /var/log
read_write:
- /sandbox
- /tmp
- /dev/null
landlock:
compatibility: best_effort
process:
run_as_user: sandbox
run_as_group: sandbox
network_policies:
opencode_api:
name: opencode-api
endpoints:
- host: opencode.ai
port: 443
protocol: rest
tls: terminate
enforcement: enforce
access: full
binaries:
- path: /usr/local/bin/opencode
- path: /usr/bin/node
nvidia_inference:
name: nvidia-inference
endpoints:
- host: integrate.api.nvidia.com
port: 443
protocol: rest
tls: terminate
enforcement: enforce
access: full
binaries:
- path: /usr/local/bin/opencode
- path: /usr/bin/node
- path: /usr/bin/curl
- path: /bin/bash
npm_registry:
name: npm-registry
endpoints:
- host: registry.npmjs.org
port: 443
binaries:
- path: /usr/bin/npm
- path: /usr/bin/node
- path: /usr/local/bin/npm
- path: /usr/local/bin/node
github_rest_api:
name: github-rest-api
endpoints:
- host: api.github.com
port: 443
protocol: rest
tls: terminate
enforcement: enforce
access: read-only
binaries:
- path: /usr/local/bin/opencode
- path: /usr/bin/node
- path: /usr/bin/gh
github_ssh_over_https:
name: github-ssh-over-https
endpoints:
- host: github.com
port: 443
protocol: rest
tls: terminate
enforcement: enforce
rules:
- allow:
method: GET
path: "/**/info/refs*"
- allow:
method: POST
path: "/**/git-upload-pack"
binaries:
- path: /usr/bin/git
Compared to the default policy, this adds:
opencode_api: allows opencode and Node.js to reachopencode.ai:443- Broader
nvidia_inferencebinaries: adds/usr/local/bin/opencode,/usr/bin/curl, and/bin/bashso opencode's subprocesses can reach the NVIDIA endpoint inference.allowed_routes: includesnvidiaso inference routing works for userland code- GitHub access scoped for opencode's git operations
:::{warning}
The filesystem_policy, landlock, and process sections are static. They are set at sandbox creation time and cannot be changed on a running sandbox. If you need to modify these, you must delete and recreate the sandbox. The network_policies and inference sections are dynamic and can be hot-reloaded.
:::
Step 6: Push the Policy
Apply your custom policy to the running sandbox:
$ nemoclaw sandbox policy set opencode-sandbox --policy opencode-policy.yaml --wait
The --wait flag blocks until the sandbox confirms the policy is loaded. You will see output indicating success or failure.
Verify the policy revision was accepted:
$ nemoclaw sandbox policy list opencode-sandbox
The latest revision should show status loaded.
Step 7: Set Up Inference Routing
So far, you have allowed the opencode agent to reach integrate.api.nvidia.com directly through network policy. But what about code that opencode writes and runs inside the sandbox? If that code calls an LLM API, it goes through the privacy router: a separate mechanism.
Create an inference route so userland code can access NVIDIA models:
$ nemoclaw inference create \
--routing-hint nvidia \
--base-url https://integrate.api.nvidia.com \
--model-id z-ai/glm5 \
--api-key $NVIDIA_API_KEY
The policy you wrote in Step 5 already includes nvidia in inference.allowed_routes, so you do not need to push a policy update. If you had not included it, you would add it to the policy and push again:
$ nemoclaw sandbox policy set opencode-sandbox --policy opencode-policy.yaml --wait
:::{note} The network policies control which hosts the agent binary can reach directly. The inference routes control where LLM API calls from userland code (scripts, notebooks, applications the agent writes) get routed. These are two separate enforcement points. :::
Step 8: Verify
Tail the logs again:
$ nemoclaw sandbox logs opencode-sandbox --tail
You should no longer see action=deny lines for the endpoints you added. Connections to opencode.ai, integrate.api.nvidia.com, and GitHub should show action=allow.
If you still see denials, read the log line carefully. It tells you the exact host, port, and binary that was blocked. Add the missing entry to your policy and push again. This observe-modify-push cycle is the policy iteration loop, and it is the normal workflow for getting a new tool running in NemoClaw.
Clean Up
When you are done:
$ nemoclaw sandbox delete opencode-sandbox
Next Steps
- {doc}
../../safety-and-privacy/policies: Full reference on policy YAML structure, static and dynamic fields, and enforcement modes - {doc}
../../safety-and-privacy/network-access-rules: How the proxy evaluates network rules, L4 and L7 inspection, and TLS termination - {doc}
../../inference/index: Inference route configuration, protocol detection, and transparent rerouting - {doc}
../../sandboxes/providers: Provider types, credential discovery, and manual and automatic creation - {doc}
../../safety-and-privacy/security-model: The four protection layers and how they interact