Architecture Details

View as Markdown

NemoClaw combines a host CLI, an in-sandbox integration layer, and a versioned YAML blueprint that defines the sandbox image, policies, and inference profiles applied through OpenShell.

System Overview

NVIDIA OpenShell is a general-purpose agent runtime. It provides sandbox containers, a credential-storing gateway, inference proxying, and policy enforcement, but it has no opinions about what runs inside. NemoClaw is an opinionated reference stack built on OpenShell that handles what goes in the sandbox, prepares agent-specific integration, and makes the setup accessible.

Deployment Topology

The logical diagram above shows how components relate. This section shows what actually runs where on the host. NemoClaw’s default Docker-driver topology does not place the sandbox in an embedded k3s cluster. On Linux, NemoClaw configures and restarts the package-managed OpenShell gateway user service when it is installed, then creates the sandbox as a Docker container. NemoClaw treats that service as authoritative only when systemctl --user show openshell-gateway reports a package/vendor unit path and an openshell-gateway ExecStart. Per-user units, partial units, and user-manager or bus outages do not take over gateway ownership; NemoClaw falls back to the standalone gateway process used by earlier installs. That compatibility fallback remains until supported upgrade paths no longer include pre-service OpenShell installs and the package-managed handoff has direct nightly coverage. On Apple Silicon macOS, NemoClaw starts the OpenShell Docker-driver gateway and creates the sandbox as a Docker container. In both Docker-driver modes, the sandbox is a Docker container, not a Kubernetes pod. Entrypoint supervisors create the in-container /tmp/nemoclaw-gateway-local marker only when they actually launch an in-container gateway, and they normally keep it present while that supervisor is active. On normal exits, handled SIGTERM/SIGINT, startup failures, and shell errexit termination through the EXIT trap, the supervisor removes the marker on a best-effort basis so the Docker health check does not keep trusting a stale gateway PID. Terminal runtimes may not write it. NemoClaw does not treat sandbox environment hints such as OPENSHELL_DRIVERS as authoritative for gateway ownership. Legacy non-Docker-driver installs still use the k3s-based gateway path. In that topology, the openshell-cluster-nemoclaw container runs an embedded k3s cluster that includes the OpenShell gateway, an agent-sandbox-controller workload, and a Kubernetes custom resource definition named sandboxes.agents.x-k8s.io. Each NemoClaw sandbox appears as a Sandbox custom resource in the openshell namespace, and the controller reconciles that resource into the corresponding agent pod. For example, kubectl get sandboxes.agents.x-k8s.io -n openshell inside the legacy cluster container lists the sandbox resources, and kubectl describe pod -n openshell <sandbox-pod> reports Controlled By: Sandbox/<name>. That Kubernetes resource path is a legacy implementation detail of the non-Docker-driver gateway, and it is not present in the default Docker-driver topology.

The diagram below shows the standard Docker-driver topology.

Layering from top to bottom:

LayerRuns asRole
Host CLIHost process (nemoclaw on Node.js)Orchestrates OpenShell via openshell CLI calls.
OpenShell gatewayHost process by default; optional Linux compatibility container when the gateway binary needs a newer host ABIHosts the credential store, owns sandbox lifecycle coordination, and provides the L7 proxy.
Docker daemonHost serviceRuns the Docker-driver sandbox container and, on affected Linux hosts, the optional gateway compatibility container.
Sandbox containerDocker containerRuns the selected compatible agent and NemoClaw integration under Landlock + seccomp + netns.
OpenShell L7 proxyGateway processIntercepts agent egress and rewrites Authorization headers (Bearer/Bot) and URL-path segments to inject the real credential at the network boundary.

NemoClaw never gives the sandbox a raw provider key. At onboard time it registers credentials with OpenShell’s provider/placeholder system, and the L7 proxy substitutes the real value into outbound requests at egress. The CLI helper isInferenceRouteReady (in src/lib/onboard.ts) is a host-side readiness check used by the resume flow to decide whether the active route already covers the chosen provider and model. It is not a runtime component.

For the DGX Spark-specific variant of this topology (cgroup v2, aarch64, unified memory), refer to the NVIDIA Spark playbook.

NemoClaw Agent Integration

NemoClaw integrates with each supported agent through a runtime layer that adapts the agent to OpenShell-managed providers, policies, and sandbox state. The concrete files differ by agent because each runtime has its own plugin system, config format, state layout, and startup command.

AgentIntegration filesRuntime behavior
OpenClawnemoclaw/openclaw.plugin.json, nemoclaw/src/runtime-context.ts, and the TypeScript package under nemoclaw/src/Registers the /nemoclaw slash command, adds the NemoClaw inference provider, and injects sandbox and policy context into OpenClaw turns.

The OpenClaw integration is a thin TypeScript plugin that runs in-process with the OpenClaw gateway inside the sandbox. Its durable entry points are nemoclaw/src/index.ts, nemoclaw/src/runtime-context.ts, and nemoclaw/openclaw.plugin.json. The nemoclaw/src/commands/ directory contains in-sandbox /nemoclaw command handlers and migration helpers. The nemoclaw/src/blueprint/ directory contains runner, state, snapshot, SSRF, and private-network validation code. Before an OpenClaw turn starts, the plugin prepends a short system-context block with the active sandbox name, sandbox phase, network policy summary, and filesystem policy summary. This guidance stays out of the visible chat transcript. When the policy or phase changes during a session, the plugin sends a smaller update block instead of repeating the full context. The context tells the agent to try allowed network and filesystem operations before reporting them unavailable, and to distinguish policy denials from DNS, timeout, TLS, or filesystem errors.

NemoClaw Blueprint

The blueprint is a versioned YAML package with its own release stream. The runner resolves, verifies, and applies the blueprint through the OpenShell CLI. The blueprint defines the sandbox shape, default policies, and inference profiles; the runner performs the OpenShell operations.

nemoclaw-blueprint/
ā”œā”€ā”€ blueprint.yaml Manifest: version, profiles, compatibility
ā”œā”€ā”€ model-specific-setup/ Agent-scoped model/provider compatibility manifests
ā”œā”€ā”€ router/ Model Router config and routing engine
ā”œā”€ā”€ policies/
│ └── presets/ Shared policy presets

The default OpenClaw policy starts from nemoclaw-blueprint/policies/openclaw-sandbox.yaml.

The current blueprint runner implementation lives in the nemoclaw/ TypeScript package:

nemoclaw/src/blueprint/
ā”œā”€ā”€ runner.ts CLI runner: plan / apply / status / rollback
ā”œā”€ā”€ ssrf.ts SSRF endpoint validation (IP + DNS checks)
ā”œā”€ā”€ private-networks.ts Shared private-network block list loader for SSRF checks
ā”œā”€ā”€ snapshot.ts Migration snapshot / restore lifecycle
ā”œā”€ā”€ state.ts Persistent run state management

Blueprint Lifecycle

  1. Resolve. The integration layer locates the blueprint artifact and checks the version against the OpenShell and agent runtime constraints in blueprint.yaml.
  2. Verify. The integration layer checks the artifact digest against the expected value.
  3. Plan. The runner determines what OpenShell resources to create or update, such as the gateway, providers, sandbox, inference route, and policy.
  4. Apply. The runner executes the plan by calling openshell CLI commands.
  5. Status. The runner reports current state.

Sandbox Environment

Normal NemoClaw onboarding builds from the ghcr.io/nvidia/nemoclaw/sandbox-base base image and layers the NemoClaw runtime Dockerfile on top. The direct blueprint runner still carries a pinned OpenShell Community OpenClaw image for legacy openshell sandbox create --from compatibility. Inside the sandbox:

  • The selected compatible agent runs with the NemoClaw integration layer installed or generated for that agent.
  • Inference calls are routed through OpenShell to the configured provider.
  • Network egress is restricted by the baseline policy for the selected agent profile.
  • Filesystem access is confined to /sandbox and /tmp for read-write access, with system paths read-only.
  • NemoClaw injects sandbox and policy context into agent turns when the selected agent supports runtime context hooks, so the agent can attempt allowed actions and report policy blocks or infrastructure failures accurately.
  • The image exposes a Docker health check that probes the in-sandbox gateway, so container runtimes can report whether the agent service is responding.
  • The image includes common runtime compatibility helpers such as Homebrew and a python to python3 symlink for tools that still invoke python.

Inference Routing

Inference requests from the agent never leave the sandbox directly. OpenShell intercepts them and routes them to the configured provider:

Compatible agent (sandbox) ──▶ OpenShell gateway ──▶ Provider endpoint

When you select the Model Router provider, the OpenShell gateway routes to a host-side router process instead of a single upstream model. The router selects from the configured pool, then calls the upstream NVIDIA endpoint with the credential held outside the sandbox.

Some model and provider combinations need agent-specific compatibility setup. NemoClaw keeps those declarations under nemoclaw-blueprint/model-specific-setup/<agent>/ so fixes for each supported agent can be tested and reviewed independently.

Refer to Choose an Inference Provider for provider configuration details.

Provider Credential Storage

Provider credentials live in the OpenShell gateway store, not on the host filesystem. NemoClaw never writes them to host disk. The OpenShell L7 proxy injects values at egress. Refer to Credential Storage for the inspection, rotation, and migration flow.

Host-Side State and Config

NemoClaw keeps non-secret operator-facing state on the host rather than inside the sandbox.

PathPurpose
~/.nemoclaw/sandboxes.jsonRegistered sandbox metadata for the default gateway port, including the default sandbox selection.
~/.nemoclaw/gateways/<port>/Segregated host state root (its own registry, snapshots, and legacy credential-migration files) for a non-default NEMOCLAW_GATEWAY_PORT. On upgrade, rows and related state move out of the legacy shared root only when their recorded gateway identity matches the selected port. Provider credentials remain in the OpenShell gateway store. The default gateway port uses the top-level ~/.nemoclaw/ location, so existing single-gateway hosts are unchanged.
~/.openclaw/openclaw.jsonHost OpenClaw configuration that NemoClaw snapshots or restores during migration flows.

The following environment variables configure optional services and local access.

VariablePurpose
NEMOCLAW_GATEWAY_PORTOptional host-side gateway port override for an independent OpenShell gateway and port-scoped NemoClaw state root. Supported for OpenClaw, Hermes, and Deep Agents.
TELEGRAM_BOT_TOKENTelegram bot token you provide before nemoclaw onboard. OpenShell stores it in a provider; the sandbox receives placeholders, not the raw secret.
TELEGRAM_ALLOWED_IDSComma-separated Telegram user or chat IDs for allowlists when onboarding applies channel restrictions.
TELEGRAM_GROUP_POLICYOpenClaw Telegram group access policy: open by default, allowlist to require explicit group entries, or disabled to turn off OpenClaw group access. Hermes ignores this value.
SLACK_BOT_TOKENSlack bot token (xoxb-...) you provide before nemoclaw onboard. Stored as an OpenShell provider; never passed directly to the sandbox.
SLACK_APP_TOKENSlack app-level token (xapp-...) required for Socket Mode. Stored alongside SLACK_BOT_TOKEN during onboarding.
SLACK_ALLOWED_USERSComma-separated Slack member IDs for DM and channel @mention user allowlisting.
SLACK_ALLOWED_CHANNELSComma-separated Slack channel IDs where channel @mention events are enabled (e.g. C012AB3CD,C987ZY6XW). Baked into the sandbox image at build time. Combine with SLACK_ALLOWED_USERS to restrict both channel and member.
CHAT_UI_URLURL for the optional chat UI endpoint.
NEMOCLAW_DISABLE_DEVICE_AUTHBuild-time-only toggle that disables gateway device pairing when set to 1 before the sandbox image is created.

For normal setup and reconfiguration, prefer nemoclaw onboard over editing these files by hand. Do not treat NEMOCLAW_DISABLE_DEVICE_AUTH as a runtime setting for an already-created sandbox.